Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ d9bce9d9

History | View | Annotate | Download (34.4 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
#define MEMSUFFIX _raw
23
#include "op_helper_mem.h"
24
#if !defined(CONFIG_USER_ONLY)
25
#define MEMSUFFIX _user
26
#include "op_helper_mem.h"
27
#define MEMSUFFIX _kernel
28
#include "op_helper_mem.h"
29
#endif
30

    
31
//#define DEBUG_OP
32
//#define DEBUG_EXCEPTIONS
33
//#define DEBUG_SOFTWARE_TLB
34
//#define FLUSH_ALL_TLBS
35

    
36
/*****************************************************************************/
37
/* Exceptions processing helpers */
38
void cpu_loop_exit (void)
39
{
40
    longjmp(env->jmp_env, 1);
41
}
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 EXCP_PROGRAM:
50
        if (error_code == 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
/*****************************************************************************/
67
/* Registers load and stores */
68
void do_load_cr (void)
69
{
70
    T0 = (env->crf[0] << 28) |
71
        (env->crf[1] << 24) |
72
        (env->crf[2] << 20) |
73
        (env->crf[3] << 16) |
74
        (env->crf[4] << 12) |
75
        (env->crf[5] << 8) |
76
        (env->crf[6] << 4) |
77
        (env->crf[7] << 0);
78
}
79

    
80
void do_store_cr (uint32_t mask)
81
{
82
    int i, sh;
83

    
84
    for (i = 0, sh = 7; i < 8; i++, sh --) {
85
        if (mask & (1 << sh))
86
            env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
87
    }
88
}
89

    
90
void do_load_xer (void)
91
{
92
    T0 = (xer_so << XER_SO) |
93
        (xer_ov << XER_OV) |
94
        (xer_ca << XER_CA) |
95
        (xer_bc << XER_BC) |
96
        (xer_cmp << XER_CMP);
97
}
98

    
99
void do_store_xer (void)
100
{
101
    xer_so = (T0 >> XER_SO) & 0x01;
102
    xer_ov = (T0 >> XER_OV) & 0x01;
103
    xer_ca = (T0 >> XER_CA) & 0x01;
104
    xer_cmp = (T0 >> XER_CMP) & 0xFF;
105
    xer_bc = (T0 >> XER_BC) & 0x7F;
106
}
107

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

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

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

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

    
179
/*****************************************************************************/
180
/* Fixed point operations helpers */
181
#if defined(TARGET_PPC64)
182
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
183
{
184
    *plow += a;
185
    /* carry test */
186
    if (*plow < a)
187
        (*phigh)++;
188
    *phigh += b;
189
}
190

    
191
static void neg128 (uint64_t *plow, uint64_t *phigh)
192
{
193
    *plow = ~ *plow;
194
    *phigh = ~ *phigh;
195
    add128(plow, phigh, 1, 0);
196
}
197

    
198
static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
199
{
200
    uint32_t a0, a1, b0, b1;
201
    uint64_t v;
202

    
203
    a0 = a;
204
    a1 = a >> 32;
205

    
206
    b0 = b;
207
    b1 = b >> 32;
208
    
209
    v = (uint64_t)a0 * (uint64_t)b0;
210
    *plow = v;
211
    *phigh = 0;
212

    
213
    v = (uint64_t)a0 * (uint64_t)b1;
214
    add128(plow, phigh, v << 32, v >> 32);
215

    
216
    v = (uint64_t)a1 * (uint64_t)b0;
217
    add128(plow, phigh, v << 32, v >> 32);
218

    
219
    v = (uint64_t)a1 * (uint64_t)b1;
220
    *phigh += v;
221
#if defined(DEBUG_MULDIV)
222
    printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
223
           a, b, *phigh, *plow);
224
#endif
225
}
226

    
227
void do_mul64 (uint64_t *plow, uint64_t *phigh)
228
{
229
    mul64(plow, phigh, T0, T1);
230
}
231

    
232
static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
233
{
234
    int sa, sb;
235
    sa = (a < 0);
236
    if (sa)
237
        a = -a;
238
    sb = (b < 0);
239
    if (sb)
240
        b = -b;
241
    mul64(plow, phigh, a, b);
242
    if (sa ^ sb) {
243
        neg128(plow, phigh);
244
    }
245
}
246

    
247
void do_imul64 (uint64_t *plow, uint64_t *phigh)
248
{
249
    imul64(plow, phigh, T0, T1);
250
}
251
#endif
252

    
253
void do_adde (void)
254
{
255
    T2 = T0;
256
    T0 += T1 + xer_ca;
257
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
258
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
259
        xer_ca = 0;
260
    } else {
261
        xer_ca = 1;
262
    }
263
}
264

    
265
#if defined(TARGET_PPC64)
266
void do_adde_64 (void)
267
{
268
    T2 = T0;
269
    T0 += T1 + xer_ca;
270
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
271
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
272
        xer_ca = 0;
273
    } else {
274
        xer_ca = 1;
275
    }
276
}
277
#endif
278

    
279
void do_addmeo (void)
280
{
281
    T1 = T0;
282
    T0 += xer_ca + (-1);
283
    if (likely(!((uint32_t)T1 &
284
                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
285
        xer_ov = 0;
286
    } else {
287
        xer_so = 1;
288
        xer_ov = 1;
289
    }
290
    if (likely(T1 != 0))
291
        xer_ca = 1;
292
}
293

    
294
#if defined(TARGET_PPC64)
295
void do_addmeo_64 (void)
296
{
297
    T1 = T0;
298
    T0 += xer_ca + (-1);
299
    if (likely(!((uint64_t)T1 &
300
                 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
301
        xer_ov = 0;
302
    } else {
303
        xer_so = 1;
304
        xer_ov = 1;
305
    }
306
    if (likely(T1 != 0))
307
        xer_ca = 1;
308
}
309
#endif
310

    
311
void do_divwo (void)
312
{
313
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
314
                 (int32_t)T1 == 0))) {
315
        xer_ov = 0;
316
        T0 = (int32_t)T0 / (int32_t)T1;
317
    } else {
318
        xer_so = 1;
319
        xer_ov = 1;
320
        T0 = (-1) * ((uint32_t)T0 >> 31);
321
    }
322
}
323

    
324
#if defined(TARGET_PPC64)
325
void do_divdo (void)
326
{
327
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1ULL) ||
328
                 (int64_t)T1 == 0))) {
329
        xer_ov = 0;
330
        T0 = (int64_t)T0 / (int64_t)T1;
331
    } else {
332
        xer_so = 1;
333
        xer_ov = 1;
334
        T0 = (-1ULL) * ((uint64_t)T0 >> 63);
335
    }
336
}
337
#endif
338

    
339
void do_divwuo (void)
340
{
341
    if (likely((uint32_t)T1 != 0)) {
342
        xer_ov = 0;
343
        T0 = (uint32_t)T0 / (uint32_t)T1;
344
    } else {
345
        xer_so = 1;
346
        xer_ov = 1;
347
        T0 = 0;
348
    }
349
}
350

    
351
#if defined(TARGET_PPC64)
352
void do_divduo (void)
353
{
354
    if (likely((uint64_t)T1 != 0)) {
355
        xer_ov = 0;
356
        T0 = (uint64_t)T0 / (uint64_t)T1;
357
    } else {
358
        xer_so = 1;
359
        xer_ov = 1;
360
        T0 = 0;
361
    }
362
}
363
#endif
364

    
365
void do_mullwo (void)
366
{
367
    int64_t res = (int64_t)T0 * (int64_t)T1;
368

    
369
    if (likely((int32_t)res == res)) {
370
        xer_ov = 0;
371
    } else {
372
        xer_ov = 1;
373
        xer_so = 1;
374
    }
375
    T0 = (int32_t)res;
376
}
377

    
378
#if defined(TARGET_PPC64)
379
void do_mulldo (void)
380
{
381
    int64_t th;
382
    uint64_t tl;
383

    
384
    do_imul64(&tl, &th);
385
    if (likely(th == 0)) {
386
        xer_ov = 0;
387
    } else {
388
        xer_ov = 1;
389
        xer_so = 1;
390
    }
391
    T0 = (int64_t)tl;
392
}
393
#endif
394

    
395
void do_nego (void)
396
{
397
    if (likely((int32_t)T0 != INT32_MIN)) {
398
        xer_ov = 0;
399
        T0 = -(int32_t)T0;
400
    } else {
401
        xer_ov = 1;
402
        xer_so = 1;
403
    }
404
}
405

    
406
#if defined(TARGET_PPC64)
407
void do_nego_64 (void)
408
{
409
    if (likely((int64_t)T0 != INT64_MIN)) {
410
        xer_ov = 0;
411
        T0 = -(int64_t)T0;
412
    } else {
413
        xer_ov = 1;
414
        xer_so = 1;
415
    }
416
}
417
#endif
418

    
419
void do_subfe (void)
420
{
421
    T0 = T1 + ~T0 + xer_ca;
422
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
423
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
424
        xer_ca = 0;
425
    } else {
426
        xer_ca = 1;
427
    }
428
}
429

    
430
#if defined(TARGET_PPC64)
431
void do_subfe_64 (void)
432
{
433
    T0 = T1 + ~T0 + xer_ca;
434
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
435
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
436
        xer_ca = 0;
437
    } else {
438
        xer_ca = 1;
439
    }
440
}
441
#endif
442

    
443
void do_subfmeo (void)
444
{
445
    T1 = T0;
446
    T0 = ~T0 + xer_ca - 1;
447
    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
448
                 (1UL << 31)))) {
449
        xer_ov = 0;
450
    } else {
451
        xer_so = 1;
452
        xer_ov = 1;
453
    }
454
    if (likely((uint32_t)T1 != UINT32_MAX))
455
        xer_ca = 1;
456
}
457

    
458
#if defined(TARGET_PPC64)
459
void do_subfmeo_64 (void)
460
{
461
    T1 = T0;
462
    T0 = ~T0 + xer_ca - 1;
463
    if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
464
                 (1ULL << 63)))) {
465
        xer_ov = 0;
466
    } else {
467
        xer_so = 1;
468
        xer_ov = 1;
469
    }
470
    if (likely((uint64_t)T1 != UINT64_MAX))
471
        xer_ca = 1;
472
}
473
#endif
474

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

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

    
513
/* shift right arithmetic helper */
514
void do_sraw (void)
515
{
516
    int32_t ret;
517

    
518
    if (likely(!(T1 & 0x20UL))) {
519
        if (likely((uint32_t)T1 != 0)) {
520
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
521
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
522
                xer_ca = 0;
523
            } else {
524
                xer_ca = 1;
525
            }
526
        } else {
527
            ret = T0;
528
            xer_ca = 0;
529
        }
530
    } else {
531
        ret = (-1) * ((uint32_t)T0 >> 31);
532
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
533
            xer_ca = 0;
534
        } else {
535
            xer_ca = 1;
536
        }
537
    }
538
    T0 = ret;
539
}
540

    
541
#if defined(TARGET_PPC64)
542
void do_srad (void)
543
{
544
    int64_t ret;
545

    
546
    if (likely(!(T1 & 0x40UL))) {
547
        if (likely((uint64_t)T1 != 0)) {
548
            ret = (int64_t)T0 >> (T1 & 0x3FUL);
549
            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
550
                xer_ca = 0;
551
            } else {
552
                xer_ca = 1;
553
            }
554
        } else {
555
            ret = T0;
556
            xer_ca = 0;
557
        }
558
    } else {
559
        ret = (-1) * ((uint64_t)T0 >> 63);
560
        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
561
            xer_ca = 0;
562
        } else {
563
            xer_ca = 1;
564
        }
565
    }
566
    T0 = ret;
567
}
568
#endif
569

    
570
static inline int popcnt (uint32_t val)
571
{
572
    int i;
573

    
574
    for (i = 0; val != 0;)
575
        val = val ^ (val - 1);
576

    
577
    return i;
578
}
579

    
580
void do_popcntb (void)
581
{
582
    uint32_t ret;
583
    int i;
584

    
585
    ret = 0;
586
    for (i = 0; i < 32; i += 8)
587
        ret |= popcnt((T0 >> i) & 0xFF) << i;
588
    T0 = ret;
589
}
590

    
591
#if defined(TARGET_PPC64)
592
void do_popcntb_64 (void)
593
{
594
    uint64_t ret;
595
    int i;
596

    
597
    ret = 0;
598
    for (i = 0; i < 64; i += 8)
599
        ret |= popcnt((T0 >> i) & 0xFF) << i;
600
    T0 = ret;
601
}
602
#endif
603

    
604
/*****************************************************************************/
605
/* Floating point operations helpers */
606
void do_fctiw (void)
607
{
608
    union {
609
        double d;
610
        uint64_t i;
611
    } p;
612

    
613
    /* XXX: higher bits are not supposed to be significant.
614
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
615
     */
616
    p.i = float64_to_int32(FT0, &env->fp_status);
617
    p.i |= 0xFFF80000ULL << 32;
618
    FT0 = p.d;
619
}
620

    
621
void do_fctiwz (void)
622
{
623
    union {
624
        double d;
625
        uint64_t i;
626
    } p;
627

    
628
    /* XXX: higher bits are not supposed to be significant.
629
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
630
     */
631
    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
632
    p.i |= 0xFFF80000ULL << 32;
633
    FT0 = p.d;
634
}
635

    
636
void do_fnmadd (void)
637
{
638
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
639
    FT0 = float64_add(FT0, FT2, &env->fp_status);
640
    if (likely(!isnan(FT0)))
641
        FT0 = float64_chs(FT0);
642
}
643

    
644
void do_fnmsub (void)
645
{
646
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
647
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
648
    if (likely(!isnan(FT0)))
649
        FT0 = float64_chs(FT0);
650
}
651

    
652
void do_fsqrt (void)
653
{
654
    FT0 = float64_sqrt(FT0, &env->fp_status);
655
}
656

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

    
664
    if (likely(isnormal(FT0))) {
665
        FT0 = float32_div(1.0, FT0, &env->fp_status);
666
    } else {
667
        p.d = FT0;
668
        if (p.i == 0x8000000000000000ULL) {
669
            p.i = 0xFFF0000000000000ULL;
670
        } else if (p.i == 0x0000000000000000ULL) {
671
            p.i = 0x7FF0000000000000ULL;
672
        } else if (isnan(FT0)) {
673
            p.i = 0x7FF8000000000000ULL;
674
        } else if (FT0 < 0.0) {
675
            p.i = 0x8000000000000000ULL;
676
        } else {
677
            p.i = 0x0000000000000000ULL;
678
        }
679
        FT0 = p.d;
680
    }
681
}
682

    
683
void do_frsqrte (void)
684
{
685
    union {
686
        double d;
687
        uint64_t i;
688
    } p;
689

    
690
    if (likely(isnormal(FT0) && FT0 > 0.0)) {
691
        FT0 = float64_sqrt(FT0, &env->fp_status);
692
        FT0 = float32_div(1.0, FT0, &env->fp_status);
693
    } else {
694
        p.d = FT0;
695
        if (p.i == 0x8000000000000000ULL) {
696
            p.i = 0xFFF0000000000000ULL;
697
        } else if (p.i == 0x0000000000000000ULL) {
698
            p.i = 0x7FF0000000000000ULL;
699
        } else if (isnan(FT0)) {
700
            if (!(p.i & 0x0008000000000000ULL))
701
                p.i |= 0x000FFFFFFFFFFFFFULL;
702
        } else if (FT0 < 0) {
703
            p.i = 0x7FF8000000000000ULL;
704
        } else {
705
            p.i = 0x0000000000000000ULL;
706
        }
707
        FT0 = p.d;
708
    }
709
}
710

    
711
void do_fsel (void)
712
{
713
    if (FT0 >= 0)
714
        FT0 = FT1;
715
    else
716
        FT0 = FT2;
717
}
718

    
719
void do_fcmpu (void)
720
{
721
    if (likely(!isnan(FT0) && !isnan(FT1))) {
722
        if (float64_lt(FT0, FT1, &env->fp_status)) {
723
            T0 = 0x08UL;
724
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
725
            T0 = 0x04UL;
726
        } else {
727
            T0 = 0x02UL;
728
        }
729
    } else {
730
        T0 = 0x01UL;
731
        env->fpscr[4] |= 0x1;
732
        env->fpscr[6] |= 0x1;
733
    }
734
    env->fpscr[3] = T0;
735
}
736

    
737
void do_fcmpo (void)
738
{
739
    env->fpscr[4] &= ~0x1;
740
    if (likely(!isnan(FT0) && !isnan(FT1))) {
741
        if (float64_lt(FT0, FT1, &env->fp_status)) {
742
            T0 = 0x08UL;
743
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
744
            T0 = 0x04UL;
745
        } else {
746
            T0 = 0x02UL;
747
        }
748
    } else {
749
        T0 = 0x01UL;
750
        env->fpscr[4] |= 0x1;
751
        if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
752
            /* Quiet NaN case */
753
            env->fpscr[6] |= 0x1;
754
            if (!(env->fpscr[1] & 0x8))
755
                env->fpscr[4] |= 0x8;
756
        } else {
757
            env->fpscr[4] |= 0x8;
758
        }
759
    }
760
    env->fpscr[3] = T0;
761
}
762

    
763
#if !defined (CONFIG_USER_ONLY)
764
void do_rfi (void)
765
{
766
    env->nip = (target_ulong)(env->spr[SPR_SRR0] & ~0x00000003);
767
    T0 = (target_ulong)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
768
    do_store_msr(env, T0);
769
#if defined (DEBUG_OP)
770
    dump_rfi();
771
#endif
772
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
773
}
774

    
775
#if defined(TARGET_PPC64)
776
void do_rfi_32 (void)
777
{
778
    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
779
    T0 = (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
780
    do_store_msr(env, T0);
781
#if defined (DEBUG_OP)
782
    dump_rfi();
783
#endif
784
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
785
}
786
#endif
787
#endif
788

    
789
void do_tw (int flags)
790
{
791
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
792
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
793
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
794
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
795
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01)))))
796
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
797
}
798

    
799
#if defined(TARGET_PPC64)
800
void do_td (int flags)
801
{
802
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
803
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
804
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
805
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
806
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
807
        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
808
}
809
#endif
810

    
811
/* Instruction cache invalidation helper */
812
void do_icbi (void)
813
{
814
    uint32_t tmp;
815
    /* Invalidate one cache line :
816
     * PowerPC specification says this is to be treated like a load
817
     * (not a fetch) by the MMU. To be sure it will be so,
818
     * do the load "by hand".
819
     */
820
    tmp = ldl_kernel((uint32_t)T0);
821
    T0 &= ~(ICACHE_LINE_SIZE - 1);
822
    tb_invalidate_page_range((uint32_t)T0, (uint32_t)(T0 + ICACHE_LINE_SIZE));
823
}
824

    
825
#if defined(TARGET_PPC64)
826
void do_icbi_64 (void)
827
{
828
    uint64_t tmp;
829
    /* Invalidate one cache line :
830
     * PowerPC specification says this is to be treated like a load
831
     * (not a fetch) by the MMU. To be sure it will be so,
832
     * do the load "by hand".
833
     */
834
    tmp = ldq_kernel((uint64_t)T0);
835
    T0 &= ~(ICACHE_LINE_SIZE - 1);
836
    tb_invalidate_page_range((uint64_t)T0, (uint64_t)(T0 + ICACHE_LINE_SIZE));
837
}
838
#endif
839

    
840
/*****************************************************************************/
841
/* PowerPC 601 specific instructions (POWER bridge) */
842
void do_POWER_abso (void)
843
{
844
    if ((uint32_t)T0 == INT32_MIN) {
845
        T0 = INT32_MAX;
846
        xer_ov = 1;
847
        xer_so = 1;
848
    } else {
849
        T0 = -T0;
850
        xer_ov = 0;
851
    }
852
}
853

    
854
void do_POWER_clcs (void)
855
{
856
    switch (T0) {
857
    case 0x0CUL:
858
        /* Instruction cache line size */
859
        T0 = ICACHE_LINE_SIZE;
860
        break;
861
    case 0x0DUL:
862
        /* Data cache line size */
863
        T0 = DCACHE_LINE_SIZE;
864
        break;
865
    case 0x0EUL:
866
        /* Minimum cache line size */
867
        T0 = ICACHE_LINE_SIZE < DCACHE_LINE_SIZE ?
868
            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
869
        break;
870
    case 0x0FUL:
871
        /* Maximum cache line size */
872
        T0 = ICACHE_LINE_SIZE > DCACHE_LINE_SIZE ?
873
            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
874
        break;
875
    default:
876
        /* Undefined */
877
        break;
878
    }
879
}
880

    
881
void do_POWER_div (void)
882
{
883
    uint64_t tmp;
884

    
885
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
886
        T0 = (long)((-1) * (T0 >> 31));
887
        env->spr[SPR_MQ] = 0;
888
    } else {
889
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
890
        env->spr[SPR_MQ] = tmp % T1;
891
        T0 = tmp / (int32_t)T1;
892
    }
893
}
894

    
895
void do_POWER_divo (void)
896
{
897
    int64_t tmp;
898

    
899
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
900
        T0 = (long)((-1) * (T0 >> 31));
901
        env->spr[SPR_MQ] = 0;
902
        xer_ov = 1;
903
        xer_so = 1;
904
    } else {
905
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
906
        env->spr[SPR_MQ] = tmp % T1;
907
        tmp /= (int32_t)T1;
908
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
909
            xer_ov = 1;
910
            xer_so = 1;
911
        } else {
912
            xer_ov = 0;
913
        }
914
        T0 = tmp;
915
    }
916
}
917

    
918
void do_POWER_divs (void)
919
{
920
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
921
        T0 = (long)((-1) * (T0 >> 31));
922
        env->spr[SPR_MQ] = 0;
923
    } else {
924
        env->spr[SPR_MQ] = T0 % T1;
925
        T0 = (int32_t)T0 / (int32_t)T1;
926
    }
927
}
928

    
929
void do_POWER_divso (void)
930
{
931
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
932
        T0 = (long)((-1) * (T0 >> 31));
933
        env->spr[SPR_MQ] = 0;
934
        xer_ov = 1;
935
        xer_so = 1;
936
    } else {
937
        T0 = (int32_t)T0 / (int32_t)T1;
938
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
939
        xer_ov = 0;
940
    }
941
}
942

    
943
void do_POWER_dozo (void)
944
{
945
    if ((int32_t)T1 > (int32_t)T0) {
946
        T2 = T0;
947
        T0 = T1 - T0;
948
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
949
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
950
            xer_so = 1;
951
            xer_ov = 1;
952
        } else {
953
            xer_ov = 0;
954
        }
955
    } else {
956
        T0 = 0;
957
        xer_ov = 0;
958
    }
959
}
960

    
961
void do_POWER_maskg (void)
962
{
963
    uint32_t ret;
964

    
965
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
966
        ret = -1;
967
    } else {
968
        ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
969
            (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
970
        if ((uint32_t)T0 > (uint32_t)T1)
971
            ret = ~ret;
972
    }
973
    T0 = ret;
974
}
975

    
976
void do_POWER_mulo (void)
977
{
978
    uint64_t tmp;
979

    
980
    tmp = (uint64_t)T0 * (uint64_t)T1;
981
    env->spr[SPR_MQ] = tmp >> 32;
982
    T0 = tmp;
983
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
984
        xer_ov = 1;
985
        xer_so = 1;
986
    } else {
987
        xer_ov = 0;
988
    }
989
}
990

    
991
#if !defined (CONFIG_USER_ONLY)
992
void do_POWER_rac (void)
993
{
994
#if 0
995
    mmu_ctx_t ctx;
996

997
    /* We don't have to generate many instances of this instruction,
998
     * as rac is supervisor only.
999
     */
1000
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
1001
        T0 = ctx.raddr;
1002
#endif
1003
}
1004

    
1005
void do_POWER_rfsvc (void)
1006
{
1007
    env->nip = env->lr & ~0x00000003UL;
1008
    T0 = env->ctr & 0x0000FFFFUL;
1009
    do_store_msr(env, T0);
1010
#if defined (DEBUG_OP)
1011
    dump_rfi();
1012
#endif
1013
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1014
}
1015

    
1016
/* PowerPC 601 BAT management helper */
1017
void do_store_601_batu (int nr)
1018
{
1019
    do_store_ibatu(env, nr, (uint32_t)T0);
1020
    env->DBAT[0][nr] = env->IBAT[0][nr];
1021
    env->DBAT[1][nr] = env->IBAT[1][nr];
1022
}
1023
#endif
1024

    
1025
/*****************************************************************************/
1026
/* 602 specific instructions */
1027
/* mfrom is the most crazy instruction ever seen, imho ! */
1028
/* Real implementation uses a ROM table. Do the same */
1029
#define USE_MFROM_ROM_TABLE
1030
void do_op_602_mfrom (void)
1031
{
1032
    if (likely(T0 < 602)) {
1033
#if defined(USE_MFROM_ROM_TABLE)
1034
#include "mfrom_table.c"
1035
        T0 = mfrom_ROM_table[T0];
1036
#else
1037
        double d;
1038
        /* Extremly decomposed:
1039
         *                    -T0 / 256
1040
         * T0 = 256 * log10(10          + 1.0) + 0.5
1041
         */
1042
        d = T0;
1043
        d = float64_div(d, 256, &env->fp_status);
1044
        d = float64_chs(d);
1045
        d = exp10(d); // XXX: use float emulation function
1046
        d = float64_add(d, 1.0, &env->fp_status);
1047
        d = log10(d); // XXX: use float emulation function
1048
        d = float64_mul(d, 256, &env->fp_status);
1049
        d = float64_add(d, 0.5, &env->fp_status);
1050
        T0 = float64_round_to_int(d, &env->fp_status);
1051
#endif
1052
    } else {
1053
        T0 = 0;
1054
    }
1055
}
1056

    
1057
/*****************************************************************************/
1058
/* Embedded PowerPC specific helpers */
1059
void do_405_check_ov (void)
1060
{
1061
    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1062
               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1063
        xer_ov = 0;
1064
    } else {
1065
        xer_ov = 1;
1066
        xer_so = 1;
1067
    }
1068
}
1069

    
1070
void do_405_check_sat (void)
1071
{
1072
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1073
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1074
        /* Saturate result */
1075
        if (T2 >> 31) {
1076
            T0 = INT32_MIN;
1077
        } else {
1078
            T0 = INT32_MAX;
1079
        }
1080
    }
1081
}
1082

    
1083
#if !defined(CONFIG_USER_ONLY)
1084
void do_4xx_rfci (void)
1085
{
1086
    env->nip = env->spr[SPR_40x_SRR2];
1087
    T0 = env->spr[SPR_40x_SRR3] & ~0xFFFF0000;
1088
    do_store_msr(env, T0);
1089
#if defined (DEBUG_OP)
1090
    dump_rfi();
1091
#endif
1092
    env->interrupt_request = CPU_INTERRUPT_EXITTB;
1093
}
1094

    
1095
void do_4xx_load_dcr (int dcrn)
1096
{
1097
    target_ulong val;
1098
    
1099
    if (unlikely(env->dcr_read == NULL))
1100
        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
1101
    else if (unlikely((*env->dcr_read)(env->dcr_env, dcrn, &val) != 0))
1102
        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
1103
    else
1104
        T0 = val;
1105
}
1106

    
1107
void do_4xx_store_dcr (int dcrn)
1108
{
1109
    if (unlikely(env->dcr_write == NULL))
1110
        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
1111
    else if (unlikely((*env->dcr_write)(env->dcr_env, dcrn, T0) != 0))
1112
        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
1113
}
1114

    
1115
void do_load_403_pb (int num)
1116
{
1117
    T0 = env->pb[num];
1118
}
1119

    
1120
void do_store_403_pb (int num)
1121
{
1122
    if (likely(env->pb[num] != T0)) {
1123
        env->pb[num] = T0;
1124
        /* Should be optimized */
1125
        tlb_flush(env, 1);
1126
    }
1127
}
1128
#endif
1129

    
1130
/* 440 specific */
1131
void do_440_dlmzb (void)
1132
{
1133
    target_ulong mask;
1134
    int i;
1135

    
1136
    i = 1;
1137
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1138
        if ((T0 & mask) == 0)
1139
            goto done;
1140
        i++;
1141
    }
1142
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1143
        if ((T1 & mask) == 0)
1144
            break;
1145
        i++;
1146
    }
1147
 done:
1148
    T0 = i;
1149
}
1150

    
1151
/*****************************************************************************/
1152
/* Softmmu support */
1153
#if !defined (CONFIG_USER_ONLY)
1154

    
1155
#define MMUSUFFIX _mmu
1156
#define GETPC() (__builtin_return_address(0))
1157

    
1158
#define SHIFT 0
1159
#include "softmmu_template.h"
1160

    
1161
#define SHIFT 1
1162
#include "softmmu_template.h"
1163

    
1164
#define SHIFT 2
1165
#include "softmmu_template.h"
1166

    
1167
#define SHIFT 3
1168
#include "softmmu_template.h"
1169

    
1170
/* try to fill the TLB and return an exception if error. If retaddr is
1171
   NULL, it means that the function was called in C code (i.e. not
1172
   from generated code or from helper.c) */
1173
/* XXX: fix it to restore all registers */
1174
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
1175
{
1176
    TranslationBlock *tb;
1177
    CPUState *saved_env;
1178
    target_phys_addr_t pc;
1179
    int ret;
1180

    
1181
    /* XXX: hack to restore env in all cases, even if not called from
1182
       generated code */
1183
    saved_env = env;
1184
    env = cpu_single_env;
1185
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1186
    if (unlikely(ret != 0)) {
1187
        if (likely(retaddr)) {
1188
            /* now we have a real cpu fault */
1189
            pc = (target_phys_addr_t)retaddr;
1190
            tb = tb_find_pc(pc);
1191
            if (likely(tb)) {
1192
                /* the PC is inside the translated code. It means that we have
1193
                   a virtual CPU fault */
1194
                cpu_restore_state(tb, env, pc, NULL);
1195
            }
1196
        }
1197
        do_raise_exception_err(env->exception_index, env->error_code);
1198
    }
1199
    env = saved_env;
1200
}
1201

    
1202
/* TLB invalidation helpers */
1203
void do_tlbia (void)
1204
{
1205
    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
1206
        ppc6xx_tlb_invalidate_all(env);
1207
    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
1208
        /* XXX: TODO */
1209
#if 0
1210
        ppcbooke_tlb_invalidate_all(env);
1211
#endif
1212
    } else {
1213
        tlb_flush(env, 1);
1214
    }
1215
}
1216

    
1217
void do_tlbie (void)
1218
{
1219
    T0 = (uint32_t)T0;
1220
#if !defined(FLUSH_ALL_TLBS)
1221
    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
1222
        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
1223
        if (env->id_tlbs == 1)
1224
            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
1225
    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
1226
        /* XXX: TODO */
1227
#if 0
1228
        ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
1229
                                     env->spr[SPR_BOOKE_PID]);
1230
#endif
1231
    } else {
1232
        /* tlbie invalidate TLBs for all segments */
1233
        T0 &= TARGET_PAGE_MASK;
1234
        T0 &= ~((target_ulong)-1 << 28);
1235
        /* XXX: this case should be optimized,
1236
         * giving a mask to tlb_flush_page
1237
         */
1238
        tlb_flush_page(env, T0 | (0x0 << 28));
1239
        tlb_flush_page(env, T0 | (0x1 << 28));
1240
        tlb_flush_page(env, T0 | (0x2 << 28));
1241
        tlb_flush_page(env, T0 | (0x3 << 28));
1242
        tlb_flush_page(env, T0 | (0x4 << 28));
1243
        tlb_flush_page(env, T0 | (0x5 << 28));
1244
        tlb_flush_page(env, T0 | (0x6 << 28));
1245
        tlb_flush_page(env, T0 | (0x7 << 28));
1246
        tlb_flush_page(env, T0 | (0x8 << 28));
1247
        tlb_flush_page(env, T0 | (0x9 << 28));
1248
        tlb_flush_page(env, T0 | (0xA << 28));
1249
        tlb_flush_page(env, T0 | (0xB << 28));
1250
        tlb_flush_page(env, T0 | (0xC << 28));
1251
        tlb_flush_page(env, T0 | (0xD << 28));
1252
        tlb_flush_page(env, T0 | (0xE << 28));
1253
        tlb_flush_page(env, T0 | (0xF << 28));
1254
    }
1255
#else
1256
    do_tlbia();
1257
#endif
1258
}
1259

    
1260
#if defined(TARGET_PPC64)
1261
void do_tlbie_64 (void)
1262
{
1263
    T0 = (uint64_t)T0;
1264
#if !defined(FLUSH_ALL_TLBS)
1265
    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
1266
        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
1267
        if (env->id_tlbs == 1)
1268
            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
1269
    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
1270
        /* XXX: TODO */
1271
#if 0
1272
        ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
1273
                                     env->spr[SPR_BOOKE_PID]);
1274
#endif
1275
    } else {
1276
        /* tlbie invalidate TLBs for all segments
1277
         * As we have 2^36 segments, invalidate all qemu TLBs
1278
         */
1279
#if 0
1280
        T0 &= TARGET_PAGE_MASK;
1281
        T0 &= ~((target_ulong)-1 << 28);
1282
        /* XXX: this case should be optimized,
1283
         * giving a mask to tlb_flush_page
1284
         */
1285
        tlb_flush_page(env, T0 | (0x0 << 28));
1286
        tlb_flush_page(env, T0 | (0x1 << 28));
1287
        tlb_flush_page(env, T0 | (0x2 << 28));
1288
        tlb_flush_page(env, T0 | (0x3 << 28));
1289
        tlb_flush_page(env, T0 | (0x4 << 28));
1290
        tlb_flush_page(env, T0 | (0x5 << 28));
1291
        tlb_flush_page(env, T0 | (0x6 << 28));
1292
        tlb_flush_page(env, T0 | (0x7 << 28));
1293
        tlb_flush_page(env, T0 | (0x8 << 28));
1294
        tlb_flush_page(env, T0 | (0x9 << 28));
1295
        tlb_flush_page(env, T0 | (0xA << 28));
1296
        tlb_flush_page(env, T0 | (0xB << 28));
1297
        tlb_flush_page(env, T0 | (0xC << 28));
1298
        tlb_flush_page(env, T0 | (0xD << 28));
1299
        tlb_flush_page(env, T0 | (0xE << 28));
1300
        tlb_flush_page(env, T0 | (0xF << 28));
1301
#else
1302
        tlb_flush(env, 1);
1303
#endif
1304
    }
1305
#else
1306
    do_tlbia();
1307
#endif
1308
}
1309
#endif
1310

    
1311
#if defined(TARGET_PPC64)
1312
void do_slbia (void)
1313
{
1314
    /* XXX: TODO */
1315
    tlb_flush(env, 1);
1316
}
1317

    
1318
void do_slbie (void)
1319
{
1320
    /* XXX: TODO */
1321
    tlb_flush(env, 1);
1322
}
1323
#endif
1324

    
1325
/* Software driven TLBs management */
1326
/* PowerPC 602/603 software TLB load instructions helpers */
1327
void do_load_6xx_tlb (int is_code)
1328
{
1329
    target_ulong RPN, CMP, EPN;
1330
    int way;
1331

    
1332
    RPN = env->spr[SPR_RPA];
1333
    if (is_code) {
1334
        CMP = env->spr[SPR_ICMP];
1335
        EPN = env->spr[SPR_IMISS];
1336
    } else {
1337
        CMP = env->spr[SPR_DCMP];
1338
        EPN = env->spr[SPR_DMISS];
1339
    }
1340
    way = (env->spr[SPR_SRR1] >> 17) & 1;
1341
#if defined (DEBUG_SOFTWARE_TLB)
1342
    if (loglevel != 0) {
1343
        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
1344
                __func__, (unsigned long)T0, (unsigned long)EPN,
1345
                (unsigned long)CMP, (unsigned long)RPN, way);
1346
    }
1347
#endif
1348
    /* Store this TLB */
1349
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
1350
                     way, is_code, CMP, RPN);
1351
}
1352

    
1353
/* Helpers for 4xx TLB management */
1354
void do_4xx_tlbia (void)
1355
{
1356
#if 0
1357
    ppc_tlb_t *tlb;
1358
    target_ulong page, end;
1359
    int i;
1360

1361
    for (i = 0; i < 64; i++) {
1362
        tlb = &env->tlb[i];
1363
        if (tlb->prot & PAGE_VALID) {
1364
            end = tlb->EPN + tlb->size;
1365
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1366
                tlb_flush_page(env, page);
1367
            tlb->prot &= ~PAGE_VALID;
1368
        }
1369
    }
1370
#endif
1371
}
1372

    
1373
void do_4xx_tlbre_lo (void)
1374
{
1375
#if 0
1376
    ppc_tlb_t *tlb;
1377

1378
    T0 &= 0x3F;
1379
    tlb = &env->tlb[T0];
1380
    T0 = tlb->stor[0];
1381
    env->spr[SPR_40x_PID] = tlb->pid;
1382
#endif
1383
}
1384

    
1385
void do_4xx_tlbre_hi (void)
1386
{
1387
#if 0
1388
    ppc_tlb_t *tlb;
1389

1390
    T0 &= 0x3F;
1391
    tlb = &env->tlb[T0];
1392
    T0 = tlb->stor[1];
1393
#endif
1394
}
1395

    
1396
static int tlb_4xx_search (target_ulong virtual)
1397
{
1398
#if 0
1399
    ppc_tlb_t *tlb;
1400
    target_ulong base, mask;
1401
    int i, ret;
1402

1403
    /* Default return value is no match */
1404
    ret = -1;
1405
    for (i = 0; i < 64; i++) {
1406
        tlb = &env->tlb[i];
1407
        /* Check TLB validity */
1408
        if (!(tlb->prot & PAGE_VALID))
1409
            continue;
1410
        /* Check TLB PID vs current PID */
1411
        if (tlb->pid != 0 && tlb->pid != env->spr[SPR_40x_PID])
1412
            continue;
1413
        /* Check TLB address vs virtual address */
1414
        base = tlb->EPN;
1415
        mask = ~(tlb->size - 1);
1416
        if ((base & mask) != (virtual & mask))
1417
            continue;
1418
        ret = i;
1419
        break;
1420
    }
1421

1422
    return ret;
1423
#else
1424
    return -1;
1425
#endif
1426
}
1427

    
1428
void do_4xx_tlbsx (void)
1429
{
1430
    T0 = tlb_4xx_search(T0);
1431
}
1432

    
1433
void do_4xx_tlbsx_ (void)
1434
{
1435
    int tmp = xer_ov;
1436

    
1437
    T0 = tlb_4xx_search(T0);
1438
    if (T0 != -1)
1439
        tmp |= 0x02;
1440
    env->crf[0] = tmp;
1441
}
1442

    
1443
void do_4xx_tlbwe_lo (void)
1444
{
1445
#if 0
1446
    ppc_tlb_t *tlb;
1447
    target_ulong page, end;
1448

1449
    T0 &= 0x3F;
1450
    tlb = &env->tlb[T0];
1451
    /* Invalidate previous TLB (if it's valid) */
1452
    if (tlb->prot & PAGE_VALID) {
1453
        end = tlb->EPN + tlb->size;
1454
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1455
            tlb_flush_page(env, page);
1456
    }
1457
    tlb->size = 1024 << (2 * ((T1 >> 7) & 0x7));
1458
    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
1459
    if (T1 & 0x400)
1460
        tlb->prot |= PAGE_VALID;
1461
    else
1462
        tlb->prot &= ~PAGE_VALID;
1463
    tlb->pid = env->spr[SPR_BOOKE_PID]; /* PID */
1464
    /* Invalidate new TLB (if valid) */
1465
    if (tlb->prot & PAGE_VALID) {
1466
        end = tlb->EPN + tlb->size;
1467
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1468
            tlb_flush_page(env, page);
1469
    }
1470
#endif
1471
}
1472

    
1473
void do_4xx_tlbwe_hi (void)
1474
{
1475
#if 0
1476
    ppc_tlb_t *tlb;
1477

1478
    T0 &= 0x3F;
1479
    tlb = &env->tlb[T0];
1480
    tlb->RPN = T1 & 0xFFFFFC00;
1481
    tlb->prot = PAGE_READ;
1482
    if (T1 & 0x200)
1483
        tlb->prot |= PAGE_EXEC;
1484
    if (T1 & 0x100)
1485
        tlb->prot |= PAGE_WRITE;
1486
#endif
1487
}
1488
#endif /* !CONFIG_USER_ONLY */