Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ bd7d9a6d

History | View | Annotate | Download (74.8 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
#include "host-utils.h"
22

    
23
#include "helper_regs.h"
24
#include "op_helper.h"
25

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

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

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

    
48
void do_raise_exception_err (uint32_t exception, int error_code)
49
{
50
#if 0
51
    printf("Raise exception %3x code : %d\n", exception, error_code);
52
#endif
53
    env->exception_index = exception;
54
    env->error_code = error_code;
55
    cpu_loop_exit();
56
}
57

    
58
void do_raise_exception (uint32_t exception)
59
{
60
    do_raise_exception_err(exception, 0);
61
}
62

    
63
void cpu_dump_EA (target_ulong EA);
64
void do_print_mem_EA (target_ulong EA)
65
{
66
    cpu_dump_EA(EA);
67
}
68

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

    
83
void do_store_cr (uint32_t mask)
84
{
85
    int i, sh;
86

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

    
93
#if defined(TARGET_PPC64)
94
void do_store_pri (int prio)
95
{
96
    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
97
    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
98
}
99
#endif
100

    
101
target_ulong ppc_load_dump_spr (int sprn)
102
{
103
    if (loglevel != 0) {
104
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
105
                sprn, sprn, env->spr[sprn]);
106
    }
107

    
108
    return env->spr[sprn];
109
}
110

    
111
void ppc_store_dump_spr (int sprn, target_ulong val)
112
{
113
    if (loglevel != 0) {
114
        fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
115
                sprn, sprn, env->spr[sprn], val);
116
    }
117
    env->spr[sprn] = val;
118
}
119

    
120
/*****************************************************************************/
121
/* Fixed point operations helpers */
122
void do_adde (void)
123
{
124
    T2 = T0;
125
    T0 += T1 + xer_ca;
126
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
127
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
128
        xer_ca = 0;
129
    } else {
130
        xer_ca = 1;
131
    }
132
}
133

    
134
#if defined(TARGET_PPC64)
135
void do_adde_64 (void)
136
{
137
    T2 = T0;
138
    T0 += T1 + xer_ca;
139
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
140
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
141
        xer_ca = 0;
142
    } else {
143
        xer_ca = 1;
144
    }
145
}
146
#endif
147

    
148
void do_addmeo (void)
149
{
150
    T1 = T0;
151
    T0 += xer_ca + (-1);
152
    xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
153
    xer_so |= xer_ov;
154
    if (likely(T1 != 0))
155
        xer_ca = 1;
156
    else
157
        xer_ca = 0;
158
}
159

    
160
#if defined(TARGET_PPC64)
161
void do_addmeo_64 (void)
162
{
163
    T1 = T0;
164
    T0 += xer_ca + (-1);
165
    xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
166
    xer_so |= xer_ov;
167
    if (likely(T1 != 0))
168
        xer_ca = 1;
169
    else
170
        xer_ca = 0;
171
}
172
#endif
173

    
174
void do_divwo (void)
175
{
176
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
177
                 (int32_t)T1 == 0))) {
178
        xer_ov = 0;
179
        T0 = (int32_t)T0 / (int32_t)T1;
180
    } else {
181
        xer_ov = 1;
182
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
183
    }
184
    xer_so |= xer_ov;
185
}
186

    
187
#if defined(TARGET_PPC64)
188
void do_divdo (void)
189
{
190
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
191
                 (int64_t)T1 == 0))) {
192
        xer_ov = 0;
193
        T0 = (int64_t)T0 / (int64_t)T1;
194
    } else {
195
        xer_ov = 1;
196
        T0 = UINT64_MAX * ((uint64_t)T0 >> 63);
197
    }
198
    xer_so |= xer_ov;
199
}
200
#endif
201

    
202
void do_divwuo (void)
203
{
204
    if (likely((uint32_t)T1 != 0)) {
205
        xer_ov = 0;
206
        T0 = (uint32_t)T0 / (uint32_t)T1;
207
    } else {
208
        xer_ov = 1;
209
        xer_so = 1;
210
        T0 = 0;
211
    }
212
}
213

    
214
#if defined(TARGET_PPC64)
215
void do_divduo (void)
216
{
217
    if (likely((uint64_t)T1 != 0)) {
218
        xer_ov = 0;
219
        T0 = (uint64_t)T0 / (uint64_t)T1;
220
    } else {
221
        xer_ov = 1;
222
        xer_so = 1;
223
        T0 = 0;
224
    }
225
}
226
#endif
227

    
228
void do_mullwo (void)
229
{
230
    int64_t res = (int64_t)T0 * (int64_t)T1;
231

    
232
    if (likely((int32_t)res == res)) {
233
        xer_ov = 0;
234
    } else {
235
        xer_ov = 1;
236
        xer_so = 1;
237
    }
238
    T0 = (int32_t)res;
239
}
240

    
241
#if defined(TARGET_PPC64)
242
void do_mulldo (void)
243
{
244
    int64_t th;
245
    uint64_t tl;
246

    
247
    muls64(&tl, &th, T0, T1);
248
    T0 = (int64_t)tl;
249
    /* If th != 0 && th != -1, then we had an overflow */
250
    if (likely((uint64_t)(th + 1) <= 1)) {
251
        xer_ov = 0;
252
    } else {
253
        xer_ov = 1;
254
    }
255
    xer_so |= xer_ov;
256
}
257
#endif
258

    
259
void do_nego (void)
260
{
261
    if (likely((int32_t)T0 != INT32_MIN)) {
262
        xer_ov = 0;
263
        T0 = -(int32_t)T0;
264
    } else {
265
        xer_ov = 1;
266
        xer_so = 1;
267
    }
268
}
269

    
270
#if defined(TARGET_PPC64)
271
void do_nego_64 (void)
272
{
273
    if (likely((int64_t)T0 != INT64_MIN)) {
274
        xer_ov = 0;
275
        T0 = -(int64_t)T0;
276
    } else {
277
        xer_ov = 1;
278
        xer_so = 1;
279
    }
280
}
281
#endif
282

    
283
void do_subfe (void)
284
{
285
    T0 = T1 + ~T0 + xer_ca;
286
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
287
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
288
        xer_ca = 0;
289
    } else {
290
        xer_ca = 1;
291
    }
292
}
293

    
294
#if defined(TARGET_PPC64)
295
void do_subfe_64 (void)
296
{
297
    T0 = T1 + ~T0 + xer_ca;
298
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
299
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
300
        xer_ca = 0;
301
    } else {
302
        xer_ca = 1;
303
    }
304
}
305
#endif
306

    
307
void do_subfmeo (void)
308
{
309
    T1 = T0;
310
    T0 = ~T0 + xer_ca - 1;
311
    xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
312
    xer_so |= xer_ov;
313
    if (likely((uint32_t)T1 != UINT32_MAX))
314
        xer_ca = 1;
315
    else
316
        xer_ca = 0;
317
}
318

    
319
#if defined(TARGET_PPC64)
320
void do_subfmeo_64 (void)
321
{
322
    T1 = T0;
323
    T0 = ~T0 + xer_ca - 1;
324
    xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
325
    xer_so |= xer_ov;
326
    if (likely((uint64_t)T1 != UINT64_MAX))
327
        xer_ca = 1;
328
    else
329
        xer_ca = 0;
330
}
331
#endif
332

    
333
void do_subfzeo (void)
334
{
335
    T1 = T0;
336
    T0 = ~T0 + xer_ca;
337
    xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
338
              ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
339
    xer_so |= xer_ov;
340
    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
341
        xer_ca = 0;
342
    } else {
343
        xer_ca = 1;
344
    }
345
}
346

    
347
#if defined(TARGET_PPC64)
348
void do_subfzeo_64 (void)
349
{
350
    T1 = T0;
351
    T0 = ~T0 + xer_ca;
352
    xer_ov = (((uint64_t)~T1 ^  UINT64_MAX) &
353
              ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
354
    xer_so |= xer_ov;
355
    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
356
        xer_ca = 0;
357
    } else {
358
        xer_ca = 1;
359
    }
360
}
361
#endif
362

    
363
void do_cntlzw (void)
364
{
365
    T0 = clz32(T0);
366
}
367

    
368
#if defined(TARGET_PPC64)
369
void do_cntlzd (void)
370
{
371
    T0 = clz64(T0);
372
}
373
#endif
374

    
375
/* shift right arithmetic helper */
376
void do_sraw (void)
377
{
378
    int32_t ret;
379

    
380
    if (likely(!(T1 & 0x20UL))) {
381
        if (likely((uint32_t)T1 != 0)) {
382
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
383
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
384
                xer_ca = 0;
385
            } else {
386
                xer_ca = 1;
387
            }
388
        } else {
389
            ret = T0;
390
            xer_ca = 0;
391
        }
392
    } else {
393
        ret = UINT32_MAX * ((uint32_t)T0 >> 31);
394
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
395
            xer_ca = 0;
396
        } else {
397
            xer_ca = 1;
398
        }
399
    }
400
    T0 = ret;
401
}
402

    
403
#if defined(TARGET_PPC64)
404
void do_srad (void)
405
{
406
    int64_t ret;
407

    
408
    if (likely(!(T1 & 0x40UL))) {
409
        if (likely((uint64_t)T1 != 0)) {
410
            ret = (int64_t)T0 >> (T1 & 0x3FUL);
411
            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
412
                xer_ca = 0;
413
            } else {
414
                xer_ca = 1;
415
            }
416
        } else {
417
            ret = T0;
418
            xer_ca = 0;
419
        }
420
    } else {
421
        ret = UINT64_MAX * ((uint64_t)T0 >> 63);
422
        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
423
            xer_ca = 0;
424
        } else {
425
            xer_ca = 1;
426
        }
427
    }
428
    T0 = ret;
429
}
430
#endif
431

    
432
void do_popcntb (void)
433
{
434
    uint32_t ret;
435
    int i;
436

    
437
    ret = 0;
438
    for (i = 0; i < 32; i += 8)
439
        ret |= ctpop8((T0 >> i) & 0xFF) << i;
440
    T0 = ret;
441
}
442

    
443
#if defined(TARGET_PPC64)
444
void do_popcntb_64 (void)
445
{
446
    uint64_t ret;
447
    int i;
448

    
449
    ret = 0;
450
    for (i = 0; i < 64; i += 8)
451
        ret |= ctpop8((T0 >> i) & 0xFF) << i;
452
    T0 = ret;
453
}
454
#endif
455

    
456
/*****************************************************************************/
457
/* Floating point operations helpers */
458
static always_inline int fpisneg (float64 d)
459
{
460
    CPU_DoubleU u;
461

    
462
    u.d = d;
463

    
464
    return u.ll >> 63 != 0;
465
}
466

    
467
static always_inline int isden (float64 d)
468
{
469
    CPU_DoubleU u;
470

    
471
    u.d = d;
472

    
473
    return ((u.ll >> 52) & 0x7FF) == 0;
474
}
475

    
476
static always_inline int iszero (float64 d)
477
{
478
    CPU_DoubleU u;
479

    
480
    u.d = d;
481

    
482
    return (u.ll & ~0x8000000000000000ULL) == 0;
483
}
484

    
485
static always_inline int isinfinity (float64 d)
486
{
487
    CPU_DoubleU u;
488

    
489
    u.d = d;
490

    
491
    return ((u.ll >> 52) & 0x7FF) == 0x7FF &&
492
        (u.ll & 0x000FFFFFFFFFFFFFULL) == 0;
493
}
494

    
495
#ifdef CONFIG_SOFTFLOAT
496
static always_inline int isfinite (float64 d)
497
{
498
    CPU_DoubleU u;
499

    
500
    u.d = d;
501

    
502
    return (((u.ll >> 52) & 0x7FF) != 0x7FF);
503
}
504

    
505
static always_inline int isnormal (float64 d)
506
{
507
    CPU_DoubleU u;
508

    
509
    u.d = d;
510

    
511
    uint32_t exp = (u.ll >> 52) & 0x7FF;
512
    return ((0 < exp) && (exp < 0x7FF));
513
}
514
#endif
515

    
516
void do_compute_fprf (int set_fprf)
517
{
518
    int isneg;
519

    
520
    isneg = fpisneg(FT0);
521
    if (unlikely(float64_is_nan(FT0))) {
522
        if (float64_is_signaling_nan(FT0)) {
523
            /* Signaling NaN: flags are undefined */
524
            T0 = 0x00;
525
        } else {
526
            /* Quiet NaN */
527
            T0 = 0x11;
528
        }
529
    } else if (unlikely(isinfinity(FT0))) {
530
        /* +/- infinity */
531
        if (isneg)
532
            T0 = 0x09;
533
        else
534
            T0 = 0x05;
535
    } else {
536
        if (iszero(FT0)) {
537
            /* +/- zero */
538
            if (isneg)
539
                T0 = 0x12;
540
            else
541
                T0 = 0x02;
542
        } else {
543
            if (isden(FT0)) {
544
                /* Denormalized numbers */
545
                T0 = 0x10;
546
            } else {
547
                /* Normalized numbers */
548
                T0 = 0x00;
549
            }
550
            if (isneg) {
551
                T0 |= 0x08;
552
            } else {
553
                T0 |= 0x04;
554
            }
555
        }
556
    }
557
    if (set_fprf) {
558
        /* We update FPSCR_FPRF */
559
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
560
        env->fpscr |= T0 << FPSCR_FPRF;
561
    }
562
    /* We just need fpcc to update Rc1 */
563
    T0 &= 0xF;
564
}
565

    
566
/* Floating-point invalid operations exception */
567
static always_inline void fload_invalid_op_excp (int op)
568
{
569
    int ve;
570

    
571
    ve = fpscr_ve;
572
    if (op & POWERPC_EXCP_FP_VXSNAN) {
573
        /* Operation on signaling NaN */
574
        env->fpscr |= 1 << FPSCR_VXSNAN;
575
    }
576
    if (op & POWERPC_EXCP_FP_VXSOFT) {
577
        /* Software-defined condition */
578
        env->fpscr |= 1 << FPSCR_VXSOFT;
579
    }
580
    switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
581
    case POWERPC_EXCP_FP_VXISI:
582
        /* Magnitude subtraction of infinities */
583
        env->fpscr |= 1 << FPSCR_VXISI;
584
        goto update_arith;
585
    case POWERPC_EXCP_FP_VXIDI:
586
        /* Division of infinity by infinity */
587
        env->fpscr |= 1 << FPSCR_VXIDI;
588
        goto update_arith;
589
    case POWERPC_EXCP_FP_VXZDZ:
590
        /* Division of zero by zero */
591
        env->fpscr |= 1 << FPSCR_VXZDZ;
592
        goto update_arith;
593
    case POWERPC_EXCP_FP_VXIMZ:
594
        /* Multiplication of zero by infinity */
595
        env->fpscr |= 1 << FPSCR_VXIMZ;
596
        goto update_arith;
597
    case POWERPC_EXCP_FP_VXVC:
598
        /* Ordered comparison of NaN */
599
        env->fpscr |= 1 << FPSCR_VXVC;
600
        env->fpscr &= ~(0xF << FPSCR_FPCC);
601
        env->fpscr |= 0x11 << FPSCR_FPCC;
602
        /* We must update the target FPR before raising the exception */
603
        if (ve != 0) {
604
            env->exception_index = POWERPC_EXCP_PROGRAM;
605
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
606
            /* Update the floating-point enabled exception summary */
607
            env->fpscr |= 1 << FPSCR_FEX;
608
            /* Exception is differed */
609
            ve = 0;
610
        }
611
        break;
612
    case POWERPC_EXCP_FP_VXSQRT:
613
        /* Square root of a negative number */
614
        env->fpscr |= 1 << FPSCR_VXSQRT;
615
    update_arith:
616
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
617
        if (ve == 0) {
618
            /* Set the result to quiet NaN */
619
            FT0 = UINT64_MAX;
620
            env->fpscr &= ~(0xF << FPSCR_FPCC);
621
            env->fpscr |= 0x11 << FPSCR_FPCC;
622
        }
623
        break;
624
    case POWERPC_EXCP_FP_VXCVI:
625
        /* Invalid conversion */
626
        env->fpscr |= 1 << FPSCR_VXCVI;
627
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
628
        if (ve == 0) {
629
            /* Set the result to quiet NaN */
630
            FT0 = UINT64_MAX;
631
            env->fpscr &= ~(0xF << FPSCR_FPCC);
632
            env->fpscr |= 0x11 << FPSCR_FPCC;
633
        }
634
        break;
635
    }
636
    /* Update the floating-point invalid operation summary */
637
    env->fpscr |= 1 << FPSCR_VX;
638
    /* Update the floating-point exception summary */
639
    env->fpscr |= 1 << FPSCR_FX;
640
    if (ve != 0) {
641
        /* Update the floating-point enabled exception summary */
642
        env->fpscr |= 1 << FPSCR_FEX;
643
        if (msr_fe0 != 0 || msr_fe1 != 0)
644
            do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
645
    }
646
}
647

    
648
static always_inline void float_zero_divide_excp (void)
649
{
650
    CPU_DoubleU u0, u1;
651

    
652
    env->fpscr |= 1 << FPSCR_ZX;
653
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
654
    /* Update the floating-point exception summary */
655
    env->fpscr |= 1 << FPSCR_FX;
656
    if (fpscr_ze != 0) {
657
        /* Update the floating-point enabled exception summary */
658
        env->fpscr |= 1 << FPSCR_FEX;
659
        if (msr_fe0 != 0 || msr_fe1 != 0) {
660
            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
661
                                   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
662
        }
663
    } else {
664
        /* Set the result to infinity */
665
        u0.d = FT0;
666
        u1.d = FT1;
667
        u0.ll = ((u0.ll ^ u1.ll) & 0x8000000000000000ULL);
668
        u0.ll |= 0x7FFULL << 52;
669
        FT0 = u0.d;
670
    }
671
}
672

    
673
static always_inline void float_overflow_excp (void)
674
{
675
    env->fpscr |= 1 << FPSCR_OX;
676
    /* Update the floating-point exception summary */
677
    env->fpscr |= 1 << FPSCR_FX;
678
    if (fpscr_oe != 0) {
679
        /* XXX: should adjust the result */
680
        /* Update the floating-point enabled exception summary */
681
        env->fpscr |= 1 << FPSCR_FEX;
682
        /* We must update the target FPR before raising the exception */
683
        env->exception_index = POWERPC_EXCP_PROGRAM;
684
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
685
    } else {
686
        env->fpscr |= 1 << FPSCR_XX;
687
        env->fpscr |= 1 << FPSCR_FI;
688
    }
689
}
690

    
691
static always_inline void float_underflow_excp (void)
692
{
693
    env->fpscr |= 1 << FPSCR_UX;
694
    /* Update the floating-point exception summary */
695
    env->fpscr |= 1 << FPSCR_FX;
696
    if (fpscr_ue != 0) {
697
        /* XXX: should adjust the result */
698
        /* Update the floating-point enabled exception summary */
699
        env->fpscr |= 1 << FPSCR_FEX;
700
        /* We must update the target FPR before raising the exception */
701
        env->exception_index = POWERPC_EXCP_PROGRAM;
702
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
703
    }
704
}
705

    
706
static always_inline void float_inexact_excp (void)
707
{
708
    env->fpscr |= 1 << FPSCR_XX;
709
    /* Update the floating-point exception summary */
710
    env->fpscr |= 1 << FPSCR_FX;
711
    if (fpscr_xe != 0) {
712
        /* Update the floating-point enabled exception summary */
713
        env->fpscr |= 1 << FPSCR_FEX;
714
        /* We must update the target FPR before raising the exception */
715
        env->exception_index = POWERPC_EXCP_PROGRAM;
716
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
717
    }
718
}
719

    
720
static always_inline void fpscr_set_rounding_mode (void)
721
{
722
    int rnd_type;
723

    
724
    /* Set rounding mode */
725
    switch (fpscr_rn) {
726
    case 0:
727
        /* Best approximation (round to nearest) */
728
        rnd_type = float_round_nearest_even;
729
        break;
730
    case 1:
731
        /* Smaller magnitude (round toward zero) */
732
        rnd_type = float_round_to_zero;
733
        break;
734
    case 2:
735
        /* Round toward +infinite */
736
        rnd_type = float_round_up;
737
        break;
738
    default:
739
    case 3:
740
        /* Round toward -infinite */
741
        rnd_type = float_round_down;
742
        break;
743
    }
744
    set_float_rounding_mode(rnd_type, &env->fp_status);
745
}
746

    
747
void do_fpscr_setbit (int bit)
748
{
749
    int prev;
750

    
751
    prev = (env->fpscr >> bit) & 1;
752
    env->fpscr |= 1 << bit;
753
    if (prev == 0) {
754
        switch (bit) {
755
        case FPSCR_VX:
756
            env->fpscr |= 1 << FPSCR_FX;
757
            if (fpscr_ve)
758
                goto raise_ve;
759
        case FPSCR_OX:
760
            env->fpscr |= 1 << FPSCR_FX;
761
            if (fpscr_oe)
762
                goto raise_oe;
763
            break;
764
        case FPSCR_UX:
765
            env->fpscr |= 1 << FPSCR_FX;
766
            if (fpscr_ue)
767
                goto raise_ue;
768
            break;
769
        case FPSCR_ZX:
770
            env->fpscr |= 1 << FPSCR_FX;
771
            if (fpscr_ze)
772
                goto raise_ze;
773
            break;
774
        case FPSCR_XX:
775
            env->fpscr |= 1 << FPSCR_FX;
776
            if (fpscr_xe)
777
                goto raise_xe;
778
            break;
779
        case FPSCR_VXSNAN:
780
        case FPSCR_VXISI:
781
        case FPSCR_VXIDI:
782
        case FPSCR_VXZDZ:
783
        case FPSCR_VXIMZ:
784
        case FPSCR_VXVC:
785
        case FPSCR_VXSOFT:
786
        case FPSCR_VXSQRT:
787
        case FPSCR_VXCVI:
788
            env->fpscr |= 1 << FPSCR_VX;
789
            env->fpscr |= 1 << FPSCR_FX;
790
            if (fpscr_ve != 0)
791
                goto raise_ve;
792
            break;
793
        case FPSCR_VE:
794
            if (fpscr_vx != 0) {
795
            raise_ve:
796
                env->error_code = POWERPC_EXCP_FP;
797
                if (fpscr_vxsnan)
798
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
799
                if (fpscr_vxisi)
800
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
801
                if (fpscr_vxidi)
802
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
803
                if (fpscr_vxzdz)
804
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
805
                if (fpscr_vximz)
806
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
807
                if (fpscr_vxvc)
808
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
809
                if (fpscr_vxsoft)
810
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
811
                if (fpscr_vxsqrt)
812
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
813
                if (fpscr_vxcvi)
814
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
815
                goto raise_excp;
816
            }
817
            break;
818
        case FPSCR_OE:
819
            if (fpscr_ox != 0) {
820
            raise_oe:
821
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
822
                goto raise_excp;
823
            }
824
            break;
825
        case FPSCR_UE:
826
            if (fpscr_ux != 0) {
827
            raise_ue:
828
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
829
                goto raise_excp;
830
            }
831
            break;
832
        case FPSCR_ZE:
833
            if (fpscr_zx != 0) {
834
            raise_ze:
835
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
836
                goto raise_excp;
837
            }
838
            break;
839
        case FPSCR_XE:
840
            if (fpscr_xx != 0) {
841
            raise_xe:
842
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
843
                goto raise_excp;
844
            }
845
            break;
846
        case FPSCR_RN1:
847
        case FPSCR_RN:
848
            fpscr_set_rounding_mode();
849
            break;
850
        default:
851
            break;
852
        raise_excp:
853
            /* Update the floating-point enabled exception summary */
854
            env->fpscr |= 1 << FPSCR_FEX;
855
                /* We have to update Rc1 before raising the exception */
856
            env->exception_index = POWERPC_EXCP_PROGRAM;
857
            break;
858
        }
859
    }
860
}
861

    
862
#if defined(WORDS_BIGENDIAN)
863
#define WORD0 0
864
#define WORD1 1
865
#else
866
#define WORD0 1
867
#define WORD1 0
868
#endif
869
void do_store_fpscr (uint32_t mask)
870
{
871
    /*
872
     * We use only the 32 LSB of the incoming fpr
873
     */
874
    CPU_DoubleU u;
875
    uint32_t prev, new;
876
    int i;
877

    
878
    u.d = FT0;
879
    prev = env->fpscr;
880
    new = u.l.lower;
881
    new &= ~0x90000000;
882
    new |= prev & 0x90000000;
883
    for (i = 0; i < 7; i++) {
884
        if (mask & (1 << i)) {
885
            env->fpscr &= ~(0xF << (4 * i));
886
            env->fpscr |= new & (0xF << (4 * i));
887
        }
888
    }
889
    /* Update VX and FEX */
890
    if (fpscr_ix != 0)
891
        env->fpscr |= 1 << FPSCR_VX;
892
    else
893
        env->fpscr &= ~(1 << FPSCR_VX);
894
    if ((fpscr_ex & fpscr_eex) != 0) {
895
        env->fpscr |= 1 << FPSCR_FEX;
896
        env->exception_index = POWERPC_EXCP_PROGRAM;
897
        /* XXX: we should compute it properly */
898
        env->error_code = POWERPC_EXCP_FP;
899
    }
900
    else
901
        env->fpscr &= ~(1 << FPSCR_FEX);
902
    fpscr_set_rounding_mode();
903
}
904
#undef WORD0
905
#undef WORD1
906

    
907
#ifdef CONFIG_SOFTFLOAT
908
void do_float_check_status (void)
909
{
910
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
911
        (env->error_code & POWERPC_EXCP_FP)) {
912
        /* Differred floating-point exception after target FPR update */
913
        if (msr_fe0 != 0 || msr_fe1 != 0)
914
            do_raise_exception_err(env->exception_index, env->error_code);
915
    } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
916
        float_overflow_excp();
917
    } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
918
        float_underflow_excp();
919
    } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
920
        float_inexact_excp();
921
    }
922
}
923
#endif
924

    
925
#if USE_PRECISE_EMULATION
926
void do_fadd (void)
927
{
928
    if (unlikely(float64_is_signaling_nan(FT0) ||
929
                 float64_is_signaling_nan(FT1))) {
930
        /* sNaN addition */
931
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
932
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
933
                      fpisneg(FT0) == fpisneg(FT1))) {
934
        FT0 = float64_add(FT0, FT1, &env->fp_status);
935
    } else {
936
        /* Magnitude subtraction of infinities */
937
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
938
    }
939
}
940

    
941
void do_fsub (void)
942
{
943
    if (unlikely(float64_is_signaling_nan(FT0) ||
944
                 float64_is_signaling_nan(FT1))) {
945
        /* sNaN subtraction */
946
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
947
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
948
                      fpisneg(FT0) != fpisneg(FT1))) {
949
        FT0 = float64_sub(FT0, FT1, &env->fp_status);
950
    } else {
951
        /* Magnitude subtraction of infinities */
952
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
953
    }
954
}
955

    
956
void do_fmul (void)
957
{
958
    if (unlikely(float64_is_signaling_nan(FT0) ||
959
                 float64_is_signaling_nan(FT1))) {
960
        /* sNaN multiplication */
961
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
962
    } else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
963
                        (iszero(FT0) && isinfinity(FT1)))) {
964
        /* Multiplication of zero by infinity */
965
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
966
    } else {
967
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
968
    }
969
}
970

    
971
void do_fdiv (void)
972
{
973
    if (unlikely(float64_is_signaling_nan(FT0) ||
974
                 float64_is_signaling_nan(FT1))) {
975
        /* sNaN division */
976
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
977
    } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
978
        /* Division of infinity by infinity */
979
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
980
    } else if (unlikely(iszero(FT1))) {
981
        if (iszero(FT0)) {
982
            /* Division of zero by zero */
983
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
984
        } else {
985
            /* Division by zero */
986
            float_zero_divide_excp();
987
        }
988
    } else {
989
        FT0 = float64_div(FT0, FT1, &env->fp_status);
990
    }
991
}
992
#endif /* USE_PRECISE_EMULATION */
993

    
994
void do_fctiw (void)
995
{
996
    CPU_DoubleU p;
997

    
998
    if (unlikely(float64_is_signaling_nan(FT0))) {
999
        /* sNaN conversion */
1000
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1001
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1002
        /* qNan / infinity conversion */
1003
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1004
    } else {
1005
        p.ll = float64_to_int32(FT0, &env->fp_status);
1006
#if USE_PRECISE_EMULATION
1007
        /* XXX: higher bits are not supposed to be significant.
1008
         *     to make tests easier, return the same as a real PowerPC 750
1009
         */
1010
        p.ll |= 0xFFF80000ULL << 32;
1011
#endif
1012
        FT0 = p.d;
1013
    }
1014
}
1015

    
1016
void do_fctiwz (void)
1017
{
1018
    CPU_DoubleU p;
1019

    
1020
    if (unlikely(float64_is_signaling_nan(FT0))) {
1021
        /* sNaN conversion */
1022
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1023
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1024
        /* qNan / infinity conversion */
1025
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1026
    } else {
1027
        p.ll = float64_to_int32_round_to_zero(FT0, &env->fp_status);
1028
#if USE_PRECISE_EMULATION
1029
        /* XXX: higher bits are not supposed to be significant.
1030
         *     to make tests easier, return the same as a real PowerPC 750
1031
         */
1032
        p.ll |= 0xFFF80000ULL << 32;
1033
#endif
1034
        FT0 = p.d;
1035
    }
1036
}
1037

    
1038
#if defined(TARGET_PPC64)
1039
void do_fcfid (void)
1040
{
1041
    CPU_DoubleU p;
1042

    
1043
    p.d = FT0;
1044
    FT0 = int64_to_float64(p.ll, &env->fp_status);
1045
}
1046

    
1047
void do_fctid (void)
1048
{
1049
    CPU_DoubleU p;
1050

    
1051
    if (unlikely(float64_is_signaling_nan(FT0))) {
1052
        /* sNaN conversion */
1053
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1054
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1055
        /* qNan / infinity conversion */
1056
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1057
    } else {
1058
        p.ll = float64_to_int64(FT0, &env->fp_status);
1059
        FT0 = p.d;
1060
    }
1061
}
1062

    
1063
void do_fctidz (void)
1064
{
1065
    CPU_DoubleU p;
1066

    
1067
    if (unlikely(float64_is_signaling_nan(FT0))) {
1068
        /* sNaN conversion */
1069
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1070
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1071
        /* qNan / infinity conversion */
1072
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1073
    } else {
1074
        p.ll = float64_to_int64_round_to_zero(FT0, &env->fp_status);
1075
        FT0 = p.d;
1076
    }
1077
}
1078

    
1079
#endif
1080

    
1081
static always_inline void do_fri (int rounding_mode)
1082
{
1083
    if (unlikely(float64_is_signaling_nan(FT0))) {
1084
        /* sNaN round */
1085
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1086
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1087
        /* qNan / infinity round */
1088
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1089
    } else {
1090
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1091
        FT0 = float64_round_to_int(FT0, &env->fp_status);
1092
        /* Restore rounding mode from FPSCR */
1093
        fpscr_set_rounding_mode();
1094
    }
1095
}
1096

    
1097
void do_frin (void)
1098
{
1099
    do_fri(float_round_nearest_even);
1100
}
1101

    
1102
void do_friz (void)
1103
{
1104
    do_fri(float_round_to_zero);
1105
}
1106

    
1107
void do_frip (void)
1108
{
1109
    do_fri(float_round_up);
1110
}
1111

    
1112
void do_frim (void)
1113
{
1114
    do_fri(float_round_down);
1115
}
1116

    
1117
#if USE_PRECISE_EMULATION
1118
void do_fmadd (void)
1119
{
1120
    if (unlikely(float64_is_signaling_nan(FT0) ||
1121
                 float64_is_signaling_nan(FT1) ||
1122
                 float64_is_signaling_nan(FT2))) {
1123
        /* sNaN operation */
1124
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1125
    } else {
1126
#ifdef FLOAT128
1127
        /* This is the way the PowerPC specification defines it */
1128
        float128 ft0_128, ft1_128;
1129

    
1130
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1131
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1132
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1133
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1134
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1135
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1136
#else
1137
        /* This is OK on x86 hosts */
1138
        FT0 = (FT0 * FT1) + FT2;
1139
#endif
1140
    }
1141
}
1142

    
1143
void do_fmsub (void)
1144
{
1145
    if (unlikely(float64_is_signaling_nan(FT0) ||
1146
                 float64_is_signaling_nan(FT1) ||
1147
                 float64_is_signaling_nan(FT2))) {
1148
        /* sNaN operation */
1149
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1150
    } else {
1151
#ifdef FLOAT128
1152
        /* This is the way the PowerPC specification defines it */
1153
        float128 ft0_128, ft1_128;
1154

    
1155
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1156
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1157
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1158
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1159
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1160
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1161
#else
1162
        /* This is OK on x86 hosts */
1163
        FT0 = (FT0 * FT1) - FT2;
1164
#endif
1165
    }
1166
}
1167
#endif /* USE_PRECISE_EMULATION */
1168

    
1169
void do_fnmadd (void)
1170
{
1171
    if (unlikely(float64_is_signaling_nan(FT0) ||
1172
                 float64_is_signaling_nan(FT1) ||
1173
                 float64_is_signaling_nan(FT2))) {
1174
        /* sNaN operation */
1175
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1176
    } else {
1177
#if USE_PRECISE_EMULATION
1178
#ifdef FLOAT128
1179
        /* This is the way the PowerPC specification defines it */
1180
        float128 ft0_128, ft1_128;
1181

    
1182
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1183
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1184
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1185
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1186
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1187
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1188
#else
1189
        /* This is OK on x86 hosts */
1190
        FT0 = (FT0 * FT1) + FT2;
1191
#endif
1192
#else
1193
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1194
        FT0 = float64_add(FT0, FT2, &env->fp_status);
1195
#endif
1196
        if (likely(!isnan(FT0)))
1197
            FT0 = float64_chs(FT0);
1198
    }
1199
}
1200

    
1201
void do_fnmsub (void)
1202
{
1203
    if (unlikely(float64_is_signaling_nan(FT0) ||
1204
                 float64_is_signaling_nan(FT1) ||
1205
                 float64_is_signaling_nan(FT2))) {
1206
        /* sNaN operation */
1207
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1208
    } else {
1209
#if USE_PRECISE_EMULATION
1210
#ifdef FLOAT128
1211
        /* This is the way the PowerPC specification defines it */
1212
        float128 ft0_128, ft1_128;
1213

    
1214
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1215
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1216
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1217
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1218
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1219
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1220
#else
1221
        /* This is OK on x86 hosts */
1222
        FT0 = (FT0 * FT1) - FT2;
1223
#endif
1224
#else
1225
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1226
        FT0 = float64_sub(FT0, FT2, &env->fp_status);
1227
#endif
1228
        if (likely(!isnan(FT0)))
1229
            FT0 = float64_chs(FT0);
1230
    }
1231
}
1232

    
1233
#if USE_PRECISE_EMULATION
1234
void do_frsp (void)
1235
{
1236
    if (unlikely(float64_is_signaling_nan(FT0))) {
1237
        /* sNaN square root */
1238
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1239
    } else {
1240
        FT0 = float64_to_float32(FT0, &env->fp_status);
1241
    }
1242
}
1243
#endif /* USE_PRECISE_EMULATION */
1244

    
1245
void do_fsqrt (void)
1246
{
1247
    if (unlikely(float64_is_signaling_nan(FT0))) {
1248
        /* sNaN square root */
1249
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1250
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1251
        /* Square root of a negative nonzero number */
1252
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1253
    } else {
1254
        FT0 = float64_sqrt(FT0, &env->fp_status);
1255
    }
1256
}
1257

    
1258
void do_fre (void)
1259
{
1260
    CPU_DoubleU p;
1261

    
1262
    if (unlikely(float64_is_signaling_nan(FT0))) {
1263
        /* sNaN reciprocal */
1264
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1265
    } else if (unlikely(iszero(FT0))) {
1266
        /* Zero reciprocal */
1267
        float_zero_divide_excp();
1268
    } else if (likely(isnormal(FT0))) {
1269
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1270
    } else {
1271
        p.d = FT0;
1272
        if (p.ll == 0x8000000000000000ULL) {
1273
            p.ll = 0xFFF0000000000000ULL;
1274
        } else if (p.ll == 0x0000000000000000ULL) {
1275
            p.ll = 0x7FF0000000000000ULL;
1276
        } else if (isnan(FT0)) {
1277
            p.ll = 0x7FF8000000000000ULL;
1278
        } else if (fpisneg(FT0)) {
1279
            p.ll = 0x8000000000000000ULL;
1280
        } else {
1281
            p.ll = 0x0000000000000000ULL;
1282
        }
1283
        FT0 = p.d;
1284
    }
1285
}
1286

    
1287
void do_fres (void)
1288
{
1289
    CPU_DoubleU p;
1290

    
1291
    if (unlikely(float64_is_signaling_nan(FT0))) {
1292
        /* sNaN reciprocal */
1293
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1294
    } else if (unlikely(iszero(FT0))) {
1295
        /* Zero reciprocal */
1296
        float_zero_divide_excp();
1297
    } else if (likely(isnormal(FT0))) {
1298
#if USE_PRECISE_EMULATION
1299
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1300
        FT0 = float64_to_float32(FT0, &env->fp_status);
1301
#else
1302
        FT0 = float32_div(1.0, FT0, &env->fp_status);
1303
#endif
1304
    } else {
1305
        p.d = FT0;
1306
        if (p.ll == 0x8000000000000000ULL) {
1307
            p.ll = 0xFFF0000000000000ULL;
1308
        } else if (p.ll == 0x0000000000000000ULL) {
1309
            p.ll = 0x7FF0000000000000ULL;
1310
        } else if (isnan(FT0)) {
1311
            p.ll = 0x7FF8000000000000ULL;
1312
        } else if (fpisneg(FT0)) {
1313
            p.ll = 0x8000000000000000ULL;
1314
        } else {
1315
            p.ll = 0x0000000000000000ULL;
1316
        }
1317
        FT0 = p.d;
1318
    }
1319
}
1320

    
1321
void do_frsqrte (void)
1322
{
1323
    CPU_DoubleU p;
1324

    
1325
    if (unlikely(float64_is_signaling_nan(FT0))) {
1326
        /* sNaN reciprocal square root */
1327
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1328
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1329
        /* Reciprocal square root of a negative nonzero number */
1330
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1331
    } else if (likely(isnormal(FT0))) {
1332
        FT0 = float64_sqrt(FT0, &env->fp_status);
1333
        FT0 = float32_div(1.0, FT0, &env->fp_status);
1334
    } else {
1335
        p.d = FT0;
1336
        if (p.ll == 0x8000000000000000ULL) {
1337
            p.ll = 0xFFF0000000000000ULL;
1338
        } else if (p.ll == 0x0000000000000000ULL) {
1339
            p.ll = 0x7FF0000000000000ULL;
1340
        } else if (isnan(FT0)) {
1341
            p.ll |= 0x000FFFFFFFFFFFFFULL;
1342
        } else if (fpisneg(FT0)) {
1343
            p.ll = 0x7FF8000000000000ULL;
1344
        } else {
1345
            p.ll = 0x0000000000000000ULL;
1346
        }
1347
        FT0 = p.d;
1348
    }
1349
}
1350

    
1351
void do_fsel (void)
1352
{
1353
    if (!fpisneg(FT0) || iszero(FT0))
1354
        FT0 = FT1;
1355
    else
1356
        FT0 = FT2;
1357
}
1358

    
1359
void do_fcmpu (void)
1360
{
1361
    if (unlikely(float64_is_signaling_nan(FT0) ||
1362
                 float64_is_signaling_nan(FT1))) {
1363
        /* sNaN comparison */
1364
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1365
    } else {
1366
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1367
            T0 = 0x08UL;
1368
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1369
            T0 = 0x04UL;
1370
        } else {
1371
            T0 = 0x02UL;
1372
        }
1373
    }
1374
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1375
    env->fpscr |= T0 << FPSCR_FPRF;
1376
}
1377

    
1378
void do_fcmpo (void)
1379
{
1380
    if (unlikely(float64_is_nan(FT0) ||
1381
                 float64_is_nan(FT1))) {
1382
        if (float64_is_signaling_nan(FT0) ||
1383
            float64_is_signaling_nan(FT1)) {
1384
            /* sNaN comparison */
1385
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1386
                                  POWERPC_EXCP_FP_VXVC);
1387
        } else {
1388
            /* qNaN comparison */
1389
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1390
        }
1391
    } else {
1392
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1393
            T0 = 0x08UL;
1394
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1395
            T0 = 0x04UL;
1396
        } else {
1397
            T0 = 0x02UL;
1398
        }
1399
    }
1400
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1401
    env->fpscr |= T0 << FPSCR_FPRF;
1402
}
1403

    
1404
#if !defined (CONFIG_USER_ONLY)
1405
void cpu_dump_rfi (target_ulong RA, target_ulong msr);
1406

    
1407
void do_store_msr (void)
1408
{
1409
    T0 = hreg_store_msr(env, T0, 0);
1410
    if (T0 != 0) {
1411
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1412
        do_raise_exception(T0);
1413
    }
1414
}
1415

    
1416
static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
1417
                                    target_ulong msrm, int keep_msrh)
1418
{
1419
#if defined(TARGET_PPC64)
1420
    if (msr & (1ULL << MSR_SF)) {
1421
        nip = (uint64_t)nip;
1422
        msr &= (uint64_t)msrm;
1423
    } else {
1424
        nip = (uint32_t)nip;
1425
        msr = (uint32_t)(msr & msrm);
1426
        if (keep_msrh)
1427
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1428
    }
1429
#else
1430
    nip = (uint32_t)nip;
1431
    msr &= (uint32_t)msrm;
1432
#endif
1433
    /* XXX: beware: this is false if VLE is supported */
1434
    env->nip = nip & ~((target_ulong)0x00000003);
1435
    hreg_store_msr(env, msr, 1);
1436
#if defined (DEBUG_OP)
1437
    cpu_dump_rfi(env->nip, env->msr);
1438
#endif
1439
    /* No need to raise an exception here,
1440
     * as rfi is always the last insn of a TB
1441
     */
1442
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1443
}
1444

    
1445
void do_rfi (void)
1446
{
1447
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1448
             ~((target_ulong)0xFFFF0000), 1);
1449
}
1450

    
1451
#if defined(TARGET_PPC64)
1452
void do_rfid (void)
1453
{
1454
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1455
             ~((target_ulong)0xFFFF0000), 0);
1456
}
1457

    
1458
void do_hrfid (void)
1459
{
1460
    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1461
             ~((target_ulong)0xFFFF0000), 0);
1462
}
1463
#endif
1464
#endif
1465

    
1466
void do_tw (int flags)
1467
{
1468
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1469
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1470
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1471
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1472
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1473
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1474
    }
1475
}
1476

    
1477
#if defined(TARGET_PPC64)
1478
void do_td (int flags)
1479
{
1480
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
1481
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
1482
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
1483
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
1484
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
1485
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1486
}
1487
#endif
1488

    
1489
/*****************************************************************************/
1490
/* PowerPC 601 specific instructions (POWER bridge) */
1491
void do_POWER_abso (void)
1492
{
1493
    if ((int32_t)T0 == INT32_MIN) {
1494
        T0 = INT32_MAX;
1495
        xer_ov = 1;
1496
    } else if ((int32_t)T0 < 0) {
1497
        T0 = -T0;
1498
        xer_ov = 0;
1499
    } else {
1500
        xer_ov = 0;
1501
    }
1502
    xer_so |= xer_ov;
1503
}
1504

    
1505
void do_POWER_clcs (void)
1506
{
1507
    switch (T0) {
1508
    case 0x0CUL:
1509
        /* Instruction cache line size */
1510
        T0 = env->icache_line_size;
1511
        break;
1512
    case 0x0DUL:
1513
        /* Data cache line size */
1514
        T0 = env->dcache_line_size;
1515
        break;
1516
    case 0x0EUL:
1517
        /* Minimum cache line size */
1518
        T0 = env->icache_line_size < env->dcache_line_size ?
1519
            env->icache_line_size : env->dcache_line_size;
1520
        break;
1521
    case 0x0FUL:
1522
        /* Maximum cache line size */
1523
        T0 = env->icache_line_size > env->dcache_line_size ?
1524
            env->icache_line_size : env->dcache_line_size;
1525
        break;
1526
    default:
1527
        /* Undefined */
1528
        break;
1529
    }
1530
}
1531

    
1532
void do_POWER_div (void)
1533
{
1534
    uint64_t tmp;
1535

    
1536
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1537
        (int32_t)T1 == 0) {
1538
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1539
        env->spr[SPR_MQ] = 0;
1540
    } else {
1541
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1542
        env->spr[SPR_MQ] = tmp % T1;
1543
        T0 = tmp / (int32_t)T1;
1544
    }
1545
}
1546

    
1547
void do_POWER_divo (void)
1548
{
1549
    int64_t tmp;
1550

    
1551
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1552
        (int32_t)T1 == 0) {
1553
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1554
        env->spr[SPR_MQ] = 0;
1555
        xer_ov = 1;
1556
    } else {
1557
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1558
        env->spr[SPR_MQ] = tmp % T1;
1559
        tmp /= (int32_t)T1;
1560
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1561
            xer_ov = 1;
1562
        } else {
1563
            xer_ov = 0;
1564
        }
1565
        T0 = tmp;
1566
    }
1567
    xer_so |= xer_ov;
1568
}
1569

    
1570
void do_POWER_divs (void)
1571
{
1572
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1573
        (int32_t)T1 == 0) {
1574
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1575
        env->spr[SPR_MQ] = 0;
1576
    } else {
1577
        env->spr[SPR_MQ] = T0 % T1;
1578
        T0 = (int32_t)T0 / (int32_t)T1;
1579
    }
1580
}
1581

    
1582
void do_POWER_divso (void)
1583
{
1584
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1585
        (int32_t)T1 == 0) {
1586
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1587
        env->spr[SPR_MQ] = 0;
1588
        xer_ov = 1;
1589
    } else {
1590
        T0 = (int32_t)T0 / (int32_t)T1;
1591
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1592
        xer_ov = 0;
1593
    }
1594
    xer_so |= xer_ov;
1595
}
1596

    
1597
void do_POWER_dozo (void)
1598
{
1599
    if ((int32_t)T1 > (int32_t)T0) {
1600
        T2 = T0;
1601
        T0 = T1 - T0;
1602
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1603
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1604
            xer_ov = 1;
1605
            xer_so = 1;
1606
        } else {
1607
            xer_ov = 0;
1608
        }
1609
    } else {
1610
        T0 = 0;
1611
        xer_ov = 0;
1612
    }
1613
}
1614

    
1615
void do_POWER_maskg (void)
1616
{
1617
    uint32_t ret;
1618

    
1619
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1620
        ret = UINT32_MAX;
1621
    } else {
1622
        ret = (UINT32_MAX >> ((uint32_t)T0)) ^
1623
            ((UINT32_MAX >> ((uint32_t)T1)) >> 1);
1624
        if ((uint32_t)T0 > (uint32_t)T1)
1625
            ret = ~ret;
1626
    }
1627
    T0 = ret;
1628
}
1629

    
1630
void do_POWER_mulo (void)
1631
{
1632
    uint64_t tmp;
1633

    
1634
    tmp = (uint64_t)T0 * (uint64_t)T1;
1635
    env->spr[SPR_MQ] = tmp >> 32;
1636
    T0 = tmp;
1637
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1638
        xer_ov = 1;
1639
        xer_so = 1;
1640
    } else {
1641
        xer_ov = 0;
1642
    }
1643
}
1644

    
1645
#if !defined (CONFIG_USER_ONLY)
1646
void do_POWER_rac (void)
1647
{
1648
    mmu_ctx_t ctx;
1649
    int nb_BATs;
1650

    
1651
    /* We don't have to generate many instances of this instruction,
1652
     * as rac is supervisor only.
1653
     */
1654
    /* XXX: FIX THIS: Pretend we have no BAT */
1655
    nb_BATs = env->nb_BATs;
1656
    env->nb_BATs = 0;
1657
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
1658
        T0 = ctx.raddr;
1659
    env->nb_BATs = nb_BATs;
1660
}
1661

    
1662
void do_POWER_rfsvc (void)
1663
{
1664
    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1665
}
1666

    
1667
void do_store_hid0_601 (void)
1668
{
1669
    uint32_t hid0;
1670

    
1671
    hid0 = env->spr[SPR_HID0];
1672
    if ((T0 ^ hid0) & 0x00000008) {
1673
        /* Change current endianness */
1674
        env->hflags &= ~(1 << MSR_LE);
1675
        env->hflags_nmsr &= ~(1 << MSR_LE);
1676
        env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
1677
        env->hflags |= env->hflags_nmsr;
1678
        if (loglevel != 0) {
1679
            fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
1680
                    __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
1681
        }
1682
    }
1683
    env->spr[SPR_HID0] = T0;
1684
}
1685
#endif
1686

    
1687
/*****************************************************************************/
1688
/* 602 specific instructions */
1689
/* mfrom is the most crazy instruction ever seen, imho ! */
1690
/* Real implementation uses a ROM table. Do the same */
1691
#define USE_MFROM_ROM_TABLE
1692
void do_op_602_mfrom (void)
1693
{
1694
    if (likely(T0 < 602)) {
1695
#if defined(USE_MFROM_ROM_TABLE)
1696
#include "mfrom_table.c"
1697
        T0 = mfrom_ROM_table[T0];
1698
#else
1699
        double d;
1700
        /* Extremly decomposed:
1701
         *                    -T0 / 256
1702
         * T0 = 256 * log10(10          + 1.0) + 0.5
1703
         */
1704
        d = T0;
1705
        d = float64_div(d, 256, &env->fp_status);
1706
        d = float64_chs(d);
1707
        d = exp10(d); // XXX: use float emulation function
1708
        d = float64_add(d, 1.0, &env->fp_status);
1709
        d = log10(d); // XXX: use float emulation function
1710
        d = float64_mul(d, 256, &env->fp_status);
1711
        d = float64_add(d, 0.5, &env->fp_status);
1712
        T0 = float64_round_to_int(d, &env->fp_status);
1713
#endif
1714
    } else {
1715
        T0 = 0;
1716
    }
1717
}
1718

    
1719
/*****************************************************************************/
1720
/* Embedded PowerPC specific helpers */
1721
void do_405_check_sat (void)
1722
{
1723
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1724
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1725
        /* Saturate result */
1726
        if (T2 >> 31) {
1727
            T0 = INT32_MIN;
1728
        } else {
1729
            T0 = INT32_MAX;
1730
        }
1731
    }
1732
}
1733

    
1734
/* XXX: to be improved to check access rights when in user-mode */
1735
void do_load_dcr (void)
1736
{
1737
    target_ulong val;
1738

    
1739
    if (unlikely(env->dcr_env == NULL)) {
1740
        if (loglevel != 0) {
1741
            fprintf(logfile, "No DCR environment\n");
1742
        }
1743
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1744
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1745
    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1746
        if (loglevel != 0) {
1747
            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1748
        }
1749
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1750
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1751
    } else {
1752
        T0 = val;
1753
    }
1754
}
1755

    
1756
void do_store_dcr (void)
1757
{
1758
    if (unlikely(env->dcr_env == NULL)) {
1759
        if (loglevel != 0) {
1760
            fprintf(logfile, "No DCR environment\n");
1761
        }
1762
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1763
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1764
    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1765
        if (loglevel != 0) {
1766
            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1767
        }
1768
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1769
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1770
    }
1771
}
1772

    
1773
#if !defined(CONFIG_USER_ONLY)
1774
void do_40x_rfci (void)
1775
{
1776
    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1777
             ~((target_ulong)0xFFFF0000), 0);
1778
}
1779

    
1780
void do_rfci (void)
1781
{
1782
    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1783
             ~((target_ulong)0x3FFF0000), 0);
1784
}
1785

    
1786
void do_rfdi (void)
1787
{
1788
    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1789
             ~((target_ulong)0x3FFF0000), 0);
1790
}
1791

    
1792
void do_rfmci (void)
1793
{
1794
    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1795
             ~((target_ulong)0x3FFF0000), 0);
1796
}
1797

    
1798
void do_load_403_pb (int num)
1799
{
1800
    T0 = env->pb[num];
1801
}
1802

    
1803
void do_store_403_pb (int num)
1804
{
1805
    if (likely(env->pb[num] != T0)) {
1806
        env->pb[num] = T0;
1807
        /* Should be optimized */
1808
        tlb_flush(env, 1);
1809
    }
1810
}
1811
#endif
1812

    
1813
/* 440 specific */
1814
void do_440_dlmzb (void)
1815
{
1816
    target_ulong mask;
1817
    int i;
1818

    
1819
    i = 1;
1820
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1821
        if ((T0 & mask) == 0)
1822
            goto done;
1823
        i++;
1824
    }
1825
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1826
        if ((T1 & mask) == 0)
1827
            break;
1828
        i++;
1829
    }
1830
 done:
1831
    T0 = i;
1832
}
1833

    
1834
/* SPE extension helpers */
1835
/* Use a table to make this quicker */
1836
static uint8_t hbrev[16] = {
1837
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1838
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1839
};
1840

    
1841
static always_inline uint8_t byte_reverse (uint8_t val)
1842
{
1843
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1844
}
1845

    
1846
static always_inline uint32_t word_reverse (uint32_t val)
1847
{
1848
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1849
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1850
}
1851

    
1852
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
1853
void do_brinc (void)
1854
{
1855
    uint32_t a, b, d, mask;
1856

    
1857
    mask = UINT32_MAX >> (32 - MASKBITS);
1858
    a = T0 & mask;
1859
    b = T1 & mask;
1860
    d = word_reverse(1 + word_reverse(a | ~b));
1861
    T0 = (T0 & ~mask) | (d & b);
1862
}
1863

    
1864
#define DO_SPE_OP2(name)                                                      \
1865
void do_ev##name (void)                                                       \
1866
{                                                                             \
1867
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
1868
        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
1869
}
1870

    
1871
#define DO_SPE_OP1(name)                                                      \
1872
void do_ev##name (void)                                                       \
1873
{                                                                             \
1874
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1875
        (uint64_t)_do_e##name(T0_64);                                         \
1876
}
1877

    
1878
/* Fixed-point vector arithmetic */
1879
static always_inline uint32_t _do_eabs (uint32_t val)
1880
{
1881
    if ((val & 0x80000000) && val != 0x80000000)
1882
        val -= val;
1883

    
1884
    return val;
1885
}
1886

    
1887
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1888
{
1889
    return op1 + op2;
1890
}
1891

    
1892
static always_inline int _do_ecntlsw (uint32_t val)
1893
{
1894
    if (val & 0x80000000)
1895
        return clz32(~val);
1896
    else
1897
        return clz32(val);
1898
}
1899

    
1900
static always_inline int _do_ecntlzw (uint32_t val)
1901
{
1902
    return clz32(val);
1903
}
1904

    
1905
static always_inline uint32_t _do_eneg (uint32_t val)
1906
{
1907
    if (val != 0x80000000)
1908
        val -= val;
1909

    
1910
    return val;
1911
}
1912

    
1913
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1914
{
1915
    return rotl32(op1, op2);
1916
}
1917

    
1918
static always_inline uint32_t _do_erndw (uint32_t val)
1919
{
1920
    return (val + 0x000080000000) & 0xFFFF0000;
1921
}
1922

    
1923
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1924
{
1925
    /* No error here: 6 bits are used */
1926
    return op1 << (op2 & 0x3F);
1927
}
1928

    
1929
static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1930
{
1931
    /* No error here: 6 bits are used */
1932
    return op1 >> (op2 & 0x3F);
1933
}
1934

    
1935
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1936
{
1937
    /* No error here: 6 bits are used */
1938
    return op1 >> (op2 & 0x3F);
1939
}
1940

    
1941
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1942
{
1943
    return op2 - op1;
1944
}
1945

    
1946
/* evabs */
1947
DO_SPE_OP1(abs);
1948
/* evaddw */
1949
DO_SPE_OP2(addw);
1950
/* evcntlsw */
1951
DO_SPE_OP1(cntlsw);
1952
/* evcntlzw */
1953
DO_SPE_OP1(cntlzw);
1954
/* evneg */
1955
DO_SPE_OP1(neg);
1956
/* evrlw */
1957
DO_SPE_OP2(rlw);
1958
/* evrnd */
1959
DO_SPE_OP1(rndw);
1960
/* evslw */
1961
DO_SPE_OP2(slw);
1962
/* evsrws */
1963
DO_SPE_OP2(srws);
1964
/* evsrwu */
1965
DO_SPE_OP2(srwu);
1966
/* evsubfw */
1967
DO_SPE_OP2(subfw);
1968

    
1969
/* evsel is a little bit more complicated... */
1970
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1971
{
1972
    if (n)
1973
        return op1;
1974
    else
1975
        return op2;
1976
}
1977

    
1978
void do_evsel (void)
1979
{
1980
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1981
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1982
}
1983

    
1984
/* Fixed-point vector comparisons */
1985
#define DO_SPE_CMP(name)                                                      \
1986
void do_ev##name (void)                                                       \
1987
{                                                                             \
1988
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1989
                                               T1_64 >> 32) << 32,            \
1990
                         _do_e##name(T0_64, T1_64));                          \
1991
}
1992

    
1993
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1994
{
1995
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1996
}
1997
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1998
{
1999
    return op1 == op2 ? 1 : 0;
2000
}
2001

    
2002
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
2003
{
2004
    return op1 > op2 ? 1 : 0;
2005
}
2006

    
2007
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
2008
{
2009
    return op1 > op2 ? 1 : 0;
2010
}
2011

    
2012
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
2013
{
2014
    return op1 < op2 ? 1 : 0;
2015
}
2016

    
2017
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
2018
{
2019
    return op1 < op2 ? 1 : 0;
2020
}
2021

    
2022
/* evcmpeq */
2023
DO_SPE_CMP(cmpeq);
2024
/* evcmpgts */
2025
DO_SPE_CMP(cmpgts);
2026
/* evcmpgtu */
2027
DO_SPE_CMP(cmpgtu);
2028
/* evcmplts */
2029
DO_SPE_CMP(cmplts);
2030
/* evcmpltu */
2031
DO_SPE_CMP(cmpltu);
2032

    
2033
/* Single precision floating-point conversions from/to integer */
2034
static always_inline uint32_t _do_efscfsi (int32_t val)
2035
{
2036
    CPU_FloatU u;
2037

    
2038
    u.f = int32_to_float32(val, &env->spe_status);
2039

    
2040
    return u.l;
2041
}
2042

    
2043
static always_inline uint32_t _do_efscfui (uint32_t val)
2044
{
2045
    CPU_FloatU u;
2046

    
2047
    u.f = uint32_to_float32(val, &env->spe_status);
2048

    
2049
    return u.l;
2050
}
2051

    
2052
static always_inline int32_t _do_efsctsi (uint32_t val)
2053
{
2054
    CPU_FloatU u;
2055

    
2056
    u.l = val;
2057
    /* NaN are not treated the same way IEEE 754 does */
2058
    if (unlikely(isnan(u.f)))
2059
        return 0;
2060

    
2061
    return float32_to_int32(u.f, &env->spe_status);
2062
}
2063

    
2064
static always_inline uint32_t _do_efsctui (uint32_t val)
2065
{
2066
    CPU_FloatU u;
2067

    
2068
    u.l = val;
2069
    /* NaN are not treated the same way IEEE 754 does */
2070
    if (unlikely(isnan(u.f)))
2071
        return 0;
2072

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

    
2076
static always_inline int32_t _do_efsctsiz (uint32_t val)
2077
{
2078
    CPU_FloatU u;
2079

    
2080
    u.l = val;
2081
    /* NaN are not treated the same way IEEE 754 does */
2082
    if (unlikely(isnan(u.f)))
2083
        return 0;
2084

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

    
2088
static always_inline uint32_t _do_efsctuiz (uint32_t val)
2089
{
2090
    CPU_FloatU u;
2091

    
2092
    u.l = val;
2093
    /* NaN are not treated the same way IEEE 754 does */
2094
    if (unlikely(isnan(u.f)))
2095
        return 0;
2096

    
2097
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2098
}
2099

    
2100
void do_efscfsi (void)
2101
{
2102
    T0_64 = _do_efscfsi(T0_64);
2103
}
2104

    
2105
void do_efscfui (void)
2106
{
2107
    T0_64 = _do_efscfui(T0_64);
2108
}
2109

    
2110
void do_efsctsi (void)
2111
{
2112
    T0_64 = _do_efsctsi(T0_64);
2113
}
2114

    
2115
void do_efsctui (void)
2116
{
2117
    T0_64 = _do_efsctui(T0_64);
2118
}
2119

    
2120
void do_efsctsiz (void)
2121
{
2122
    T0_64 = _do_efsctsiz(T0_64);
2123
}
2124

    
2125
void do_efsctuiz (void)
2126
{
2127
    T0_64 = _do_efsctuiz(T0_64);
2128
}
2129

    
2130
/* Single precision floating-point conversion to/from fractional */
2131
static always_inline uint32_t _do_efscfsf (uint32_t val)
2132
{
2133
    CPU_FloatU u;
2134
    float32 tmp;
2135

    
2136
    u.f = int32_to_float32(val, &env->spe_status);
2137
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2138
    u.f = float32_div(u.f, tmp, &env->spe_status);
2139

    
2140
    return u.l;
2141
}
2142

    
2143
static always_inline uint32_t _do_efscfuf (uint32_t val)
2144
{
2145
    CPU_FloatU u;
2146
    float32 tmp;
2147

    
2148
    u.f = uint32_to_float32(val, &env->spe_status);
2149
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2150
    u.f = float32_div(u.f, tmp, &env->spe_status);
2151

    
2152
    return u.l;
2153
}
2154

    
2155
static always_inline int32_t _do_efsctsf (uint32_t val)
2156
{
2157
    CPU_FloatU u;
2158
    float32 tmp;
2159

    
2160
    u.l = val;
2161
    /* NaN are not treated the same way IEEE 754 does */
2162
    if (unlikely(isnan(u.f)))
2163
        return 0;
2164
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2165
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2166

    
2167
    return float32_to_int32(u.f, &env->spe_status);
2168
}
2169

    
2170
static always_inline uint32_t _do_efsctuf (uint32_t val)
2171
{
2172
    CPU_FloatU u;
2173
    float32 tmp;
2174

    
2175
    u.l = val;
2176
    /* NaN are not treated the same way IEEE 754 does */
2177
    if (unlikely(isnan(u.f)))
2178
        return 0;
2179
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2180
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2181

    
2182
    return float32_to_uint32(u.f, &env->spe_status);
2183
}
2184

    
2185
static always_inline int32_t _do_efsctsfz (uint32_t val)
2186
{
2187
    CPU_FloatU u;
2188
    float32 tmp;
2189

    
2190
    u.l = val;
2191
    /* NaN are not treated the same way IEEE 754 does */
2192
    if (unlikely(isnan(u.f)))
2193
        return 0;
2194
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2195
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2196

    
2197
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2198
}
2199

    
2200
static always_inline uint32_t _do_efsctufz (uint32_t val)
2201
{
2202
    CPU_FloatU u;
2203
    float32 tmp;
2204

    
2205
    u.l = val;
2206
    /* NaN are not treated the same way IEEE 754 does */
2207
    if (unlikely(isnan(u.f)))
2208
        return 0;
2209
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2210
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2211

    
2212
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2213
}
2214

    
2215
void do_efscfsf (void)
2216
{
2217
    T0_64 = _do_efscfsf(T0_64);
2218
}
2219

    
2220
void do_efscfuf (void)
2221
{
2222
    T0_64 = _do_efscfuf(T0_64);
2223
}
2224

    
2225
void do_efsctsf (void)
2226
{
2227
    T0_64 = _do_efsctsf(T0_64);
2228
}
2229

    
2230
void do_efsctuf (void)
2231
{
2232
    T0_64 = _do_efsctuf(T0_64);
2233
}
2234

    
2235
void do_efsctsfz (void)
2236
{
2237
    T0_64 = _do_efsctsfz(T0_64);
2238
}
2239

    
2240
void do_efsctufz (void)
2241
{
2242
    T0_64 = _do_efsctufz(T0_64);
2243
}
2244

    
2245
/* Double precision floating point helpers */
2246
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
2247
{
2248
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2249
    return _do_efdtstlt(op1, op2);
2250
}
2251

    
2252
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
2253
{
2254
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2255
    return _do_efdtstgt(op1, op2);
2256
}
2257

    
2258
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
2259
{
2260
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2261
    return _do_efdtsteq(op1, op2);
2262
}
2263

    
2264
void do_efdcmplt (void)
2265
{
2266
    T0 = _do_efdcmplt(T0_64, T1_64);
2267
}
2268

    
2269
void do_efdcmpgt (void)
2270
{
2271
    T0 = _do_efdcmpgt(T0_64, T1_64);
2272
}
2273

    
2274
void do_efdcmpeq (void)
2275
{
2276
    T0 = _do_efdcmpeq(T0_64, T1_64);
2277
}
2278

    
2279
/* Double precision floating-point conversion to/from integer */
2280
static always_inline uint64_t _do_efdcfsi (int64_t val)
2281
{
2282
    CPU_DoubleU u;
2283

    
2284
    u.d = int64_to_float64(val, &env->spe_status);
2285

    
2286
    return u.ll;
2287
}
2288

    
2289
static always_inline uint64_t _do_efdcfui (uint64_t val)
2290
{
2291
    CPU_DoubleU u;
2292

    
2293
    u.d = uint64_to_float64(val, &env->spe_status);
2294

    
2295
    return u.ll;
2296
}
2297

    
2298
static always_inline int64_t _do_efdctsi (uint64_t val)
2299
{
2300
    CPU_DoubleU u;
2301

    
2302
    u.ll = val;
2303
    /* NaN are not treated the same way IEEE 754 does */
2304
    if (unlikely(isnan(u.d)))
2305
        return 0;
2306

    
2307
    return float64_to_int64(u.d, &env->spe_status);
2308
}
2309

    
2310
static always_inline uint64_t _do_efdctui (uint64_t val)
2311
{
2312
    CPU_DoubleU u;
2313

    
2314
    u.ll = val;
2315
    /* NaN are not treated the same way IEEE 754 does */
2316
    if (unlikely(isnan(u.d)))
2317
        return 0;
2318

    
2319
    return float64_to_uint64(u.d, &env->spe_status);
2320
}
2321

    
2322
static always_inline int64_t _do_efdctsiz (uint64_t val)
2323
{
2324
    CPU_DoubleU u;
2325

    
2326
    u.ll = val;
2327
    /* NaN are not treated the same way IEEE 754 does */
2328
    if (unlikely(isnan(u.d)))
2329
        return 0;
2330

    
2331
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2332
}
2333

    
2334
static always_inline uint64_t _do_efdctuiz (uint64_t val)
2335
{
2336
    CPU_DoubleU u;
2337

    
2338
    u.ll = val;
2339
    /* NaN are not treated the same way IEEE 754 does */
2340
    if (unlikely(isnan(u.d)))
2341
        return 0;
2342

    
2343
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2344
}
2345

    
2346
void do_efdcfsi (void)
2347
{
2348
    T0_64 = _do_efdcfsi(T0_64);
2349
}
2350

    
2351
void do_efdcfui (void)
2352
{
2353
    T0_64 = _do_efdcfui(T0_64);
2354
}
2355

    
2356
void do_efdctsi (void)
2357
{
2358
    T0_64 = _do_efdctsi(T0_64);
2359
}
2360

    
2361
void do_efdctui (void)
2362
{
2363
    T0_64 = _do_efdctui(T0_64);
2364
}
2365

    
2366
void do_efdctsiz (void)
2367
{
2368
    T0_64 = _do_efdctsiz(T0_64);
2369
}
2370

    
2371
void do_efdctuiz (void)
2372
{
2373
    T0_64 = _do_efdctuiz(T0_64);
2374
}
2375

    
2376
/* Double precision floating-point conversion to/from fractional */
2377
static always_inline uint64_t _do_efdcfsf (int64_t val)
2378
{
2379
    CPU_DoubleU u;
2380
    float64 tmp;
2381

    
2382
    u.d = int32_to_float64(val, &env->spe_status);
2383
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2384
    u.d = float64_div(u.d, tmp, &env->spe_status);
2385

    
2386
    return u.ll;
2387
}
2388

    
2389
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2390
{
2391
    CPU_DoubleU u;
2392
    float64 tmp;
2393

    
2394
    u.d = uint32_to_float64(val, &env->spe_status);
2395
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2396
    u.d = float64_div(u.d, tmp, &env->spe_status);
2397

    
2398
    return u.ll;
2399
}
2400

    
2401
static always_inline int64_t _do_efdctsf (uint64_t val)
2402
{
2403
    CPU_DoubleU u;
2404
    float64 tmp;
2405

    
2406
    u.ll = val;
2407
    /* NaN are not treated the same way IEEE 754 does */
2408
    if (unlikely(isnan(u.d)))
2409
        return 0;
2410
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2411
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2412

    
2413
    return float64_to_int32(u.d, &env->spe_status);
2414
}
2415

    
2416
static always_inline uint64_t _do_efdctuf (uint64_t val)
2417
{
2418
    CPU_DoubleU u;
2419
    float64 tmp;
2420

    
2421
    u.ll = val;
2422
    /* NaN are not treated the same way IEEE 754 does */
2423
    if (unlikely(isnan(u.d)))
2424
        return 0;
2425
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2426
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2427

    
2428
    return float64_to_uint32(u.d, &env->spe_status);
2429
}
2430

    
2431
static always_inline int64_t _do_efdctsfz (uint64_t val)
2432
{
2433
    CPU_DoubleU u;
2434
    float64 tmp;
2435

    
2436
    u.ll = val;
2437
    /* NaN are not treated the same way IEEE 754 does */
2438
    if (unlikely(isnan(u.d)))
2439
        return 0;
2440
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2441
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2442

    
2443
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2444
}
2445

    
2446
static always_inline uint64_t _do_efdctufz (uint64_t val)
2447
{
2448
    CPU_DoubleU u;
2449
    float64 tmp;
2450

    
2451
    u.ll = val;
2452
    /* NaN are not treated the same way IEEE 754 does */
2453
    if (unlikely(isnan(u.d)))
2454
        return 0;
2455
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2456
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2457

    
2458
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2459
}
2460

    
2461
void do_efdcfsf (void)
2462
{
2463
    T0_64 = _do_efdcfsf(T0_64);
2464
}
2465

    
2466
void do_efdcfuf (void)
2467
{
2468
    T0_64 = _do_efdcfuf(T0_64);
2469
}
2470

    
2471
void do_efdctsf (void)
2472
{
2473
    T0_64 = _do_efdctsf(T0_64);
2474
}
2475

    
2476
void do_efdctuf (void)
2477
{
2478
    T0_64 = _do_efdctuf(T0_64);
2479
}
2480

    
2481
void do_efdctsfz (void)
2482
{
2483
    T0_64 = _do_efdctsfz(T0_64);
2484
}
2485

    
2486
void do_efdctufz (void)
2487
{
2488
    T0_64 = _do_efdctufz(T0_64);
2489
}
2490

    
2491
/* Floating point conversion between single and double precision */
2492
static always_inline uint32_t _do_efscfd (uint64_t val)
2493
{
2494
    CPU_DoubleU u1;
2495
    CPU_FloatU u2;
2496

    
2497
    u1.ll = val;
2498
    u2.f = float64_to_float32(u1.d, &env->spe_status);
2499

    
2500
    return u2.l;
2501
}
2502

    
2503
static always_inline uint64_t _do_efdcfs (uint32_t val)
2504
{
2505
    CPU_DoubleU u2;
2506
    CPU_FloatU u1;
2507

    
2508
    u1.l = val;
2509
    u2.d = float32_to_float64(u1.f, &env->spe_status);
2510

    
2511
    return u2.ll;
2512
}
2513

    
2514
void do_efscfd (void)
2515
{
2516
    T0_64 = _do_efscfd(T0_64);
2517
}
2518

    
2519
void do_efdcfs (void)
2520
{
2521
    T0_64 = _do_efdcfs(T0_64);
2522
}
2523

    
2524
/* Single precision fixed-point vector arithmetic */
2525
/* evfsabs */
2526
DO_SPE_OP1(fsabs);
2527
/* evfsnabs */
2528
DO_SPE_OP1(fsnabs);
2529
/* evfsneg */
2530
DO_SPE_OP1(fsneg);
2531
/* evfsadd */
2532
DO_SPE_OP2(fsadd);
2533
/* evfssub */
2534
DO_SPE_OP2(fssub);
2535
/* evfsmul */
2536
DO_SPE_OP2(fsmul);
2537
/* evfsdiv */
2538
DO_SPE_OP2(fsdiv);
2539

    
2540
/* Single-precision floating-point comparisons */
2541
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2542
{
2543
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2544
    return _do_efststlt(op1, op2);
2545
}
2546

    
2547
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2548
{
2549
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2550
    return _do_efststgt(op1, op2);
2551
}
2552

    
2553
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2554
{
2555
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2556
    return _do_efststeq(op1, op2);
2557
}
2558

    
2559
void do_efscmplt (void)
2560
{
2561
    T0 = _do_efscmplt(T0_64, T1_64);
2562
}
2563

    
2564
void do_efscmpgt (void)
2565
{
2566
    T0 = _do_efscmpgt(T0_64, T1_64);
2567
}
2568

    
2569
void do_efscmpeq (void)
2570
{
2571
    T0 = _do_efscmpeq(T0_64, T1_64);
2572
}
2573

    
2574
/* Single-precision floating-point vector comparisons */
2575
/* evfscmplt */
2576
DO_SPE_CMP(fscmplt);
2577
/* evfscmpgt */
2578
DO_SPE_CMP(fscmpgt);
2579
/* evfscmpeq */
2580
DO_SPE_CMP(fscmpeq);
2581
/* evfststlt */
2582
DO_SPE_CMP(fststlt);
2583
/* evfststgt */
2584
DO_SPE_CMP(fststgt);
2585
/* evfststeq */
2586
DO_SPE_CMP(fststeq);
2587

    
2588
/* Single-precision floating-point vector conversions */
2589
/* evfscfsi */
2590
DO_SPE_OP1(fscfsi);
2591
/* evfscfui */
2592
DO_SPE_OP1(fscfui);
2593
/* evfscfuf */
2594
DO_SPE_OP1(fscfuf);
2595
/* evfscfsf */
2596
DO_SPE_OP1(fscfsf);
2597
/* evfsctsi */
2598
DO_SPE_OP1(fsctsi);
2599
/* evfsctui */
2600
DO_SPE_OP1(fsctui);
2601
/* evfsctsiz */
2602
DO_SPE_OP1(fsctsiz);
2603
/* evfsctuiz */
2604
DO_SPE_OP1(fsctuiz);
2605
/* evfsctsf */
2606
DO_SPE_OP1(fsctsf);
2607
/* evfsctuf */
2608
DO_SPE_OP1(fsctuf);
2609

    
2610
/*****************************************************************************/
2611
/* Softmmu support */
2612
#if !defined (CONFIG_USER_ONLY)
2613

    
2614
#define MMUSUFFIX _mmu
2615

    
2616
#define SHIFT 0
2617
#include "softmmu_template.h"
2618

    
2619
#define SHIFT 1
2620
#include "softmmu_template.h"
2621

    
2622
#define SHIFT 2
2623
#include "softmmu_template.h"
2624

    
2625
#define SHIFT 3
2626
#include "softmmu_template.h"
2627

    
2628
/* try to fill the TLB and return an exception if error. If retaddr is
2629
   NULL, it means that the function was called in C code (i.e. not
2630
   from generated code or from helper.c) */
2631
/* XXX: fix it to restore all registers */
2632
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2633
{
2634
    TranslationBlock *tb;
2635
    CPUState *saved_env;
2636
    unsigned long pc;
2637
    int ret;
2638

    
2639
    /* XXX: hack to restore env in all cases, even if not called from
2640
       generated code */
2641
    saved_env = env;
2642
    env = cpu_single_env;
2643
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2644
    if (unlikely(ret != 0)) {
2645
        if (likely(retaddr)) {
2646
            /* now we have a real cpu fault */
2647
            pc = (unsigned long)retaddr;
2648
            tb = tb_find_pc(pc);
2649
            if (likely(tb)) {
2650
                /* the PC is inside the translated code. It means that we have
2651
                   a virtual CPU fault */
2652
                cpu_restore_state(tb, env, pc, NULL);
2653
            }
2654
        }
2655
        do_raise_exception_err(env->exception_index, env->error_code);
2656
    }
2657
    env = saved_env;
2658
}
2659

    
2660
/* Software driven TLBs management */
2661
/* PowerPC 602/603 software TLB load instructions helpers */
2662
void do_load_6xx_tlb (int is_code)
2663
{
2664
    target_ulong RPN, CMP, EPN;
2665
    int way;
2666

    
2667
    RPN = env->spr[SPR_RPA];
2668
    if (is_code) {
2669
        CMP = env->spr[SPR_ICMP];
2670
        EPN = env->spr[SPR_IMISS];
2671
    } else {
2672
        CMP = env->spr[SPR_DCMP];
2673
        EPN = env->spr[SPR_DMISS];
2674
    }
2675
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2676
#if defined (DEBUG_SOFTWARE_TLB)
2677
    if (loglevel != 0) {
2678
        fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2679
                " PTE1 " ADDRX " way %d\n",
2680
                __func__, T0, EPN, CMP, RPN, way);
2681
    }
2682
#endif
2683
    /* Store this TLB */
2684
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2685
                     way, is_code, CMP, RPN);
2686
}
2687

    
2688
void do_load_74xx_tlb (int is_code)
2689
{
2690
    target_ulong RPN, CMP, EPN;
2691
    int way;
2692

    
2693
    RPN = env->spr[SPR_PTELO];
2694
    CMP = env->spr[SPR_PTEHI];
2695
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2696
    way = env->spr[SPR_TLBMISS] & 0x3;
2697
#if defined (DEBUG_SOFTWARE_TLB)
2698
    if (loglevel != 0) {
2699
        fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2700
                " PTE1 " ADDRX " way %d\n",
2701
                __func__, T0, EPN, CMP, RPN, way);
2702
    }
2703
#endif
2704
    /* Store this TLB */
2705
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2706
                     way, is_code, CMP, RPN);
2707
}
2708

    
2709
static always_inline target_ulong booke_tlb_to_page_size (int size)
2710
{
2711
    return 1024 << (2 * size);
2712
}
2713

    
2714
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
2715
{
2716
    int size;
2717

    
2718
    switch (page_size) {
2719
    case 0x00000400UL:
2720
        size = 0x0;
2721
        break;
2722
    case 0x00001000UL:
2723
        size = 0x1;
2724
        break;
2725
    case 0x00004000UL:
2726
        size = 0x2;
2727
        break;
2728
    case 0x00010000UL:
2729
        size = 0x3;
2730
        break;
2731
    case 0x00040000UL:
2732
        size = 0x4;
2733
        break;
2734
    case 0x00100000UL:
2735
        size = 0x5;
2736
        break;
2737
    case 0x00400000UL:
2738
        size = 0x6;
2739
        break;
2740
    case 0x01000000UL:
2741
        size = 0x7;
2742
        break;
2743
    case 0x04000000UL:
2744
        size = 0x8;
2745
        break;
2746
    case 0x10000000UL:
2747
        size = 0x9;
2748
        break;
2749
    case 0x40000000UL:
2750
        size = 0xA;
2751
        break;
2752
#if defined (TARGET_PPC64)
2753
    case 0x000100000000ULL:
2754
        size = 0xB;
2755
        break;
2756
    case 0x000400000000ULL:
2757
        size = 0xC;
2758
        break;
2759
    case 0x001000000000ULL:
2760
        size = 0xD;
2761
        break;
2762
    case 0x004000000000ULL:
2763
        size = 0xE;
2764
        break;
2765
    case 0x010000000000ULL:
2766
        size = 0xF;
2767
        break;
2768
#endif
2769
    default:
2770
        size = -1;
2771
        break;
2772
    }
2773

    
2774
    return size;
2775
}
2776

    
2777
/* Helpers for 4xx TLB management */
2778
void do_4xx_tlbre_lo (void)
2779
{
2780
    ppcemb_tlb_t *tlb;
2781
    int size;
2782

    
2783
    T0 &= 0x3F;
2784
    tlb = &env->tlb[T0].tlbe;
2785
    T0 = tlb->EPN;
2786
    if (tlb->prot & PAGE_VALID)
2787
        T0 |= 0x400;
2788
    size = booke_page_size_to_tlb(tlb->size);
2789
    if (size < 0 || size > 0x7)
2790
        size = 1;
2791
    T0 |= size << 7;
2792
    env->spr[SPR_40x_PID] = tlb->PID;
2793
}
2794

    
2795
void do_4xx_tlbre_hi (void)
2796
{
2797
    ppcemb_tlb_t *tlb;
2798

    
2799
    T0 &= 0x3F;
2800
    tlb = &env->tlb[T0].tlbe;
2801
    T0 = tlb->RPN;
2802
    if (tlb->prot & PAGE_EXEC)
2803
        T0 |= 0x200;
2804
    if (tlb->prot & PAGE_WRITE)
2805
        T0 |= 0x100;
2806
}
2807

    
2808
void do_4xx_tlbwe_hi (void)
2809
{
2810
    ppcemb_tlb_t *tlb;
2811
    target_ulong page, end;
2812

    
2813
#if defined (DEBUG_SOFTWARE_TLB)
2814
    if (loglevel != 0) {
2815
        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2816
    }
2817
#endif
2818
    T0 &= 0x3F;
2819
    tlb = &env->tlb[T0].tlbe;
2820
    /* Invalidate previous TLB (if it's valid) */
2821
    if (tlb->prot & PAGE_VALID) {
2822
        end = tlb->EPN + tlb->size;
2823
#if defined (DEBUG_SOFTWARE_TLB)
2824
        if (loglevel != 0) {
2825
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2826
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2827
        }
2828
#endif
2829
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2830
            tlb_flush_page(env, page);
2831
    }
2832
    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2833
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2834
     * If this ever occurs, one should use the ppcemb target instead
2835
     * of the ppc or ppc64 one
2836
     */
2837
    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2838
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2839
                  "are not supported (%d)\n",
2840
                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
2841
    }
2842
    tlb->EPN = T1 & ~(tlb->size - 1);
2843
    if (T1 & 0x40)
2844
        tlb->prot |= PAGE_VALID;
2845
    else
2846
        tlb->prot &= ~PAGE_VALID;
2847
    if (T1 & 0x20) {
2848
        /* XXX: TO BE FIXED */
2849
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2850
    }
2851
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2852
    tlb->attr = T1 & 0xFF;
2853
#if defined (DEBUG_SOFTWARE_TLB)
2854
    if (loglevel != 0) {
2855
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2856
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2857
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2858
                tlb->prot & PAGE_READ ? 'r' : '-',
2859
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2860
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2861
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2862
    }
2863
#endif
2864
    /* Invalidate new TLB (if valid) */
2865
    if (tlb->prot & PAGE_VALID) {
2866
        end = tlb->EPN + tlb->size;
2867
#if defined (DEBUG_SOFTWARE_TLB)
2868
        if (loglevel != 0) {
2869
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2870
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2871
        }
2872
#endif
2873
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2874
            tlb_flush_page(env, page);
2875
    }
2876
}
2877

    
2878
void do_4xx_tlbwe_lo (void)
2879
{
2880
    ppcemb_tlb_t *tlb;
2881

    
2882
#if defined (DEBUG_SOFTWARE_TLB)
2883
    if (loglevel != 0) {
2884
        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2885
    }
2886
#endif
2887
    T0 &= 0x3F;
2888
    tlb = &env->tlb[T0].tlbe;
2889
    tlb->RPN = T1 & 0xFFFFFC00;
2890
    tlb->prot = PAGE_READ;
2891
    if (T1 & 0x200)
2892
        tlb->prot |= PAGE_EXEC;
2893
    if (T1 & 0x100)
2894
        tlb->prot |= PAGE_WRITE;
2895
#if defined (DEBUG_SOFTWARE_TLB)
2896
    if (loglevel != 0) {
2897
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2898
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2899
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2900
                tlb->prot & PAGE_READ ? 'r' : '-',
2901
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2902
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2903
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2904
    }
2905
#endif
2906
}
2907

    
2908
/* PowerPC 440 TLB management */
2909
void do_440_tlbwe (int word)
2910
{
2911
    ppcemb_tlb_t *tlb;
2912
    target_ulong EPN, RPN, size;
2913
    int do_flush_tlbs;
2914

    
2915
#if defined (DEBUG_SOFTWARE_TLB)
2916
    if (loglevel != 0) {
2917
        fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
2918
                __func__, word, T0, T1);
2919
    }
2920
#endif
2921
    do_flush_tlbs = 0;
2922
    T0 &= 0x3F;
2923
    tlb = &env->tlb[T0].tlbe;
2924
    switch (word) {
2925
    default:
2926
        /* Just here to please gcc */
2927
    case 0:
2928
        EPN = T1 & 0xFFFFFC00;
2929
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2930
            do_flush_tlbs = 1;
2931
        tlb->EPN = EPN;
2932
        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2933
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2934
            do_flush_tlbs = 1;
2935
        tlb->size = size;
2936
        tlb->attr &= ~0x1;
2937
        tlb->attr |= (T1 >> 8) & 1;
2938
        if (T1 & 0x200) {
2939
            tlb->prot |= PAGE_VALID;
2940
        } else {
2941
            if (tlb->prot & PAGE_VALID) {
2942
                tlb->prot &= ~PAGE_VALID;
2943
                do_flush_tlbs = 1;
2944
            }
2945
        }
2946
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2947
        if (do_flush_tlbs)
2948
            tlb_flush(env, 1);
2949
        break;
2950
    case 1:
2951
        RPN = T1 & 0xFFFFFC0F;
2952
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2953
            tlb_flush(env, 1);
2954
        tlb->RPN = RPN;
2955
        break;
2956
    case 2:
2957
        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2958
        tlb->prot = tlb->prot & PAGE_VALID;
2959
        if (T1 & 0x1)
2960
            tlb->prot |= PAGE_READ << 4;
2961
        if (T1 & 0x2)
2962
            tlb->prot |= PAGE_WRITE << 4;
2963
        if (T1 & 0x4)
2964
            tlb->prot |= PAGE_EXEC << 4;
2965
        if (T1 & 0x8)
2966
            tlb->prot |= PAGE_READ;
2967
        if (T1 & 0x10)
2968
            tlb->prot |= PAGE_WRITE;
2969
        if (T1 & 0x20)
2970
            tlb->prot |= PAGE_EXEC;
2971
        break;
2972
    }
2973
}
2974

    
2975
void do_440_tlbre (int word)
2976
{
2977
    ppcemb_tlb_t *tlb;
2978
    int size;
2979

    
2980
    T0 &= 0x3F;
2981
    tlb = &env->tlb[T0].tlbe;
2982
    switch (word) {
2983
    default:
2984
        /* Just here to please gcc */
2985
    case 0:
2986
        T0 = tlb->EPN;
2987
        size = booke_page_size_to_tlb(tlb->size);
2988
        if (size < 0 || size > 0xF)
2989
            size = 1;
2990
        T0 |= size << 4;
2991
        if (tlb->attr & 0x1)
2992
            T0 |= 0x100;
2993
        if (tlb->prot & PAGE_VALID)
2994
            T0 |= 0x200;
2995
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2996
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2997
        break;
2998
    case 1:
2999
        T0 = tlb->RPN;
3000
        break;
3001
    case 2:
3002
        T0 = tlb->attr & ~0x1;
3003
        if (tlb->prot & (PAGE_READ << 4))
3004
            T0 |= 0x1;
3005
        if (tlb->prot & (PAGE_WRITE << 4))
3006
            T0 |= 0x2;
3007
        if (tlb->prot & (PAGE_EXEC << 4))
3008
            T0 |= 0x4;
3009
        if (tlb->prot & PAGE_READ)
3010
            T0 |= 0x8;
3011
        if (tlb->prot & PAGE_WRITE)
3012
            T0 |= 0x10;
3013
        if (tlb->prot & PAGE_EXEC)
3014
            T0 |= 0x20;
3015
        break;
3016
    }
3017
}
3018
#endif /* !CONFIG_USER_ONLY */