Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 61c04807

History | View | Annotate | Download (75 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
target_ulong do_load_cr (void)
72
{
73
    return (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
target_ulong do_popcntb (target_ulong t0)
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
    return ret;
441
}
442

    
443
#if defined(TARGET_PPC64)
444
target_ulong do_popcntb_64 (target_ulong t0)
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
    return 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 (target_ulong t0)
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
#if defined (TARGET_PPC64)
1417
void do_store_msr_32 (target_ulong t0)
1418
{
1419
    t0 = (env->msr & ~0xFFFFFFFFULL) | (t0 & 0xFFFFFFFF);
1420
    do_store_msr(t0);
1421
}
1422
#endif
1423

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

    
1453
void do_rfi (void)
1454
{
1455
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1456
             ~((target_ulong)0xFFFF0000), 1);
1457
}
1458

    
1459
#if defined(TARGET_PPC64)
1460
void do_rfid (void)
1461
{
1462
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1463
             ~((target_ulong)0xFFFF0000), 0);
1464
}
1465

    
1466
void do_hrfid (void)
1467
{
1468
    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1469
             ~((target_ulong)0xFFFF0000), 0);
1470
}
1471
#endif
1472
#endif
1473

    
1474
void do_tw (int flags)
1475
{
1476
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1477
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1478
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1479
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1480
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1481
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1482
    }
1483
}
1484

    
1485
#if defined(TARGET_PPC64)
1486
void do_td (int flags)
1487
{
1488
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
1489
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
1490
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
1491
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
1492
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
1493
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1494
}
1495
#endif
1496

    
1497
/*****************************************************************************/
1498
/* PowerPC 601 specific instructions (POWER bridge) */
1499
void do_POWER_abso (void)
1500
{
1501
    if ((int32_t)T0 == INT32_MIN) {
1502
        T0 = INT32_MAX;
1503
        xer_ov = 1;
1504
    } else if ((int32_t)T0 < 0) {
1505
        T0 = -T0;
1506
        xer_ov = 0;
1507
    } else {
1508
        xer_ov = 0;
1509
    }
1510
    xer_so |= xer_ov;
1511
}
1512

    
1513
void do_POWER_clcs (void)
1514
{
1515
    switch (T0) {
1516
    case 0x0CUL:
1517
        /* Instruction cache line size */
1518
        T0 = env->icache_line_size;
1519
        break;
1520
    case 0x0DUL:
1521
        /* Data cache line size */
1522
        T0 = env->dcache_line_size;
1523
        break;
1524
    case 0x0EUL:
1525
        /* Minimum cache line size */
1526
        T0 = env->icache_line_size < env->dcache_line_size ?
1527
            env->icache_line_size : env->dcache_line_size;
1528
        break;
1529
    case 0x0FUL:
1530
        /* Maximum cache line size */
1531
        T0 = env->icache_line_size > env->dcache_line_size ?
1532
            env->icache_line_size : env->dcache_line_size;
1533
        break;
1534
    default:
1535
        /* Undefined */
1536
        break;
1537
    }
1538
}
1539

    
1540
void do_POWER_div (void)
1541
{
1542
    uint64_t tmp;
1543

    
1544
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1545
        (int32_t)T1 == 0) {
1546
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1547
        env->spr[SPR_MQ] = 0;
1548
    } else {
1549
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1550
        env->spr[SPR_MQ] = tmp % T1;
1551
        T0 = tmp / (int32_t)T1;
1552
    }
1553
}
1554

    
1555
void do_POWER_divo (void)
1556
{
1557
    int64_t tmp;
1558

    
1559
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1560
        (int32_t)T1 == 0) {
1561
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1562
        env->spr[SPR_MQ] = 0;
1563
        xer_ov = 1;
1564
    } else {
1565
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1566
        env->spr[SPR_MQ] = tmp % T1;
1567
        tmp /= (int32_t)T1;
1568
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1569
            xer_ov = 1;
1570
        } else {
1571
            xer_ov = 0;
1572
        }
1573
        T0 = tmp;
1574
    }
1575
    xer_so |= xer_ov;
1576
}
1577

    
1578
void do_POWER_divs (void)
1579
{
1580
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1581
        (int32_t)T1 == 0) {
1582
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1583
        env->spr[SPR_MQ] = 0;
1584
    } else {
1585
        env->spr[SPR_MQ] = T0 % T1;
1586
        T0 = (int32_t)T0 / (int32_t)T1;
1587
    }
1588
}
1589

    
1590
void do_POWER_divso (void)
1591
{
1592
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1593
        (int32_t)T1 == 0) {
1594
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1595
        env->spr[SPR_MQ] = 0;
1596
        xer_ov = 1;
1597
    } else {
1598
        T0 = (int32_t)T0 / (int32_t)T1;
1599
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1600
        xer_ov = 0;
1601
    }
1602
    xer_so |= xer_ov;
1603
}
1604

    
1605
void do_POWER_dozo (void)
1606
{
1607
    if ((int32_t)T1 > (int32_t)T0) {
1608
        T2 = T0;
1609
        T0 = T1 - T0;
1610
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1611
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1612
            xer_ov = 1;
1613
            xer_so = 1;
1614
        } else {
1615
            xer_ov = 0;
1616
        }
1617
    } else {
1618
        T0 = 0;
1619
        xer_ov = 0;
1620
    }
1621
}
1622

    
1623
void do_POWER_maskg (void)
1624
{
1625
    uint32_t ret;
1626

    
1627
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1628
        ret = UINT32_MAX;
1629
    } else {
1630
        ret = (UINT32_MAX >> ((uint32_t)T0)) ^
1631
            ((UINT32_MAX >> ((uint32_t)T1)) >> 1);
1632
        if ((uint32_t)T0 > (uint32_t)T1)
1633
            ret = ~ret;
1634
    }
1635
    T0 = ret;
1636
}
1637

    
1638
void do_POWER_mulo (void)
1639
{
1640
    uint64_t tmp;
1641

    
1642
    tmp = (uint64_t)T0 * (uint64_t)T1;
1643
    env->spr[SPR_MQ] = tmp >> 32;
1644
    T0 = tmp;
1645
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1646
        xer_ov = 1;
1647
        xer_so = 1;
1648
    } else {
1649
        xer_ov = 0;
1650
    }
1651
}
1652

    
1653
#if !defined (CONFIG_USER_ONLY)
1654
void do_POWER_rac (void)
1655
{
1656
    mmu_ctx_t ctx;
1657
    int nb_BATs;
1658

    
1659
    /* We don't have to generate many instances of this instruction,
1660
     * as rac is supervisor only.
1661
     */
1662
    /* XXX: FIX THIS: Pretend we have no BAT */
1663
    nb_BATs = env->nb_BATs;
1664
    env->nb_BATs = 0;
1665
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
1666
        T0 = ctx.raddr;
1667
    env->nb_BATs = nb_BATs;
1668
}
1669

    
1670
void do_POWER_rfsvc (void)
1671
{
1672
    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1673
}
1674

    
1675
void do_store_hid0_601 (void)
1676
{
1677
    uint32_t hid0;
1678

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

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

    
1727
/*****************************************************************************/
1728
/* Embedded PowerPC specific helpers */
1729
void do_405_check_sat (void)
1730
{
1731
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1732
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1733
        /* Saturate result */
1734
        if (T2 >> 31) {
1735
            T0 = INT32_MIN;
1736
        } else {
1737
            T0 = INT32_MAX;
1738
        }
1739
    }
1740
}
1741

    
1742
/* XXX: to be improved to check access rights when in user-mode */
1743
void do_load_dcr (void)
1744
{
1745
    target_ulong val;
1746

    
1747
    if (unlikely(env->dcr_env == NULL)) {
1748
        if (loglevel != 0) {
1749
            fprintf(logfile, "No DCR environment\n");
1750
        }
1751
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1752
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1753
    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1754
        if (loglevel != 0) {
1755
            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1756
        }
1757
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1758
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1759
    } else {
1760
        T0 = val;
1761
    }
1762
}
1763

    
1764
void do_store_dcr (void)
1765
{
1766
    if (unlikely(env->dcr_env == NULL)) {
1767
        if (loglevel != 0) {
1768
            fprintf(logfile, "No DCR environment\n");
1769
        }
1770
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1771
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1772
    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1773
        if (loglevel != 0) {
1774
            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1775
        }
1776
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1777
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1778
    }
1779
}
1780

    
1781
#if !defined(CONFIG_USER_ONLY)
1782
void do_40x_rfci (void)
1783
{
1784
    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1785
             ~((target_ulong)0xFFFF0000), 0);
1786
}
1787

    
1788
void do_rfci (void)
1789
{
1790
    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1791
             ~((target_ulong)0x3FFF0000), 0);
1792
}
1793

    
1794
void do_rfdi (void)
1795
{
1796
    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1797
             ~((target_ulong)0x3FFF0000), 0);
1798
}
1799

    
1800
void do_rfmci (void)
1801
{
1802
    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1803
             ~((target_ulong)0x3FFF0000), 0);
1804
}
1805

    
1806
void do_load_403_pb (int num)
1807
{
1808
    T0 = env->pb[num];
1809
}
1810

    
1811
void do_store_403_pb (int num)
1812
{
1813
    if (likely(env->pb[num] != T0)) {
1814
        env->pb[num] = T0;
1815
        /* Should be optimized */
1816
        tlb_flush(env, 1);
1817
    }
1818
}
1819
#endif
1820

    
1821
/* 440 specific */
1822
void do_440_dlmzb (void)
1823
{
1824
    target_ulong mask;
1825
    int i;
1826

    
1827
    i = 1;
1828
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1829
        if ((T0 & mask) == 0)
1830
            goto done;
1831
        i++;
1832
    }
1833
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1834
        if ((T1 & mask) == 0)
1835
            break;
1836
        i++;
1837
    }
1838
 done:
1839
    T0 = i;
1840
}
1841

    
1842
/* SPE extension helpers */
1843
/* Use a table to make this quicker */
1844
static uint8_t hbrev[16] = {
1845
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1846
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1847
};
1848

    
1849
static always_inline uint8_t byte_reverse (uint8_t val)
1850
{
1851
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1852
}
1853

    
1854
static always_inline uint32_t word_reverse (uint32_t val)
1855
{
1856
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1857
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1858
}
1859

    
1860
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
1861
void do_brinc (void)
1862
{
1863
    uint32_t a, b, d, mask;
1864

    
1865
    mask = UINT32_MAX >> (32 - MASKBITS);
1866
    a = T0 & mask;
1867
    b = T1 & mask;
1868
    d = word_reverse(1 + word_reverse(a | ~b));
1869
    T0 = (T0 & ~mask) | (d & b);
1870
}
1871

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

    
1879
#define DO_SPE_OP1(name)                                                      \
1880
void do_ev##name (void)                                                       \
1881
{                                                                             \
1882
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1883
        (uint64_t)_do_e##name(T0_64);                                         \
1884
}
1885

    
1886
/* Fixed-point vector arithmetic */
1887
static always_inline uint32_t _do_eabs (uint32_t val)
1888
{
1889
    if ((val & 0x80000000) && val != 0x80000000)
1890
        val -= val;
1891

    
1892
    return val;
1893
}
1894

    
1895
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1896
{
1897
    return op1 + op2;
1898
}
1899

    
1900
static always_inline int _do_ecntlsw (uint32_t val)
1901
{
1902
    if (val & 0x80000000)
1903
        return clz32(~val);
1904
    else
1905
        return clz32(val);
1906
}
1907

    
1908
static always_inline int _do_ecntlzw (uint32_t val)
1909
{
1910
    return clz32(val);
1911
}
1912

    
1913
static always_inline uint32_t _do_eneg (uint32_t val)
1914
{
1915
    if (val != 0x80000000)
1916
        val -= val;
1917

    
1918
    return val;
1919
}
1920

    
1921
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1922
{
1923
    return rotl32(op1, op2);
1924
}
1925

    
1926
static always_inline uint32_t _do_erndw (uint32_t val)
1927
{
1928
    return (val + 0x000080000000) & 0xFFFF0000;
1929
}
1930

    
1931
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1932
{
1933
    /* No error here: 6 bits are used */
1934
    return op1 << (op2 & 0x3F);
1935
}
1936

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

    
1943
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1944
{
1945
    /* No error here: 6 bits are used */
1946
    return op1 >> (op2 & 0x3F);
1947
}
1948

    
1949
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1950
{
1951
    return op2 - op1;
1952
}
1953

    
1954
/* evabs */
1955
DO_SPE_OP1(abs);
1956
/* evaddw */
1957
DO_SPE_OP2(addw);
1958
/* evcntlsw */
1959
DO_SPE_OP1(cntlsw);
1960
/* evcntlzw */
1961
DO_SPE_OP1(cntlzw);
1962
/* evneg */
1963
DO_SPE_OP1(neg);
1964
/* evrlw */
1965
DO_SPE_OP2(rlw);
1966
/* evrnd */
1967
DO_SPE_OP1(rndw);
1968
/* evslw */
1969
DO_SPE_OP2(slw);
1970
/* evsrws */
1971
DO_SPE_OP2(srws);
1972
/* evsrwu */
1973
DO_SPE_OP2(srwu);
1974
/* evsubfw */
1975
DO_SPE_OP2(subfw);
1976

    
1977
/* evsel is a little bit more complicated... */
1978
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1979
{
1980
    if (n)
1981
        return op1;
1982
    else
1983
        return op2;
1984
}
1985

    
1986
void do_evsel (void)
1987
{
1988
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1989
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1990
}
1991

    
1992
/* Fixed-point vector comparisons */
1993
#define DO_SPE_CMP(name)                                                      \
1994
void do_ev##name (void)                                                       \
1995
{                                                                             \
1996
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1997
                                               T1_64 >> 32) << 32,            \
1998
                         _do_e##name(T0_64, T1_64));                          \
1999
}
2000

    
2001
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
2002
{
2003
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
2004
}
2005
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
2006
{
2007
    return op1 == op2 ? 1 : 0;
2008
}
2009

    
2010
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
2011
{
2012
    return op1 > op2 ? 1 : 0;
2013
}
2014

    
2015
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
2016
{
2017
    return op1 > op2 ? 1 : 0;
2018
}
2019

    
2020
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
2021
{
2022
    return op1 < op2 ? 1 : 0;
2023
}
2024

    
2025
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
2026
{
2027
    return op1 < op2 ? 1 : 0;
2028
}
2029

    
2030
/* evcmpeq */
2031
DO_SPE_CMP(cmpeq);
2032
/* evcmpgts */
2033
DO_SPE_CMP(cmpgts);
2034
/* evcmpgtu */
2035
DO_SPE_CMP(cmpgtu);
2036
/* evcmplts */
2037
DO_SPE_CMP(cmplts);
2038
/* evcmpltu */
2039
DO_SPE_CMP(cmpltu);
2040

    
2041
/* Single precision floating-point conversions from/to integer */
2042
static always_inline uint32_t _do_efscfsi (int32_t val)
2043
{
2044
    CPU_FloatU u;
2045

    
2046
    u.f = int32_to_float32(val, &env->spe_status);
2047

    
2048
    return u.l;
2049
}
2050

    
2051
static always_inline uint32_t _do_efscfui (uint32_t val)
2052
{
2053
    CPU_FloatU u;
2054

    
2055
    u.f = uint32_to_float32(val, &env->spe_status);
2056

    
2057
    return u.l;
2058
}
2059

    
2060
static always_inline int32_t _do_efsctsi (uint32_t val)
2061
{
2062
    CPU_FloatU u;
2063

    
2064
    u.l = val;
2065
    /* NaN are not treated the same way IEEE 754 does */
2066
    if (unlikely(isnan(u.f)))
2067
        return 0;
2068

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

    
2072
static always_inline uint32_t _do_efsctui (uint32_t val)
2073
{
2074
    CPU_FloatU u;
2075

    
2076
    u.l = val;
2077
    /* NaN are not treated the same way IEEE 754 does */
2078
    if (unlikely(isnan(u.f)))
2079
        return 0;
2080

    
2081
    return float32_to_uint32(u.f, &env->spe_status);
2082
}
2083

    
2084
static always_inline int32_t _do_efsctsiz (uint32_t val)
2085
{
2086
    CPU_FloatU u;
2087

    
2088
    u.l = val;
2089
    /* NaN are not treated the same way IEEE 754 does */
2090
    if (unlikely(isnan(u.f)))
2091
        return 0;
2092

    
2093
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2094
}
2095

    
2096
static always_inline uint32_t _do_efsctuiz (uint32_t val)
2097
{
2098
    CPU_FloatU u;
2099

    
2100
    u.l = val;
2101
    /* NaN are not treated the same way IEEE 754 does */
2102
    if (unlikely(isnan(u.f)))
2103
        return 0;
2104

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

    
2108
void do_efscfsi (void)
2109
{
2110
    T0_64 = _do_efscfsi(T0_64);
2111
}
2112

    
2113
void do_efscfui (void)
2114
{
2115
    T0_64 = _do_efscfui(T0_64);
2116
}
2117

    
2118
void do_efsctsi (void)
2119
{
2120
    T0_64 = _do_efsctsi(T0_64);
2121
}
2122

    
2123
void do_efsctui (void)
2124
{
2125
    T0_64 = _do_efsctui(T0_64);
2126
}
2127

    
2128
void do_efsctsiz (void)
2129
{
2130
    T0_64 = _do_efsctsiz(T0_64);
2131
}
2132

    
2133
void do_efsctuiz (void)
2134
{
2135
    T0_64 = _do_efsctuiz(T0_64);
2136
}
2137

    
2138
/* Single precision floating-point conversion to/from fractional */
2139
static always_inline uint32_t _do_efscfsf (uint32_t val)
2140
{
2141
    CPU_FloatU u;
2142
    float32 tmp;
2143

    
2144
    u.f = int32_to_float32(val, &env->spe_status);
2145
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2146
    u.f = float32_div(u.f, tmp, &env->spe_status);
2147

    
2148
    return u.l;
2149
}
2150

    
2151
static always_inline uint32_t _do_efscfuf (uint32_t val)
2152
{
2153
    CPU_FloatU u;
2154
    float32 tmp;
2155

    
2156
    u.f = uint32_to_float32(val, &env->spe_status);
2157
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2158
    u.f = float32_div(u.f, tmp, &env->spe_status);
2159

    
2160
    return u.l;
2161
}
2162

    
2163
static always_inline int32_t _do_efsctsf (uint32_t val)
2164
{
2165
    CPU_FloatU u;
2166
    float32 tmp;
2167

    
2168
    u.l = val;
2169
    /* NaN are not treated the same way IEEE 754 does */
2170
    if (unlikely(isnan(u.f)))
2171
        return 0;
2172
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2173
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2174

    
2175
    return float32_to_int32(u.f, &env->spe_status);
2176
}
2177

    
2178
static always_inline uint32_t _do_efsctuf (uint32_t val)
2179
{
2180
    CPU_FloatU u;
2181
    float32 tmp;
2182

    
2183
    u.l = val;
2184
    /* NaN are not treated the same way IEEE 754 does */
2185
    if (unlikely(isnan(u.f)))
2186
        return 0;
2187
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2188
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2189

    
2190
    return float32_to_uint32(u.f, &env->spe_status);
2191
}
2192

    
2193
static always_inline int32_t _do_efsctsfz (uint32_t val)
2194
{
2195
    CPU_FloatU u;
2196
    float32 tmp;
2197

    
2198
    u.l = val;
2199
    /* NaN are not treated the same way IEEE 754 does */
2200
    if (unlikely(isnan(u.f)))
2201
        return 0;
2202
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2203
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2204

    
2205
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2206
}
2207

    
2208
static always_inline uint32_t _do_efsctufz (uint32_t val)
2209
{
2210
    CPU_FloatU u;
2211
    float32 tmp;
2212

    
2213
    u.l = val;
2214
    /* NaN are not treated the same way IEEE 754 does */
2215
    if (unlikely(isnan(u.f)))
2216
        return 0;
2217
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2218
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2219

    
2220
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2221
}
2222

    
2223
void do_efscfsf (void)
2224
{
2225
    T0_64 = _do_efscfsf(T0_64);
2226
}
2227

    
2228
void do_efscfuf (void)
2229
{
2230
    T0_64 = _do_efscfuf(T0_64);
2231
}
2232

    
2233
void do_efsctsf (void)
2234
{
2235
    T0_64 = _do_efsctsf(T0_64);
2236
}
2237

    
2238
void do_efsctuf (void)
2239
{
2240
    T0_64 = _do_efsctuf(T0_64);
2241
}
2242

    
2243
void do_efsctsfz (void)
2244
{
2245
    T0_64 = _do_efsctsfz(T0_64);
2246
}
2247

    
2248
void do_efsctufz (void)
2249
{
2250
    T0_64 = _do_efsctufz(T0_64);
2251
}
2252

    
2253
/* Double precision floating point helpers */
2254
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
2255
{
2256
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2257
    return _do_efdtstlt(op1, op2);
2258
}
2259

    
2260
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
2261
{
2262
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2263
    return _do_efdtstgt(op1, op2);
2264
}
2265

    
2266
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
2267
{
2268
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2269
    return _do_efdtsteq(op1, op2);
2270
}
2271

    
2272
void do_efdcmplt (void)
2273
{
2274
    T0 = _do_efdcmplt(T0_64, T1_64);
2275
}
2276

    
2277
void do_efdcmpgt (void)
2278
{
2279
    T0 = _do_efdcmpgt(T0_64, T1_64);
2280
}
2281

    
2282
void do_efdcmpeq (void)
2283
{
2284
    T0 = _do_efdcmpeq(T0_64, T1_64);
2285
}
2286

    
2287
/* Double precision floating-point conversion to/from integer */
2288
static always_inline uint64_t _do_efdcfsi (int64_t val)
2289
{
2290
    CPU_DoubleU u;
2291

    
2292
    u.d = int64_to_float64(val, &env->spe_status);
2293

    
2294
    return u.ll;
2295
}
2296

    
2297
static always_inline uint64_t _do_efdcfui (uint64_t val)
2298
{
2299
    CPU_DoubleU u;
2300

    
2301
    u.d = uint64_to_float64(val, &env->spe_status);
2302

    
2303
    return u.ll;
2304
}
2305

    
2306
static always_inline int64_t _do_efdctsi (uint64_t val)
2307
{
2308
    CPU_DoubleU u;
2309

    
2310
    u.ll = val;
2311
    /* NaN are not treated the same way IEEE 754 does */
2312
    if (unlikely(isnan(u.d)))
2313
        return 0;
2314

    
2315
    return float64_to_int64(u.d, &env->spe_status);
2316
}
2317

    
2318
static always_inline uint64_t _do_efdctui (uint64_t val)
2319
{
2320
    CPU_DoubleU u;
2321

    
2322
    u.ll = val;
2323
    /* NaN are not treated the same way IEEE 754 does */
2324
    if (unlikely(isnan(u.d)))
2325
        return 0;
2326

    
2327
    return float64_to_uint64(u.d, &env->spe_status);
2328
}
2329

    
2330
static always_inline int64_t _do_efdctsiz (uint64_t val)
2331
{
2332
    CPU_DoubleU u;
2333

    
2334
    u.ll = val;
2335
    /* NaN are not treated the same way IEEE 754 does */
2336
    if (unlikely(isnan(u.d)))
2337
        return 0;
2338

    
2339
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2340
}
2341

    
2342
static always_inline uint64_t _do_efdctuiz (uint64_t val)
2343
{
2344
    CPU_DoubleU u;
2345

    
2346
    u.ll = val;
2347
    /* NaN are not treated the same way IEEE 754 does */
2348
    if (unlikely(isnan(u.d)))
2349
        return 0;
2350

    
2351
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2352
}
2353

    
2354
void do_efdcfsi (void)
2355
{
2356
    T0_64 = _do_efdcfsi(T0_64);
2357
}
2358

    
2359
void do_efdcfui (void)
2360
{
2361
    T0_64 = _do_efdcfui(T0_64);
2362
}
2363

    
2364
void do_efdctsi (void)
2365
{
2366
    T0_64 = _do_efdctsi(T0_64);
2367
}
2368

    
2369
void do_efdctui (void)
2370
{
2371
    T0_64 = _do_efdctui(T0_64);
2372
}
2373

    
2374
void do_efdctsiz (void)
2375
{
2376
    T0_64 = _do_efdctsiz(T0_64);
2377
}
2378

    
2379
void do_efdctuiz (void)
2380
{
2381
    T0_64 = _do_efdctuiz(T0_64);
2382
}
2383

    
2384
/* Double precision floating-point conversion to/from fractional */
2385
static always_inline uint64_t _do_efdcfsf (int64_t val)
2386
{
2387
    CPU_DoubleU u;
2388
    float64 tmp;
2389

    
2390
    u.d = int32_to_float64(val, &env->spe_status);
2391
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2392
    u.d = float64_div(u.d, tmp, &env->spe_status);
2393

    
2394
    return u.ll;
2395
}
2396

    
2397
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2398
{
2399
    CPU_DoubleU u;
2400
    float64 tmp;
2401

    
2402
    u.d = uint32_to_float64(val, &env->spe_status);
2403
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2404
    u.d = float64_div(u.d, tmp, &env->spe_status);
2405

    
2406
    return u.ll;
2407
}
2408

    
2409
static always_inline int64_t _do_efdctsf (uint64_t val)
2410
{
2411
    CPU_DoubleU u;
2412
    float64 tmp;
2413

    
2414
    u.ll = val;
2415
    /* NaN are not treated the same way IEEE 754 does */
2416
    if (unlikely(isnan(u.d)))
2417
        return 0;
2418
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2419
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2420

    
2421
    return float64_to_int32(u.d, &env->spe_status);
2422
}
2423

    
2424
static always_inline uint64_t _do_efdctuf (uint64_t val)
2425
{
2426
    CPU_DoubleU u;
2427
    float64 tmp;
2428

    
2429
    u.ll = val;
2430
    /* NaN are not treated the same way IEEE 754 does */
2431
    if (unlikely(isnan(u.d)))
2432
        return 0;
2433
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2434
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2435

    
2436
    return float64_to_uint32(u.d, &env->spe_status);
2437
}
2438

    
2439
static always_inline int64_t _do_efdctsfz (uint64_t val)
2440
{
2441
    CPU_DoubleU u;
2442
    float64 tmp;
2443

    
2444
    u.ll = val;
2445
    /* NaN are not treated the same way IEEE 754 does */
2446
    if (unlikely(isnan(u.d)))
2447
        return 0;
2448
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2449
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2450

    
2451
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2452
}
2453

    
2454
static always_inline uint64_t _do_efdctufz (uint64_t val)
2455
{
2456
    CPU_DoubleU u;
2457
    float64 tmp;
2458

    
2459
    u.ll = val;
2460
    /* NaN are not treated the same way IEEE 754 does */
2461
    if (unlikely(isnan(u.d)))
2462
        return 0;
2463
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2464
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2465

    
2466
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2467
}
2468

    
2469
void do_efdcfsf (void)
2470
{
2471
    T0_64 = _do_efdcfsf(T0_64);
2472
}
2473

    
2474
void do_efdcfuf (void)
2475
{
2476
    T0_64 = _do_efdcfuf(T0_64);
2477
}
2478

    
2479
void do_efdctsf (void)
2480
{
2481
    T0_64 = _do_efdctsf(T0_64);
2482
}
2483

    
2484
void do_efdctuf (void)
2485
{
2486
    T0_64 = _do_efdctuf(T0_64);
2487
}
2488

    
2489
void do_efdctsfz (void)
2490
{
2491
    T0_64 = _do_efdctsfz(T0_64);
2492
}
2493

    
2494
void do_efdctufz (void)
2495
{
2496
    T0_64 = _do_efdctufz(T0_64);
2497
}
2498

    
2499
/* Floating point conversion between single and double precision */
2500
static always_inline uint32_t _do_efscfd (uint64_t val)
2501
{
2502
    CPU_DoubleU u1;
2503
    CPU_FloatU u2;
2504

    
2505
    u1.ll = val;
2506
    u2.f = float64_to_float32(u1.d, &env->spe_status);
2507

    
2508
    return u2.l;
2509
}
2510

    
2511
static always_inline uint64_t _do_efdcfs (uint32_t val)
2512
{
2513
    CPU_DoubleU u2;
2514
    CPU_FloatU u1;
2515

    
2516
    u1.l = val;
2517
    u2.d = float32_to_float64(u1.f, &env->spe_status);
2518

    
2519
    return u2.ll;
2520
}
2521

    
2522
void do_efscfd (void)
2523
{
2524
    T0_64 = _do_efscfd(T0_64);
2525
}
2526

    
2527
void do_efdcfs (void)
2528
{
2529
    T0_64 = _do_efdcfs(T0_64);
2530
}
2531

    
2532
/* Single precision fixed-point vector arithmetic */
2533
/* evfsabs */
2534
DO_SPE_OP1(fsabs);
2535
/* evfsnabs */
2536
DO_SPE_OP1(fsnabs);
2537
/* evfsneg */
2538
DO_SPE_OP1(fsneg);
2539
/* evfsadd */
2540
DO_SPE_OP2(fsadd);
2541
/* evfssub */
2542
DO_SPE_OP2(fssub);
2543
/* evfsmul */
2544
DO_SPE_OP2(fsmul);
2545
/* evfsdiv */
2546
DO_SPE_OP2(fsdiv);
2547

    
2548
/* Single-precision floating-point comparisons */
2549
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2550
{
2551
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2552
    return _do_efststlt(op1, op2);
2553
}
2554

    
2555
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2556
{
2557
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2558
    return _do_efststgt(op1, op2);
2559
}
2560

    
2561
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2562
{
2563
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2564
    return _do_efststeq(op1, op2);
2565
}
2566

    
2567
void do_efscmplt (void)
2568
{
2569
    T0 = _do_efscmplt(T0_64, T1_64);
2570
}
2571

    
2572
void do_efscmpgt (void)
2573
{
2574
    T0 = _do_efscmpgt(T0_64, T1_64);
2575
}
2576

    
2577
void do_efscmpeq (void)
2578
{
2579
    T0 = _do_efscmpeq(T0_64, T1_64);
2580
}
2581

    
2582
/* Single-precision floating-point vector comparisons */
2583
/* evfscmplt */
2584
DO_SPE_CMP(fscmplt);
2585
/* evfscmpgt */
2586
DO_SPE_CMP(fscmpgt);
2587
/* evfscmpeq */
2588
DO_SPE_CMP(fscmpeq);
2589
/* evfststlt */
2590
DO_SPE_CMP(fststlt);
2591
/* evfststgt */
2592
DO_SPE_CMP(fststgt);
2593
/* evfststeq */
2594
DO_SPE_CMP(fststeq);
2595

    
2596
/* Single-precision floating-point vector conversions */
2597
/* evfscfsi */
2598
DO_SPE_OP1(fscfsi);
2599
/* evfscfui */
2600
DO_SPE_OP1(fscfui);
2601
/* evfscfuf */
2602
DO_SPE_OP1(fscfuf);
2603
/* evfscfsf */
2604
DO_SPE_OP1(fscfsf);
2605
/* evfsctsi */
2606
DO_SPE_OP1(fsctsi);
2607
/* evfsctui */
2608
DO_SPE_OP1(fsctui);
2609
/* evfsctsiz */
2610
DO_SPE_OP1(fsctsiz);
2611
/* evfsctuiz */
2612
DO_SPE_OP1(fsctuiz);
2613
/* evfsctsf */
2614
DO_SPE_OP1(fsctsf);
2615
/* evfsctuf */
2616
DO_SPE_OP1(fsctuf);
2617

    
2618
/*****************************************************************************/
2619
/* Softmmu support */
2620
#if !defined (CONFIG_USER_ONLY)
2621

    
2622
#define MMUSUFFIX _mmu
2623

    
2624
#define SHIFT 0
2625
#include "softmmu_template.h"
2626

    
2627
#define SHIFT 1
2628
#include "softmmu_template.h"
2629

    
2630
#define SHIFT 2
2631
#include "softmmu_template.h"
2632

    
2633
#define SHIFT 3
2634
#include "softmmu_template.h"
2635

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

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

    
2668
/* Software driven TLBs management */
2669
/* PowerPC 602/603 software TLB load instructions helpers */
2670
void do_load_6xx_tlb (int is_code)
2671
{
2672
    target_ulong RPN, CMP, EPN;
2673
    int way;
2674

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

    
2696
void do_load_74xx_tlb (int is_code)
2697
{
2698
    target_ulong RPN, CMP, EPN;
2699
    int way;
2700

    
2701
    RPN = env->spr[SPR_PTELO];
2702
    CMP = env->spr[SPR_PTEHI];
2703
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2704
    way = env->spr[SPR_TLBMISS] & 0x3;
2705
#if defined (DEBUG_SOFTWARE_TLB)
2706
    if (loglevel != 0) {
2707
        fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2708
                " PTE1 " ADDRX " way %d\n",
2709
                __func__, T0, EPN, CMP, RPN, way);
2710
    }
2711
#endif
2712
    /* Store this TLB */
2713
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2714
                     way, is_code, CMP, RPN);
2715
}
2716

    
2717
static always_inline target_ulong booke_tlb_to_page_size (int size)
2718
{
2719
    return 1024 << (2 * size);
2720
}
2721

    
2722
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
2723
{
2724
    int size;
2725

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

    
2782
    return size;
2783
}
2784

    
2785
/* Helpers for 4xx TLB management */
2786
void do_4xx_tlbre_lo (void)
2787
{
2788
    ppcemb_tlb_t *tlb;
2789
    int size;
2790

    
2791
    T0 &= 0x3F;
2792
    tlb = &env->tlb[T0].tlbe;
2793
    T0 = tlb->EPN;
2794
    if (tlb->prot & PAGE_VALID)
2795
        T0 |= 0x400;
2796
    size = booke_page_size_to_tlb(tlb->size);
2797
    if (size < 0 || size > 0x7)
2798
        size = 1;
2799
    T0 |= size << 7;
2800
    env->spr[SPR_40x_PID] = tlb->PID;
2801
}
2802

    
2803
void do_4xx_tlbre_hi (void)
2804
{
2805
    ppcemb_tlb_t *tlb;
2806

    
2807
    T0 &= 0x3F;
2808
    tlb = &env->tlb[T0].tlbe;
2809
    T0 = tlb->RPN;
2810
    if (tlb->prot & PAGE_EXEC)
2811
        T0 |= 0x200;
2812
    if (tlb->prot & PAGE_WRITE)
2813
        T0 |= 0x100;
2814
}
2815

    
2816
void do_4xx_tlbwe_hi (void)
2817
{
2818
    ppcemb_tlb_t *tlb;
2819
    target_ulong page, end;
2820

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

    
2886
void do_4xx_tlbwe_lo (void)
2887
{
2888
    ppcemb_tlb_t *tlb;
2889

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

    
2916
/* PowerPC 440 TLB management */
2917
void do_440_tlbwe (int word)
2918
{
2919
    ppcemb_tlb_t *tlb;
2920
    target_ulong EPN, RPN, size;
2921
    int do_flush_tlbs;
2922

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

    
2983
void do_440_tlbre (int word)
2984
{
2985
    ppcemb_tlb_t *tlb;
2986
    int size;
2987

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