Statistics
| Branch: | Revision:

root / target-ppc / fpu_helper.c @ fab7fe42

History | View | Annotate | Download (104.3 kB)

1
/*
2
 *  PowerPC floating point and SPE 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, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "cpu.h"
20
#include "helper.h"
21

    
22
/*****************************************************************************/
23
/* Floating point operations helpers */
24
uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg)
25
{
26
    CPU_FloatU f;
27
    CPU_DoubleU d;
28

    
29
    f.l = arg;
30
    d.d = float32_to_float64(f.f, &env->fp_status);
31
    return d.ll;
32
}
33

    
34
uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg)
35
{
36
    CPU_FloatU f;
37
    CPU_DoubleU d;
38

    
39
    d.ll = arg;
40
    f.f = float64_to_float32(d.d, &env->fp_status);
41
    return f.l;
42
}
43

    
44
static inline int isden(float64 d)
45
{
46
    CPU_DoubleU u;
47

    
48
    u.d = d;
49

    
50
    return ((u.ll >> 52) & 0x7FF) == 0;
51
}
52

    
53
uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf)
54
{
55
    CPU_DoubleU farg;
56
    int isneg;
57
    int ret;
58

    
59
    farg.ll = arg;
60
    isneg = float64_is_neg(farg.d);
61
    if (unlikely(float64_is_any_nan(farg.d))) {
62
        if (float64_is_signaling_nan(farg.d)) {
63
            /* Signaling NaN: flags are undefined */
64
            ret = 0x00;
65
        } else {
66
            /* Quiet NaN */
67
            ret = 0x11;
68
        }
69
    } else if (unlikely(float64_is_infinity(farg.d))) {
70
        /* +/- infinity */
71
        if (isneg) {
72
            ret = 0x09;
73
        } else {
74
            ret = 0x05;
75
        }
76
    } else {
77
        if (float64_is_zero(farg.d)) {
78
            /* +/- zero */
79
            if (isneg) {
80
                ret = 0x12;
81
            } else {
82
                ret = 0x02;
83
            }
84
        } else {
85
            if (isden(farg.d)) {
86
                /* Denormalized numbers */
87
                ret = 0x10;
88
            } else {
89
                /* Normalized numbers */
90
                ret = 0x00;
91
            }
92
            if (isneg) {
93
                ret |= 0x08;
94
            } else {
95
                ret |= 0x04;
96
            }
97
        }
98
    }
99
    if (set_fprf) {
100
        /* We update FPSCR_FPRF */
101
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
102
        env->fpscr |= ret << FPSCR_FPRF;
103
    }
104
    /* We just need fpcc to update Rc1 */
105
    return ret & 0xF;
106
}
107

    
108
/* Floating-point invalid operations exception */
109
static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op,
110
                                             int set_fpcc)
111
{
112
    uint64_t ret = 0;
113
    int ve;
114

    
115
    ve = fpscr_ve;
116
    switch (op) {
117
    case POWERPC_EXCP_FP_VXSNAN:
118
        env->fpscr |= 1 << FPSCR_VXSNAN;
119
        break;
120
    case POWERPC_EXCP_FP_VXSOFT:
121
        env->fpscr |= 1 << FPSCR_VXSOFT;
122
        break;
123
    case POWERPC_EXCP_FP_VXISI:
124
        /* Magnitude subtraction of infinities */
125
        env->fpscr |= 1 << FPSCR_VXISI;
126
        goto update_arith;
127
    case POWERPC_EXCP_FP_VXIDI:
128
        /* Division of infinity by infinity */
129
        env->fpscr |= 1 << FPSCR_VXIDI;
130
        goto update_arith;
131
    case POWERPC_EXCP_FP_VXZDZ:
132
        /* Division of zero by zero */
133
        env->fpscr |= 1 << FPSCR_VXZDZ;
134
        goto update_arith;
135
    case POWERPC_EXCP_FP_VXIMZ:
136
        /* Multiplication of zero by infinity */
137
        env->fpscr |= 1 << FPSCR_VXIMZ;
138
        goto update_arith;
139
    case POWERPC_EXCP_FP_VXVC:
140
        /* Ordered comparison of NaN */
141
        env->fpscr |= 1 << FPSCR_VXVC;
142
        if (set_fpcc) {
143
            env->fpscr &= ~(0xF << FPSCR_FPCC);
144
            env->fpscr |= 0x11 << FPSCR_FPCC;
145
        }
146
        /* We must update the target FPR before raising the exception */
147
        if (ve != 0) {
148
            env->exception_index = POWERPC_EXCP_PROGRAM;
149
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
150
            /* Update the floating-point enabled exception summary */
151
            env->fpscr |= 1 << FPSCR_FEX;
152
            /* Exception is differed */
153
            ve = 0;
154
        }
155
        break;
156
    case POWERPC_EXCP_FP_VXSQRT:
157
        /* Square root of a negative number */
158
        env->fpscr |= 1 << FPSCR_VXSQRT;
159
    update_arith:
160
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
161
        if (ve == 0) {
162
            /* Set the result to quiet NaN */
163
            ret = 0x7FF8000000000000ULL;
164
            if (set_fpcc) {
165
                env->fpscr &= ~(0xF << FPSCR_FPCC);
166
                env->fpscr |= 0x11 << FPSCR_FPCC;
167
            }
168
        }
169
        break;
170
    case POWERPC_EXCP_FP_VXCVI:
171
        /* Invalid conversion */
172
        env->fpscr |= 1 << FPSCR_VXCVI;
173
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
174
        if (ve == 0) {
175
            /* Set the result to quiet NaN */
176
            ret = 0x7FF8000000000000ULL;
177
            if (set_fpcc) {
178
                env->fpscr &= ~(0xF << FPSCR_FPCC);
179
                env->fpscr |= 0x11 << FPSCR_FPCC;
180
            }
181
        }
182
        break;
183
    }
184
    /* Update the floating-point invalid operation summary */
185
    env->fpscr |= 1 << FPSCR_VX;
186
    /* Update the floating-point exception summary */
187
    env->fpscr |= 1 << FPSCR_FX;
188
    if (ve != 0) {
189
        /* Update the floating-point enabled exception summary */
190
        env->fpscr |= 1 << FPSCR_FEX;
191
        if (msr_fe0 != 0 || msr_fe1 != 0) {
192
            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
193
                                       POWERPC_EXCP_FP | op);
194
        }
195
    }
196
    return ret;
197
}
198

    
199
static inline void float_zero_divide_excp(CPUPPCState *env)
200
{
201
    env->fpscr |= 1 << FPSCR_ZX;
202
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
203
    /* Update the floating-point exception summary */
204
    env->fpscr |= 1 << FPSCR_FX;
205
    if (fpscr_ze != 0) {
206
        /* Update the floating-point enabled exception summary */
207
        env->fpscr |= 1 << FPSCR_FEX;
208
        if (msr_fe0 != 0 || msr_fe1 != 0) {
209
            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
210
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
211
        }
212
    }
213
}
214

    
215
static inline void float_overflow_excp(CPUPPCState *env)
216
{
217
    env->fpscr |= 1 << FPSCR_OX;
218
    /* Update the floating-point exception summary */
219
    env->fpscr |= 1 << FPSCR_FX;
220
    if (fpscr_oe != 0) {
221
        /* XXX: should adjust the result */
222
        /* Update the floating-point enabled exception summary */
223
        env->fpscr |= 1 << FPSCR_FEX;
224
        /* We must update the target FPR before raising the exception */
225
        env->exception_index = POWERPC_EXCP_PROGRAM;
226
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
227
    } else {
228
        env->fpscr |= 1 << FPSCR_XX;
229
        env->fpscr |= 1 << FPSCR_FI;
230
    }
231
}
232

    
233
static inline void float_underflow_excp(CPUPPCState *env)
234
{
235
    env->fpscr |= 1 << FPSCR_UX;
236
    /* Update the floating-point exception summary */
237
    env->fpscr |= 1 << FPSCR_FX;
238
    if (fpscr_ue != 0) {
239
        /* XXX: should adjust the result */
240
        /* Update the floating-point enabled exception summary */
241
        env->fpscr |= 1 << FPSCR_FEX;
242
        /* We must update the target FPR before raising the exception */
243
        env->exception_index = POWERPC_EXCP_PROGRAM;
244
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
245
    }
246
}
247

    
248
static inline void float_inexact_excp(CPUPPCState *env)
249
{
250
    env->fpscr |= 1 << FPSCR_XX;
251
    /* Update the floating-point exception summary */
252
    env->fpscr |= 1 << FPSCR_FX;
253
    if (fpscr_xe != 0) {
254
        /* Update the floating-point enabled exception summary */
255
        env->fpscr |= 1 << FPSCR_FEX;
256
        /* We must update the target FPR before raising the exception */
257
        env->exception_index = POWERPC_EXCP_PROGRAM;
258
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
259
    }
260
}
261

    
262
static inline void fpscr_set_rounding_mode(CPUPPCState *env)
263
{
264
    int rnd_type;
265

    
266
    /* Set rounding mode */
267
    switch (fpscr_rn) {
268
    case 0:
269
        /* Best approximation (round to nearest) */
270
        rnd_type = float_round_nearest_even;
271
        break;
272
    case 1:
273
        /* Smaller magnitude (round toward zero) */
274
        rnd_type = float_round_to_zero;
275
        break;
276
    case 2:
277
        /* Round toward +infinite */
278
        rnd_type = float_round_up;
279
        break;
280
    default:
281
    case 3:
282
        /* Round toward -infinite */
283
        rnd_type = float_round_down;
284
        break;
285
    }
286
    set_float_rounding_mode(rnd_type, &env->fp_status);
287
}
288

    
289
void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
290
{
291
    int prev;
292

    
293
    prev = (env->fpscr >> bit) & 1;
294
    env->fpscr &= ~(1 << bit);
295
    if (prev == 1) {
296
        switch (bit) {
297
        case FPSCR_RN1:
298
        case FPSCR_RN:
299
            fpscr_set_rounding_mode(env);
300
            break;
301
        default:
302
            break;
303
        }
304
    }
305
}
306

    
307
void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
308
{
309
    int prev;
310

    
311
    prev = (env->fpscr >> bit) & 1;
312
    env->fpscr |= 1 << bit;
313
    if (prev == 0) {
314
        switch (bit) {
315
        case FPSCR_VX:
316
            env->fpscr |= 1 << FPSCR_FX;
317
            if (fpscr_ve) {
318
                goto raise_ve;
319
            }
320
            break;
321
        case FPSCR_OX:
322
            env->fpscr |= 1 << FPSCR_FX;
323
            if (fpscr_oe) {
324
                goto raise_oe;
325
            }
326
            break;
327
        case FPSCR_UX:
328
            env->fpscr |= 1 << FPSCR_FX;
329
            if (fpscr_ue) {
330
                goto raise_ue;
331
            }
332
            break;
333
        case FPSCR_ZX:
334
            env->fpscr |= 1 << FPSCR_FX;
335
            if (fpscr_ze) {
336
                goto raise_ze;
337
            }
338
            break;
339
        case FPSCR_XX:
340
            env->fpscr |= 1 << FPSCR_FX;
341
            if (fpscr_xe) {
342
                goto raise_xe;
343
            }
344
            break;
345
        case FPSCR_VXSNAN:
346
        case FPSCR_VXISI:
347
        case FPSCR_VXIDI:
348
        case FPSCR_VXZDZ:
349
        case FPSCR_VXIMZ:
350
        case FPSCR_VXVC:
351
        case FPSCR_VXSOFT:
352
        case FPSCR_VXSQRT:
353
        case FPSCR_VXCVI:
354
            env->fpscr |= 1 << FPSCR_VX;
355
            env->fpscr |= 1 << FPSCR_FX;
356
            if (fpscr_ve != 0) {
357
                goto raise_ve;
358
            }
359
            break;
360
        case FPSCR_VE:
361
            if (fpscr_vx != 0) {
362
            raise_ve:
363
                env->error_code = POWERPC_EXCP_FP;
364
                if (fpscr_vxsnan) {
365
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
366
                }
367
                if (fpscr_vxisi) {
368
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
369
                }
370
                if (fpscr_vxidi) {
371
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
372
                }
373
                if (fpscr_vxzdz) {
374
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
375
                }
376
                if (fpscr_vximz) {
377
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
378
                }
379
                if (fpscr_vxvc) {
380
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
381
                }
382
                if (fpscr_vxsoft) {
383
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
384
                }
385
                if (fpscr_vxsqrt) {
386
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
387
                }
388
                if (fpscr_vxcvi) {
389
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
390
                }
391
                goto raise_excp;
392
            }
393
            break;
394
        case FPSCR_OE:
395
            if (fpscr_ox != 0) {
396
            raise_oe:
397
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
398
                goto raise_excp;
399
            }
400
            break;
401
        case FPSCR_UE:
402
            if (fpscr_ux != 0) {
403
            raise_ue:
404
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
405
                goto raise_excp;
406
            }
407
            break;
408
        case FPSCR_ZE:
409
            if (fpscr_zx != 0) {
410
            raise_ze:
411
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
412
                goto raise_excp;
413
            }
414
            break;
415
        case FPSCR_XE:
416
            if (fpscr_xx != 0) {
417
            raise_xe:
418
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
419
                goto raise_excp;
420
            }
421
            break;
422
        case FPSCR_RN1:
423
        case FPSCR_RN:
424
            fpscr_set_rounding_mode(env);
425
            break;
426
        default:
427
            break;
428
        raise_excp:
429
            /* Update the floating-point enabled exception summary */
430
            env->fpscr |= 1 << FPSCR_FEX;
431
            /* We have to update Rc1 before raising the exception */
432
            env->exception_index = POWERPC_EXCP_PROGRAM;
433
            break;
434
        }
435
    }
436
}
437

    
438
void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
439
{
440
    target_ulong prev, new;
441
    int i;
442

    
443
    prev = env->fpscr;
444
    new = (target_ulong)arg;
445
    new &= ~0x60000000LL;
446
    new |= prev & 0x60000000LL;
447
    for (i = 0; i < sizeof(target_ulong) * 2; i++) {
448
        if (mask & (1 << i)) {
449
            env->fpscr &= ~(0xFLL << (4 * i));
450
            env->fpscr |= new & (0xFLL << (4 * i));
451
        }
452
    }
453
    /* Update VX and FEX */
454
    if (fpscr_ix != 0) {
455
        env->fpscr |= 1 << FPSCR_VX;
456
    } else {
457
        env->fpscr &= ~(1 << FPSCR_VX);
458
    }
459
    if ((fpscr_ex & fpscr_eex) != 0) {
460
        env->fpscr |= 1 << FPSCR_FEX;
461
        env->exception_index = POWERPC_EXCP_PROGRAM;
462
        /* XXX: we should compute it properly */
463
        env->error_code = POWERPC_EXCP_FP;
464
    } else {
465
        env->fpscr &= ~(1 << FPSCR_FEX);
466
    }
467
    fpscr_set_rounding_mode(env);
468
}
469

    
470
void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
471
{
472
    helper_store_fpscr(env, arg, mask);
473
}
474

    
475
void helper_float_check_status(CPUPPCState *env)
476
{
477
    int status = get_float_exception_flags(&env->fp_status);
478

    
479
    if (status & float_flag_divbyzero) {
480
        float_zero_divide_excp(env);
481
    } else if (status & float_flag_overflow) {
482
        float_overflow_excp(env);
483
    } else if (status & float_flag_underflow) {
484
        float_underflow_excp(env);
485
    } else if (status & float_flag_inexact) {
486
        float_inexact_excp(env);
487
    }
488

    
489
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
490
        (env->error_code & POWERPC_EXCP_FP)) {
491
        /* Differred floating-point exception after target FPR update */
492
        if (msr_fe0 != 0 || msr_fe1 != 0) {
493
            helper_raise_exception_err(env, env->exception_index,
494
                                       env->error_code);
495
        }
496
    }
497
}
498

    
499
void helper_reset_fpstatus(CPUPPCState *env)
500
{
501
    set_float_exception_flags(0, &env->fp_status);
502
}
503

    
504
/* fadd - fadd. */
505
uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
506
{
507
    CPU_DoubleU farg1, farg2;
508

    
509
    farg1.ll = arg1;
510
    farg2.ll = arg2;
511

    
512
    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
513
                 float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
514
        /* Magnitude subtraction of infinities */
515
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
516
    } else {
517
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
518
                     float64_is_signaling_nan(farg2.d))) {
519
            /* sNaN addition */
520
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
521
        }
522
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
523
    }
524

    
525
    return farg1.ll;
526
}
527

    
528
/* fsub - fsub. */
529
uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
530
{
531
    CPU_DoubleU farg1, farg2;
532

    
533
    farg1.ll = arg1;
534
    farg2.ll = arg2;
535

    
536
    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
537
                 float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
538
        /* Magnitude subtraction of infinities */
539
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
540
    } else {
541
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
542
                     float64_is_signaling_nan(farg2.d))) {
543
            /* sNaN subtraction */
544
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
545
        }
546
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
547
    }
548

    
549
    return farg1.ll;
550
}
551

    
552
/* fmul - fmul. */
553
uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
554
{
555
    CPU_DoubleU farg1, farg2;
556

    
557
    farg1.ll = arg1;
558
    farg2.ll = arg2;
559

    
560
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
561
                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
562
        /* Multiplication of zero by infinity */
563
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
564
    } else {
565
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
566
                     float64_is_signaling_nan(farg2.d))) {
567
            /* sNaN multiplication */
568
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
569
        }
570
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
571
    }
572

    
573
    return farg1.ll;
574
}
575

    
576
/* fdiv - fdiv. */
577
uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
578
{
579
    CPU_DoubleU farg1, farg2;
580

    
581
    farg1.ll = arg1;
582
    farg2.ll = arg2;
583

    
584
    if (unlikely(float64_is_infinity(farg1.d) &&
585
                 float64_is_infinity(farg2.d))) {
586
        /* Division of infinity by infinity */
587
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
588
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
589
        /* Division of zero by zero */
590
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
591
    } else {
592
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
593
                     float64_is_signaling_nan(farg2.d))) {
594
            /* sNaN division */
595
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
596
        }
597
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
598
    }
599

    
600
    return farg1.ll;
601
}
602

    
603

    
604
#define FPU_FCTI(op, cvt, nanval)                                      \
605
uint64_t helper_##op(CPUPPCState *env, uint64_t arg)                   \
606
{                                                                      \
607
    CPU_DoubleU farg;                                                  \
608
                                                                       \
609
    farg.ll = arg;                                                     \
610
    farg.ll = float64_to_##cvt(farg.d, &env->fp_status);               \
611
                                                                       \
612
    if (unlikely(env->fp_status.float_exception_flags)) {              \
613
        if (float64_is_any_nan(arg)) {                                 \
614
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
615
            if (float64_is_signaling_nan(arg)) {                       \
616
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
617
            }                                                          \
618
            farg.ll = nanval;                                          \
619
        } else if (env->fp_status.float_exception_flags &              \
620
                   float_flag_invalid) {                               \
621
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
622
        }                                                              \
623
        helper_float_check_status(env);                                \
624
    }                                                                  \
625
    return farg.ll;                                                    \
626
 }
627

    
628
FPU_FCTI(fctiw, int32, 0x80000000)
629
FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000)
630
FPU_FCTI(fctiwu, uint32, 0x00000000)
631
FPU_FCTI(fctiwuz, uint32_round_to_zero, 0x00000000)
632
#if defined(TARGET_PPC64)
633
FPU_FCTI(fctid, int64, 0x8000000000000000)
634
FPU_FCTI(fctidz, int64_round_to_zero, 0x8000000000000000)
635
FPU_FCTI(fctidu, uint64, 0x0000000000000000)
636
FPU_FCTI(fctiduz, uint64_round_to_zero, 0x0000000000000000)
637
#endif
638

    
639
#if defined(TARGET_PPC64)
640
/* fcfid - fcfid. */
641
uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
642
{
643
    CPU_DoubleU farg;
644

    
645
    farg.d = int64_to_float64(arg, &env->fp_status);
646
    return farg.ll;
647
}
648

    
649

    
650

    
651
#endif
652

    
653
static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
654
                              int rounding_mode)
655
{
656
    CPU_DoubleU farg;
657

    
658
    farg.ll = arg;
659

    
660
    if (unlikely(float64_is_signaling_nan(farg.d))) {
661
        /* sNaN round */
662
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
663
                                        POWERPC_EXCP_FP_VXCVI, 1);
664
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
665
                        float64_is_infinity(farg.d))) {
666
        /* qNan / infinity round */
667
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
668
    } else {
669
        set_float_rounding_mode(rounding_mode, &env->fp_status);
670
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
671
        /* Restore rounding mode from FPSCR */
672
        fpscr_set_rounding_mode(env);
673
    }
674
    return farg.ll;
675
}
676

    
677
uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
678
{
679
    return do_fri(env, arg, float_round_nearest_even);
680
}
681

    
682
uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
683
{
684
    return do_fri(env, arg, float_round_to_zero);
685
}
686

    
687
uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
688
{
689
    return do_fri(env, arg, float_round_up);
690
}
691

    
692
uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
693
{
694
    return do_fri(env, arg, float_round_down);
695
}
696

    
697
/* fmadd - fmadd. */
698
uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
699
                      uint64_t arg3)
700
{
701
    CPU_DoubleU farg1, farg2, farg3;
702

    
703
    farg1.ll = arg1;
704
    farg2.ll = arg2;
705
    farg3.ll = arg3;
706

    
707
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
708
                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
709
        /* Multiplication of zero by infinity */
710
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
711
    } else {
712
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
713
                     float64_is_signaling_nan(farg2.d) ||
714
                     float64_is_signaling_nan(farg3.d))) {
715
            /* sNaN operation */
716
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
717
        }
718
        /* This is the way the PowerPC specification defines it */
719
        float128 ft0_128, ft1_128;
720

    
721
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
722
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
723
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
724
        if (unlikely(float128_is_infinity(ft0_128) &&
725
                     float64_is_infinity(farg3.d) &&
726
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
727
            /* Magnitude subtraction of infinities */
728
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
729
        } else {
730
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
731
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
732
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
733
        }
734
    }
735

    
736
    return farg1.ll;
737
}
738

    
739
/* fmsub - fmsub. */
740
uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
741
                      uint64_t arg3)
742
{
743
    CPU_DoubleU farg1, farg2, farg3;
744

    
745
    farg1.ll = arg1;
746
    farg2.ll = arg2;
747
    farg3.ll = arg3;
748

    
749
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
750
                 (float64_is_zero(farg1.d) &&
751
                  float64_is_infinity(farg2.d)))) {
752
        /* Multiplication of zero by infinity */
753
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
754
    } else {
755
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
756
                     float64_is_signaling_nan(farg2.d) ||
757
                     float64_is_signaling_nan(farg3.d))) {
758
            /* sNaN operation */
759
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
760
        }
761
        /* This is the way the PowerPC specification defines it */
762
        float128 ft0_128, ft1_128;
763

    
764
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
765
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
766
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
767
        if (unlikely(float128_is_infinity(ft0_128) &&
768
                     float64_is_infinity(farg3.d) &&
769
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
770
            /* Magnitude subtraction of infinities */
771
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
772
        } else {
773
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
774
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
775
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
776
        }
777
    }
778
    return farg1.ll;
779
}
780

    
781
/* fnmadd - fnmadd. */
782
uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
783
                       uint64_t arg3)
784
{
785
    CPU_DoubleU farg1, farg2, farg3;
786

    
787
    farg1.ll = arg1;
788
    farg2.ll = arg2;
789
    farg3.ll = arg3;
790

    
791
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
792
                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
793
        /* Multiplication of zero by infinity */
794
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
795
    } else {
796
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
797
                     float64_is_signaling_nan(farg2.d) ||
798
                     float64_is_signaling_nan(farg3.d))) {
799
            /* sNaN operation */
800
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
801
        }
802
        /* This is the way the PowerPC specification defines it */
803
        float128 ft0_128, ft1_128;
804

    
805
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
806
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
807
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
808
        if (unlikely(float128_is_infinity(ft0_128) &&
809
                     float64_is_infinity(farg3.d) &&
810
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
811
            /* Magnitude subtraction of infinities */
812
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
813
        } else {
814
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
815
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
816
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
817
        }
818
        if (likely(!float64_is_any_nan(farg1.d))) {
819
            farg1.d = float64_chs(farg1.d);
820
        }
821
    }
822
    return farg1.ll;
823
}
824

    
825
/* fnmsub - fnmsub. */
826
uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
827
                       uint64_t arg3)
828
{
829
    CPU_DoubleU farg1, farg2, farg3;
830

    
831
    farg1.ll = arg1;
832
    farg2.ll = arg2;
833
    farg3.ll = arg3;
834

    
835
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
836
                 (float64_is_zero(farg1.d) &&
837
                  float64_is_infinity(farg2.d)))) {
838
        /* Multiplication of zero by infinity */
839
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
840
    } else {
841
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
842
                     float64_is_signaling_nan(farg2.d) ||
843
                     float64_is_signaling_nan(farg3.d))) {
844
            /* sNaN operation */
845
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
846
        }
847
        /* This is the way the PowerPC specification defines it */
848
        float128 ft0_128, ft1_128;
849

    
850
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
851
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
852
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
853
        if (unlikely(float128_is_infinity(ft0_128) &&
854
                     float64_is_infinity(farg3.d) &&
855
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
856
            /* Magnitude subtraction of infinities */
857
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
858
        } else {
859
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
860
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
861
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
862
        }
863
        if (likely(!float64_is_any_nan(farg1.d))) {
864
            farg1.d = float64_chs(farg1.d);
865
        }
866
    }
867
    return farg1.ll;
868
}
869

    
870
/* frsp - frsp. */
871
uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
872
{
873
    CPU_DoubleU farg;
874
    float32 f32;
875

    
876
    farg.ll = arg;
877

    
878
    if (unlikely(float64_is_signaling_nan(farg.d))) {
879
        /* sNaN square root */
880
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
881
    }
882
    f32 = float64_to_float32(farg.d, &env->fp_status);
883
    farg.d = float32_to_float64(f32, &env->fp_status);
884

    
885
    return farg.ll;
886
}
887

    
888
/* fsqrt - fsqrt. */
889
uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
890
{
891
    CPU_DoubleU farg;
892

    
893
    farg.ll = arg;
894

    
895
    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
896
        /* Square root of a negative nonzero number */
897
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
898
    } else {
899
        if (unlikely(float64_is_signaling_nan(farg.d))) {
900
            /* sNaN square root */
901
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
902
        }
903
        farg.d = float64_sqrt(farg.d, &env->fp_status);
904
    }
905
    return farg.ll;
906
}
907

    
908
/* fre - fre. */
909
uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
910
{
911
    CPU_DoubleU farg;
912

    
913
    farg.ll = arg;
914

    
915
    if (unlikely(float64_is_signaling_nan(farg.d))) {
916
        /* sNaN reciprocal */
917
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
918
    }
919
    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
920
    return farg.d;
921
}
922

    
923
/* fres - fres. */
924
uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
925
{
926
    CPU_DoubleU farg;
927
    float32 f32;
928

    
929
    farg.ll = arg;
930

    
931
    if (unlikely(float64_is_signaling_nan(farg.d))) {
932
        /* sNaN reciprocal */
933
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
934
    }
935
    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
936
    f32 = float64_to_float32(farg.d, &env->fp_status);
937
    farg.d = float32_to_float64(f32, &env->fp_status);
938

    
939
    return farg.ll;
940
}
941

    
942
/* frsqrte  - frsqrte. */
943
uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
944
{
945
    CPU_DoubleU farg;
946
    float32 f32;
947

    
948
    farg.ll = arg;
949

    
950
    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
951
        /* Reciprocal square root of a negative nonzero number */
952
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
953
    } else {
954
        if (unlikely(float64_is_signaling_nan(farg.d))) {
955
            /* sNaN reciprocal square root */
956
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
957
        }
958
        farg.d = float64_sqrt(farg.d, &env->fp_status);
959
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
960
        f32 = float64_to_float32(farg.d, &env->fp_status);
961
        farg.d = float32_to_float64(f32, &env->fp_status);
962
    }
963
    return farg.ll;
964
}
965

    
966
/* fsel - fsel. */
967
uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
968
                     uint64_t arg3)
969
{
970
    CPU_DoubleU farg1;
971

    
972
    farg1.ll = arg1;
973

    
974
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
975
        !float64_is_any_nan(farg1.d)) {
976
        return arg2;
977
    } else {
978
        return arg3;
979
    }
980
}
981

    
982
void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
983
                  uint32_t crfD)
984
{
985
    CPU_DoubleU farg1, farg2;
986
    uint32_t ret = 0;
987

    
988
    farg1.ll = arg1;
989
    farg2.ll = arg2;
990

    
991
    if (unlikely(float64_is_any_nan(farg1.d) ||
992
                 float64_is_any_nan(farg2.d))) {
993
        ret = 0x01UL;
994
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
995
        ret = 0x08UL;
996
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
997
        ret = 0x04UL;
998
    } else {
999
        ret = 0x02UL;
1000
    }
1001

    
1002
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1003
    env->fpscr |= ret << FPSCR_FPRF;
1004
    env->crf[crfD] = ret;
1005
    if (unlikely(ret == 0x01UL
1006
                 && (float64_is_signaling_nan(farg1.d) ||
1007
                     float64_is_signaling_nan(farg2.d)))) {
1008
        /* sNaN comparison */
1009
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
1010
    }
1011
}
1012

    
1013
void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1014
                  uint32_t crfD)
1015
{
1016
    CPU_DoubleU farg1, farg2;
1017
    uint32_t ret = 0;
1018

    
1019
    farg1.ll = arg1;
1020
    farg2.ll = arg2;
1021

    
1022
    if (unlikely(float64_is_any_nan(farg1.d) ||
1023
                 float64_is_any_nan(farg2.d))) {
1024
        ret = 0x01UL;
1025
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1026
        ret = 0x08UL;
1027
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1028
        ret = 0x04UL;
1029
    } else {
1030
        ret = 0x02UL;
1031
    }
1032

    
1033
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1034
    env->fpscr |= ret << FPSCR_FPRF;
1035
    env->crf[crfD] = ret;
1036
    if (unlikely(ret == 0x01UL)) {
1037
        if (float64_is_signaling_nan(farg1.d) ||
1038
            float64_is_signaling_nan(farg2.d)) {
1039
            /* sNaN comparison */
1040
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
1041
                                  POWERPC_EXCP_FP_VXVC, 1);
1042
        } else {
1043
            /* qNaN comparison */
1044
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
1045
        }
1046
    }
1047
}
1048

    
1049
/* Single-precision floating-point conversions */
1050
static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val)
1051
{
1052
    CPU_FloatU u;
1053

    
1054
    u.f = int32_to_float32(val, &env->vec_status);
1055

    
1056
    return u.l;
1057
}
1058

    
1059
static inline uint32_t efscfui(CPUPPCState *env, uint32_t val)
1060
{
1061
    CPU_FloatU u;
1062

    
1063
    u.f = uint32_to_float32(val, &env->vec_status);
1064

    
1065
    return u.l;
1066
}
1067

    
1068
static inline int32_t efsctsi(CPUPPCState *env, uint32_t val)
1069
{
1070
    CPU_FloatU u;
1071

    
1072
    u.l = val;
1073
    /* NaN are not treated the same way IEEE 754 does */
1074
    if (unlikely(float32_is_quiet_nan(u.f))) {
1075
        return 0;
1076
    }
1077

    
1078
    return float32_to_int32(u.f, &env->vec_status);
1079
}
1080

    
1081
static inline uint32_t efsctui(CPUPPCState *env, uint32_t val)
1082
{
1083
    CPU_FloatU u;
1084

    
1085
    u.l = val;
1086
    /* NaN are not treated the same way IEEE 754 does */
1087
    if (unlikely(float32_is_quiet_nan(u.f))) {
1088
        return 0;
1089
    }
1090

    
1091
    return float32_to_uint32(u.f, &env->vec_status);
1092
}
1093

    
1094
static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val)
1095
{
1096
    CPU_FloatU u;
1097

    
1098
    u.l = val;
1099
    /* NaN are not treated the same way IEEE 754 does */
1100
    if (unlikely(float32_is_quiet_nan(u.f))) {
1101
        return 0;
1102
    }
1103

    
1104
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
1105
}
1106

    
1107
static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val)
1108
{
1109
    CPU_FloatU u;
1110

    
1111
    u.l = val;
1112
    /* NaN are not treated the same way IEEE 754 does */
1113
    if (unlikely(float32_is_quiet_nan(u.f))) {
1114
        return 0;
1115
    }
1116

    
1117
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
1118
}
1119

    
1120
static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val)
1121
{
1122
    CPU_FloatU u;
1123
    float32 tmp;
1124

    
1125
    u.f = int32_to_float32(val, &env->vec_status);
1126
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
1127
    u.f = float32_div(u.f, tmp, &env->vec_status);
1128

    
1129
    return u.l;
1130
}
1131

    
1132
static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val)
1133
{
1134
    CPU_FloatU u;
1135
    float32 tmp;
1136

    
1137
    u.f = uint32_to_float32(val, &env->vec_status);
1138
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1139
    u.f = float32_div(u.f, tmp, &env->vec_status);
1140

    
1141
    return u.l;
1142
}
1143

    
1144
static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val)
1145
{
1146
    CPU_FloatU u;
1147
    float32 tmp;
1148

    
1149
    u.l = val;
1150
    /* NaN are not treated the same way IEEE 754 does */
1151
    if (unlikely(float32_is_quiet_nan(u.f))) {
1152
        return 0;
1153
    }
1154
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1155
    u.f = float32_mul(u.f, tmp, &env->vec_status);
1156

    
1157
    return float32_to_int32(u.f, &env->vec_status);
1158
}
1159

    
1160
static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val)
1161
{
1162
    CPU_FloatU u;
1163
    float32 tmp;
1164

    
1165
    u.l = val;
1166
    /* NaN are not treated the same way IEEE 754 does */
1167
    if (unlikely(float32_is_quiet_nan(u.f))) {
1168
        return 0;
1169
    }
1170
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1171
    u.f = float32_mul(u.f, tmp, &env->vec_status);
1172

    
1173
    return float32_to_uint32(u.f, &env->vec_status);
1174
}
1175

    
1176
#define HELPER_SPE_SINGLE_CONV(name)                              \
1177
    uint32_t helper_e##name(CPUPPCState *env, uint32_t val)       \
1178
    {                                                             \
1179
        return e##name(env, val);                                 \
1180
    }
1181
/* efscfsi */
1182
HELPER_SPE_SINGLE_CONV(fscfsi);
1183
/* efscfui */
1184
HELPER_SPE_SINGLE_CONV(fscfui);
1185
/* efscfuf */
1186
HELPER_SPE_SINGLE_CONV(fscfuf);
1187
/* efscfsf */
1188
HELPER_SPE_SINGLE_CONV(fscfsf);
1189
/* efsctsi */
1190
HELPER_SPE_SINGLE_CONV(fsctsi);
1191
/* efsctui */
1192
HELPER_SPE_SINGLE_CONV(fsctui);
1193
/* efsctsiz */
1194
HELPER_SPE_SINGLE_CONV(fsctsiz);
1195
/* efsctuiz */
1196
HELPER_SPE_SINGLE_CONV(fsctuiz);
1197
/* efsctsf */
1198
HELPER_SPE_SINGLE_CONV(fsctsf);
1199
/* efsctuf */
1200
HELPER_SPE_SINGLE_CONV(fsctuf);
1201

    
1202
#define HELPER_SPE_VECTOR_CONV(name)                            \
1203
    uint64_t helper_ev##name(CPUPPCState *env, uint64_t val)    \
1204
    {                                                           \
1205
        return ((uint64_t)e##name(env, val >> 32) << 32) |      \
1206
            (uint64_t)e##name(env, val);                        \
1207
    }
1208
/* evfscfsi */
1209
HELPER_SPE_VECTOR_CONV(fscfsi);
1210
/* evfscfui */
1211
HELPER_SPE_VECTOR_CONV(fscfui);
1212
/* evfscfuf */
1213
HELPER_SPE_VECTOR_CONV(fscfuf);
1214
/* evfscfsf */
1215
HELPER_SPE_VECTOR_CONV(fscfsf);
1216
/* evfsctsi */
1217
HELPER_SPE_VECTOR_CONV(fsctsi);
1218
/* evfsctui */
1219
HELPER_SPE_VECTOR_CONV(fsctui);
1220
/* evfsctsiz */
1221
HELPER_SPE_VECTOR_CONV(fsctsiz);
1222
/* evfsctuiz */
1223
HELPER_SPE_VECTOR_CONV(fsctuiz);
1224
/* evfsctsf */
1225
HELPER_SPE_VECTOR_CONV(fsctsf);
1226
/* evfsctuf */
1227
HELPER_SPE_VECTOR_CONV(fsctuf);
1228

    
1229
/* Single-precision floating-point arithmetic */
1230
static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2)
1231
{
1232
    CPU_FloatU u1, u2;
1233

    
1234
    u1.l = op1;
1235
    u2.l = op2;
1236
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
1237
    return u1.l;
1238
}
1239

    
1240
static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2)
1241
{
1242
    CPU_FloatU u1, u2;
1243

    
1244
    u1.l = op1;
1245
    u2.l = op2;
1246
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
1247
    return u1.l;
1248
}
1249

    
1250
static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2)
1251
{
1252
    CPU_FloatU u1, u2;
1253

    
1254
    u1.l = op1;
1255
    u2.l = op2;
1256
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
1257
    return u1.l;
1258
}
1259

    
1260
static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2)
1261
{
1262
    CPU_FloatU u1, u2;
1263

    
1264
    u1.l = op1;
1265
    u2.l = op2;
1266
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
1267
    return u1.l;
1268
}
1269

    
1270
#define HELPER_SPE_SINGLE_ARITH(name)                                   \
1271
    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1272
    {                                                                   \
1273
        return e##name(env, op1, op2);                                  \
1274
    }
1275
/* efsadd */
1276
HELPER_SPE_SINGLE_ARITH(fsadd);
1277
/* efssub */
1278
HELPER_SPE_SINGLE_ARITH(fssub);
1279
/* efsmul */
1280
HELPER_SPE_SINGLE_ARITH(fsmul);
1281
/* efsdiv */
1282
HELPER_SPE_SINGLE_ARITH(fsdiv);
1283

    
1284
#define HELPER_SPE_VECTOR_ARITH(name)                                   \
1285
    uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1286
    {                                                                   \
1287
        return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) |   \
1288
            (uint64_t)e##name(env, op1, op2);                           \
1289
    }
1290
/* evfsadd */
1291
HELPER_SPE_VECTOR_ARITH(fsadd);
1292
/* evfssub */
1293
HELPER_SPE_VECTOR_ARITH(fssub);
1294
/* evfsmul */
1295
HELPER_SPE_VECTOR_ARITH(fsmul);
1296
/* evfsdiv */
1297
HELPER_SPE_VECTOR_ARITH(fsdiv);
1298

    
1299
/* Single-precision floating-point comparisons */
1300
static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1301
{
1302
    CPU_FloatU u1, u2;
1303

    
1304
    u1.l = op1;
1305
    u2.l = op2;
1306
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1307
}
1308

    
1309
static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1310
{
1311
    CPU_FloatU u1, u2;
1312

    
1313
    u1.l = op1;
1314
    u2.l = op2;
1315
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
1316
}
1317

    
1318
static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1319
{
1320
    CPU_FloatU u1, u2;
1321

    
1322
    u1.l = op1;
1323
    u2.l = op2;
1324
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1325
}
1326

    
1327
static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1328
{
1329
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1330
    return efscmplt(env, op1, op2);
1331
}
1332

    
1333
static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1334
{
1335
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1336
    return efscmpgt(env, op1, op2);
1337
}
1338

    
1339
static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1340
{
1341
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1342
    return efscmpeq(env, op1, op2);
1343
}
1344

    
1345
#define HELPER_SINGLE_SPE_CMP(name)                                     \
1346
    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1347
    {                                                                   \
1348
        return e##name(env, op1, op2) << 2;                             \
1349
    }
1350
/* efststlt */
1351
HELPER_SINGLE_SPE_CMP(fststlt);
1352
/* efststgt */
1353
HELPER_SINGLE_SPE_CMP(fststgt);
1354
/* efststeq */
1355
HELPER_SINGLE_SPE_CMP(fststeq);
1356
/* efscmplt */
1357
HELPER_SINGLE_SPE_CMP(fscmplt);
1358
/* efscmpgt */
1359
HELPER_SINGLE_SPE_CMP(fscmpgt);
1360
/* efscmpeq */
1361
HELPER_SINGLE_SPE_CMP(fscmpeq);
1362

    
1363
static inline uint32_t evcmp_merge(int t0, int t1)
1364
{
1365
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1366
}
1367

    
1368
#define HELPER_VECTOR_SPE_CMP(name)                                     \
1369
    uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1370
    {                                                                   \
1371
        return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32),          \
1372
                           e##name(env, op1, op2));                     \
1373
    }
1374
/* evfststlt */
1375
HELPER_VECTOR_SPE_CMP(fststlt);
1376
/* evfststgt */
1377
HELPER_VECTOR_SPE_CMP(fststgt);
1378
/* evfststeq */
1379
HELPER_VECTOR_SPE_CMP(fststeq);
1380
/* evfscmplt */
1381
HELPER_VECTOR_SPE_CMP(fscmplt);
1382
/* evfscmpgt */
1383
HELPER_VECTOR_SPE_CMP(fscmpgt);
1384
/* evfscmpeq */
1385
HELPER_VECTOR_SPE_CMP(fscmpeq);
1386

    
1387
/* Double-precision floating-point conversion */
1388
uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val)
1389
{
1390
    CPU_DoubleU u;
1391

    
1392
    u.d = int32_to_float64(val, &env->vec_status);
1393

    
1394
    return u.ll;
1395
}
1396

    
1397
uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val)
1398
{
1399
    CPU_DoubleU u;
1400

    
1401
    u.d = int64_to_float64(val, &env->vec_status);
1402

    
1403
    return u.ll;
1404
}
1405

    
1406
uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val)
1407
{
1408
    CPU_DoubleU u;
1409

    
1410
    u.d = uint32_to_float64(val, &env->vec_status);
1411

    
1412
    return u.ll;
1413
}
1414

    
1415
uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val)
1416
{
1417
    CPU_DoubleU u;
1418

    
1419
    u.d = uint64_to_float64(val, &env->vec_status);
1420

    
1421
    return u.ll;
1422
}
1423

    
1424
uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val)
1425
{
1426
    CPU_DoubleU u;
1427

    
1428
    u.ll = val;
1429
    /* NaN are not treated the same way IEEE 754 does */
1430
    if (unlikely(float64_is_any_nan(u.d))) {
1431
        return 0;
1432
    }
1433

    
1434
    return float64_to_int32(u.d, &env->vec_status);
1435
}
1436

    
1437
uint32_t helper_efdctui(CPUPPCState *env, uint64_t val)
1438
{
1439
    CPU_DoubleU u;
1440

    
1441
    u.ll = val;
1442
    /* NaN are not treated the same way IEEE 754 does */
1443
    if (unlikely(float64_is_any_nan(u.d))) {
1444
        return 0;
1445
    }
1446

    
1447
    return float64_to_uint32(u.d, &env->vec_status);
1448
}
1449

    
1450
uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val)
1451
{
1452
    CPU_DoubleU u;
1453

    
1454
    u.ll = val;
1455
    /* NaN are not treated the same way IEEE 754 does */
1456
    if (unlikely(float64_is_any_nan(u.d))) {
1457
        return 0;
1458
    }
1459

    
1460
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
1461
}
1462

    
1463
uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val)
1464
{
1465
    CPU_DoubleU u;
1466

    
1467
    u.ll = val;
1468
    /* NaN are not treated the same way IEEE 754 does */
1469
    if (unlikely(float64_is_any_nan(u.d))) {
1470
        return 0;
1471
    }
1472

    
1473
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
1474
}
1475

    
1476
uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val)
1477
{
1478
    CPU_DoubleU u;
1479

    
1480
    u.ll = val;
1481
    /* NaN are not treated the same way IEEE 754 does */
1482
    if (unlikely(float64_is_any_nan(u.d))) {
1483
        return 0;
1484
    }
1485

    
1486
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
1487
}
1488

    
1489
uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val)
1490
{
1491
    CPU_DoubleU u;
1492

    
1493
    u.ll = val;
1494
    /* NaN are not treated the same way IEEE 754 does */
1495
    if (unlikely(float64_is_any_nan(u.d))) {
1496
        return 0;
1497
    }
1498

    
1499
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
1500
}
1501

    
1502
uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val)
1503
{
1504
    CPU_DoubleU u;
1505
    float64 tmp;
1506

    
1507
    u.d = int32_to_float64(val, &env->vec_status);
1508
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1509
    u.d = float64_div(u.d, tmp, &env->vec_status);
1510

    
1511
    return u.ll;
1512
}
1513

    
1514
uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val)
1515
{
1516
    CPU_DoubleU u;
1517
    float64 tmp;
1518

    
1519
    u.d = uint32_to_float64(val, &env->vec_status);
1520
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1521
    u.d = float64_div(u.d, tmp, &env->vec_status);
1522

    
1523
    return u.ll;
1524
}
1525

    
1526
uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val)
1527
{
1528
    CPU_DoubleU u;
1529
    float64 tmp;
1530

    
1531
    u.ll = val;
1532
    /* NaN are not treated the same way IEEE 754 does */
1533
    if (unlikely(float64_is_any_nan(u.d))) {
1534
        return 0;
1535
    }
1536
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1537
    u.d = float64_mul(u.d, tmp, &env->vec_status);
1538

    
1539
    return float64_to_int32(u.d, &env->vec_status);
1540
}
1541

    
1542
uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val)
1543
{
1544
    CPU_DoubleU u;
1545
    float64 tmp;
1546

    
1547
    u.ll = val;
1548
    /* NaN are not treated the same way IEEE 754 does */
1549
    if (unlikely(float64_is_any_nan(u.d))) {
1550
        return 0;
1551
    }
1552
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1553
    u.d = float64_mul(u.d, tmp, &env->vec_status);
1554

    
1555
    return float64_to_uint32(u.d, &env->vec_status);
1556
}
1557

    
1558
uint32_t helper_efscfd(CPUPPCState *env, uint64_t val)
1559
{
1560
    CPU_DoubleU u1;
1561
    CPU_FloatU u2;
1562

    
1563
    u1.ll = val;
1564
    u2.f = float64_to_float32(u1.d, &env->vec_status);
1565

    
1566
    return u2.l;
1567
}
1568

    
1569
uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val)
1570
{
1571
    CPU_DoubleU u2;
1572
    CPU_FloatU u1;
1573

    
1574
    u1.l = val;
1575
    u2.d = float32_to_float64(u1.f, &env->vec_status);
1576

    
1577
    return u2.ll;
1578
}
1579

    
1580
/* Double precision fixed-point arithmetic */
1581
uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2)
1582
{
1583
    CPU_DoubleU u1, u2;
1584

    
1585
    u1.ll = op1;
1586
    u2.ll = op2;
1587
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
1588
    return u1.ll;
1589
}
1590

    
1591
uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2)
1592
{
1593
    CPU_DoubleU u1, u2;
1594

    
1595
    u1.ll = op1;
1596
    u2.ll = op2;
1597
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
1598
    return u1.ll;
1599
}
1600

    
1601
uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2)
1602
{
1603
    CPU_DoubleU u1, u2;
1604

    
1605
    u1.ll = op1;
1606
    u2.ll = op2;
1607
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
1608
    return u1.ll;
1609
}
1610

    
1611
uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2)
1612
{
1613
    CPU_DoubleU u1, u2;
1614

    
1615
    u1.ll = op1;
1616
    u2.ll = op2;
1617
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
1618
    return u1.ll;
1619
}
1620

    
1621
/* Double precision floating point helpers */
1622
uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1623
{
1624
    CPU_DoubleU u1, u2;
1625

    
1626
    u1.ll = op1;
1627
    u2.ll = op2;
1628
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1629
}
1630

    
1631
uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1632
{
1633
    CPU_DoubleU u1, u2;
1634

    
1635
    u1.ll = op1;
1636
    u2.ll = op2;
1637
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
1638
}
1639

    
1640
uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1641
{
1642
    CPU_DoubleU u1, u2;
1643

    
1644
    u1.ll = op1;
1645
    u2.ll = op2;
1646
    return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1647
}
1648

    
1649
uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1650
{
1651
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1652
    return helper_efdtstlt(env, op1, op2);
1653
}
1654

    
1655
uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1656
{
1657
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1658
    return helper_efdtstgt(env, op1, op2);
1659
}
1660

    
1661
uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1662
{
1663
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1664
    return helper_efdtsteq(env, op1, op2);
1665
}
1666

    
1667
#define DECODE_SPLIT(opcode, shift1, nb1, shift2, nb2) \
1668
    (((((opcode) >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) |    \
1669
     (((opcode) >> (shift2)) & ((1 << (nb2)) - 1)))
1670

    
1671
#define xT(opcode) DECODE_SPLIT(opcode, 0, 1, 21, 5)
1672
#define xA(opcode) DECODE_SPLIT(opcode, 2, 1, 16, 5)
1673
#define xB(opcode) DECODE_SPLIT(opcode, 1, 1, 11, 5)
1674
#define xC(opcode) DECODE_SPLIT(opcode, 3, 1,  6, 5)
1675
#define BF(opcode) (((opcode) >> (31-8)) & 7)
1676

    
1677
typedef union _ppc_vsr_t {
1678
    uint64_t u64[2];
1679
    uint32_t u32[4];
1680
    float32 f32[4];
1681
    float64 f64[2];
1682
} ppc_vsr_t;
1683

    
1684
static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
1685
{
1686
    if (n < 32) {
1687
        vsr->f64[0] = env->fpr[n];
1688
        vsr->u64[1] = env->vsr[n];
1689
    } else {
1690
        vsr->u64[0] = env->avr[n-32].u64[0];
1691
        vsr->u64[1] = env->avr[n-32].u64[1];
1692
    }
1693
}
1694

    
1695
static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
1696
{
1697
    if (n < 32) {
1698
        env->fpr[n] = vsr->f64[0];
1699
        env->vsr[n] = vsr->u64[1];
1700
    } else {
1701
        env->avr[n-32].u64[0] = vsr->u64[0];
1702
        env->avr[n-32].u64[1] = vsr->u64[1];
1703
    }
1704
}
1705

    
1706
#define float64_to_float64(x, env) x
1707

    
1708

    
1709
/* VSX_ADD_SUB - VSX floating point add/subract
1710
 *   name  - instruction mnemonic
1711
 *   op    - operation (add or sub)
1712
 *   nels  - number of elements (1, 2 or 4)
1713
 *   tp    - type (float32 or float64)
1714
 *   fld   - vsr_t field (f32 or f64)
1715
 *   sfprf - set FPRF
1716
 */
1717
#define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp)                    \
1718
void helper_##name(CPUPPCState *env, uint32_t opcode)                        \
1719
{                                                                            \
1720
    ppc_vsr_t xt, xa, xb;                                                    \
1721
    int i;                                                                   \
1722
                                                                             \
1723
    getVSR(xA(opcode), &xa, env);                                            \
1724
    getVSR(xB(opcode), &xb, env);                                            \
1725
    getVSR(xT(opcode), &xt, env);                                            \
1726
    helper_reset_fpstatus(env);                                              \
1727
                                                                             \
1728
    for (i = 0; i < nels; i++) {                                             \
1729
        float_status tstat = env->fp_status;                                 \
1730
        set_float_exception_flags(0, &tstat);                                \
1731
        xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &tstat);                 \
1732
        env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1733
                                                                             \
1734
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1735
            if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) {\
1736
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    \
1737
            } else if (tp##_is_signaling_nan(xa.fld[i]) ||                   \
1738
                       tp##_is_signaling_nan(xb.fld[i])) {                   \
1739
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
1740
            }                                                                \
1741
        }                                                                    \
1742
                                                                             \
1743
        if (r2sp) {                                                          \
1744
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                         \
1745
        }                                                                    \
1746
                                                                             \
1747
        if (sfprf) {                                                         \
1748
            helper_compute_fprf(env, xt.fld[i], sfprf);                      \
1749
        }                                                                    \
1750
    }                                                                        \
1751
    putVSR(xT(opcode), &xt, env);                                            \
1752
    helper_float_check_status(env);                                          \
1753
}
1754

    
1755
VSX_ADD_SUB(xsadddp, add, 1, float64, f64, 1, 0)
1756
VSX_ADD_SUB(xsaddsp, add, 1, float64, f64, 1, 1)
1757
VSX_ADD_SUB(xvadddp, add, 2, float64, f64, 0, 0)
1758
VSX_ADD_SUB(xvaddsp, add, 4, float32, f32, 0, 0)
1759
VSX_ADD_SUB(xssubdp, sub, 1, float64, f64, 1, 0)
1760
VSX_ADD_SUB(xssubsp, sub, 1, float64, f64, 1, 1)
1761
VSX_ADD_SUB(xvsubdp, sub, 2, float64, f64, 0, 0)
1762
VSX_ADD_SUB(xvsubsp, sub, 4, float32, f32, 0, 0)
1763

    
1764
/* VSX_MUL - VSX floating point multiply
1765
 *   op    - instruction mnemonic
1766
 *   nels  - number of elements (1, 2 or 4)
1767
 *   tp    - type (float32 or float64)
1768
 *   fld   - vsr_t field (f32 or f64)
1769
 *   sfprf - set FPRF
1770
 */
1771
#define VSX_MUL(op, nels, tp, fld, sfprf, r2sp)                              \
1772
void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
1773
{                                                                            \
1774
    ppc_vsr_t xt, xa, xb;                                                    \
1775
    int i;                                                                   \
1776
                                                                             \
1777
    getVSR(xA(opcode), &xa, env);                                            \
1778
    getVSR(xB(opcode), &xb, env);                                            \
1779
    getVSR(xT(opcode), &xt, env);                                            \
1780
    helper_reset_fpstatus(env);                                              \
1781
                                                                             \
1782
    for (i = 0; i < nels; i++) {                                             \
1783
        float_status tstat = env->fp_status;                                 \
1784
        set_float_exception_flags(0, &tstat);                                \
1785
        xt.fld[i] = tp##_mul(xa.fld[i], xb.fld[i], &tstat);                  \
1786
        env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1787
                                                                             \
1788
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1789
            if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(xb.fld[i])) ||  \
1790
                (tp##_is_infinity(xb.fld[i]) && tp##_is_zero(xa.fld[i]))) {  \
1791
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf);    \
1792
            } else if (tp##_is_signaling_nan(xa.fld[i]) ||                   \
1793
                       tp##_is_signaling_nan(xb.fld[i])) {                   \
1794
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
1795
            }                                                                \
1796
        }                                                                    \
1797
                                                                             \
1798
        if (r2sp) {                                                          \
1799
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                         \
1800
        }                                                                    \
1801
                                                                             \
1802
        if (sfprf) {                                                         \
1803
            helper_compute_fprf(env, xt.fld[i], sfprf);                      \
1804
        }                                                                    \
1805
    }                                                                        \
1806
                                                                             \
1807
    putVSR(xT(opcode), &xt, env);                                            \
1808
    helper_float_check_status(env);                                          \
1809
}
1810

    
1811
VSX_MUL(xsmuldp, 1, float64, f64, 1, 0)
1812
VSX_MUL(xsmulsp, 1, float64, f64, 1, 1)
1813
VSX_MUL(xvmuldp, 2, float64, f64, 0, 0)
1814
VSX_MUL(xvmulsp, 4, float32, f32, 0, 0)
1815

    
1816
/* VSX_DIV - VSX floating point divide
1817
 *   op    - instruction mnemonic
1818
 *   nels  - number of elements (1, 2 or 4)
1819
 *   tp    - type (float32 or float64)
1820
 *   fld   - vsr_t field (f32 or f64)
1821
 *   sfprf - set FPRF
1822
 */
1823
#define VSX_DIV(op, nels, tp, fld, sfprf, r2sp)                               \
1824
void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
1825
{                                                                             \
1826
    ppc_vsr_t xt, xa, xb;                                                     \
1827
    int i;                                                                    \
1828
                                                                              \
1829
    getVSR(xA(opcode), &xa, env);                                             \
1830
    getVSR(xB(opcode), &xb, env);                                             \
1831
    getVSR(xT(opcode), &xt, env);                                             \
1832
    helper_reset_fpstatus(env);                                               \
1833
                                                                              \
1834
    for (i = 0; i < nels; i++) {                                              \
1835
        float_status tstat = env->fp_status;                                  \
1836
        set_float_exception_flags(0, &tstat);                                 \
1837
        xt.fld[i] = tp##_div(xa.fld[i], xb.fld[i], &tstat);                   \
1838
        env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
1839
                                                                              \
1840
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
1841
            if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) { \
1842
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf);     \
1843
            } else if (tp##_is_zero(xa.fld[i]) &&                             \
1844
                tp##_is_zero(xb.fld[i])) {                                    \
1845
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf);     \
1846
            } else if (tp##_is_signaling_nan(xa.fld[i]) ||                    \
1847
                tp##_is_signaling_nan(xb.fld[i])) {                           \
1848
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
1849
            }                                                                 \
1850
        }                                                                     \
1851
                                                                              \
1852
        if (r2sp) {                                                           \
1853
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                          \
1854
        }                                                                     \
1855
                                                                              \
1856
        if (sfprf) {                                                          \
1857
            helper_compute_fprf(env, xt.fld[i], sfprf);                       \
1858
        }                                                                     \
1859
    }                                                                         \
1860
                                                                              \
1861
    putVSR(xT(opcode), &xt, env);                                             \
1862
    helper_float_check_status(env);                                           \
1863
}
1864

    
1865
VSX_DIV(xsdivdp, 1, float64, f64, 1, 0)
1866
VSX_DIV(xsdivsp, 1, float64, f64, 1, 1)
1867
VSX_DIV(xvdivdp, 2, float64, f64, 0, 0)
1868
VSX_DIV(xvdivsp, 4, float32, f32, 0, 0)
1869

    
1870
/* VSX_RE  - VSX floating point reciprocal estimate
1871
 *   op    - instruction mnemonic
1872
 *   nels  - number of elements (1, 2 or 4)
1873
 *   tp    - type (float32 or float64)
1874
 *   fld   - vsr_t field (f32 or f64)
1875
 *   sfprf - set FPRF
1876
 */
1877
#define VSX_RE(op, nels, tp, fld, sfprf, r2sp)                                \
1878
void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
1879
{                                                                             \
1880
    ppc_vsr_t xt, xb;                                                         \
1881
    int i;                                                                    \
1882
                                                                              \
1883
    getVSR(xB(opcode), &xb, env);                                             \
1884
    getVSR(xT(opcode), &xt, env);                                             \
1885
    helper_reset_fpstatus(env);                                               \
1886
                                                                              \
1887
    for (i = 0; i < nels; i++) {                                              \
1888
        if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) {                     \
1889
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
1890
        }                                                                     \
1891
        xt.fld[i] = tp##_div(tp##_one, xb.fld[i], &env->fp_status);           \
1892
                                                                              \
1893
        if (r2sp) {                                                           \
1894
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                          \
1895
        }                                                                     \
1896
                                                                              \
1897
        if (sfprf) {                                                          \
1898
            helper_compute_fprf(env, xt.fld[0], sfprf);                       \
1899
        }                                                                     \
1900
    }                                                                         \
1901
                                                                              \
1902
    putVSR(xT(opcode), &xt, env);                                             \
1903
    helper_float_check_status(env);                                           \
1904
}
1905

    
1906
VSX_RE(xsredp, 1, float64, f64, 1, 0)
1907
VSX_RE(xsresp, 1, float64, f64, 1, 1)
1908
VSX_RE(xvredp, 2, float64, f64, 0, 0)
1909
VSX_RE(xvresp, 4, float32, f32, 0, 0)
1910

    
1911
/* VSX_SQRT - VSX floating point square root
1912
 *   op    - instruction mnemonic
1913
 *   nels  - number of elements (1, 2 or 4)
1914
 *   tp    - type (float32 or float64)
1915
 *   fld   - vsr_t field (f32 or f64)
1916
 *   sfprf - set FPRF
1917
 */
1918
#define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp)                             \
1919
void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
1920
{                                                                            \
1921
    ppc_vsr_t xt, xb;                                                        \
1922
    int i;                                                                   \
1923
                                                                             \
1924
    getVSR(xB(opcode), &xb, env);                                            \
1925
    getVSR(xT(opcode), &xt, env);                                            \
1926
    helper_reset_fpstatus(env);                                              \
1927
                                                                             \
1928
    for (i = 0; i < nels; i++) {                                             \
1929
        float_status tstat = env->fp_status;                                 \
1930
        set_float_exception_flags(0, &tstat);                                \
1931
        xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat);                            \
1932
        env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1933
                                                                             \
1934
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1935
            if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) {        \
1936
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
1937
            } else if (tp##_is_signaling_nan(xb.fld[i])) {                   \
1938
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
1939
            }                                                                \
1940
        }                                                                    \
1941
                                                                             \
1942
        if (r2sp) {                                                          \
1943
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                         \
1944
        }                                                                    \
1945
                                                                             \
1946
        if (sfprf) {                                                         \
1947
            helper_compute_fprf(env, xt.fld[i], sfprf);                      \
1948
        }                                                                    \
1949
    }                                                                        \
1950
                                                                             \
1951
    putVSR(xT(opcode), &xt, env);                                            \
1952
    helper_float_check_status(env);                                          \
1953
}
1954

    
1955
VSX_SQRT(xssqrtdp, 1, float64, f64, 1, 0)
1956
VSX_SQRT(xssqrtsp, 1, float64, f64, 1, 1)
1957
VSX_SQRT(xvsqrtdp, 2, float64, f64, 0, 0)
1958
VSX_SQRT(xvsqrtsp, 4, float32, f32, 0, 0)
1959

    
1960
/* VSX_RSQRTE - VSX floating point reciprocal square root estimate
1961
 *   op    - instruction mnemonic
1962
 *   nels  - number of elements (1, 2 or 4)
1963
 *   tp    - type (float32 or float64)
1964
 *   fld   - vsr_t field (f32 or f64)
1965
 *   sfprf - set FPRF
1966
 */
1967
#define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp)                           \
1968
void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
1969
{                                                                            \
1970
    ppc_vsr_t xt, xb;                                                        \
1971
    int i;                                                                   \
1972
                                                                             \
1973
    getVSR(xB(opcode), &xb, env);                                            \
1974
    getVSR(xT(opcode), &xt, env);                                            \
1975
    helper_reset_fpstatus(env);                                              \
1976
                                                                             \
1977
    for (i = 0; i < nels; i++) {                                             \
1978
        float_status tstat = env->fp_status;                                 \
1979
        set_float_exception_flags(0, &tstat);                                \
1980
        xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat);                            \
1981
        xt.fld[i] = tp##_div(tp##_one, xt.fld[i], &tstat);                   \
1982
        env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1983
                                                                             \
1984
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1985
            if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) {        \
1986
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
1987
            } else if (tp##_is_signaling_nan(xb.fld[i])) {                   \
1988
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
1989
            }                                                                \
1990
        }                                                                    \
1991
                                                                             \
1992
        if (r2sp) {                                                          \
1993
            xt.fld[i] = helper_frsp(env, xt.fld[i]);                         \
1994
        }                                                                    \
1995
                                                                             \
1996
        if (sfprf) {                                                         \
1997
            helper_compute_fprf(env, xt.fld[i], sfprf);                      \
1998
        }                                                                    \
1999
    }                                                                        \
2000
                                                                             \
2001
    putVSR(xT(opcode), &xt, env);                                            \
2002
    helper_float_check_status(env);                                          \
2003
}
2004

    
2005
VSX_RSQRTE(xsrsqrtedp, 1, float64, f64, 1, 0)
2006
VSX_RSQRTE(xsrsqrtesp, 1, float64, f64, 1, 1)
2007
VSX_RSQRTE(xvrsqrtedp, 2, float64, f64, 0, 0)
2008
VSX_RSQRTE(xvrsqrtesp, 4, float32, f32, 0, 0)
2009

    
2010
static inline int ppc_float32_get_unbiased_exp(float32 f)
2011
{
2012
    return ((f >> 23) & 0xFF) - 127;
2013
}
2014

    
2015
static inline int ppc_float64_get_unbiased_exp(float64 f)
2016
{
2017
    return ((f >> 52) & 0x7FF) - 1023;
2018
}
2019

    
2020
/* VSX_TDIV - VSX floating point test for divide
2021
 *   op    - instruction mnemonic
2022
 *   nels  - number of elements (1, 2 or 4)
2023
 *   tp    - type (float32 or float64)
2024
 *   fld   - vsr_t field (f32 or f64)
2025
 *   emin  - minimum unbiased exponent
2026
 *   emax  - maximum unbiased exponent
2027
 *   nbits - number of fraction bits
2028
 */
2029
#define VSX_TDIV(op, nels, tp, fld, emin, emax, nbits)                  \
2030
void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
2031
{                                                                       \
2032
    ppc_vsr_t xa, xb;                                                   \
2033
    int i;                                                              \
2034
    int fe_flag = 0;                                                    \
2035
    int fg_flag = 0;                                                    \
2036
                                                                        \
2037
    getVSR(xA(opcode), &xa, env);                                       \
2038
    getVSR(xB(opcode), &xb, env);                                       \
2039
                                                                        \
2040
    for (i = 0; i < nels; i++) {                                        \
2041
        if (unlikely(tp##_is_infinity(xa.fld[i]) ||                     \
2042
                     tp##_is_infinity(xb.fld[i]) ||                     \
2043
                     tp##_is_zero(xb.fld[i]))) {                        \
2044
            fe_flag = 1;                                                \
2045
            fg_flag = 1;                                                \
2046
        } else {                                                        \
2047
            int e_a = ppc_##tp##_get_unbiased_exp(xa.fld[i]);           \
2048
            int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]);           \
2049
                                                                        \
2050
            if (unlikely(tp##_is_any_nan(xa.fld[i]) ||                  \
2051
                         tp##_is_any_nan(xb.fld[i]))) {                 \
2052
                fe_flag = 1;                                            \
2053
            } else if ((e_b <= emin) || (e_b >= (emax-2))) {            \
2054
                fe_flag = 1;                                            \
2055
            } else if (!tp##_is_zero(xa.fld[i]) &&                      \
2056
                       (((e_a - e_b) >= emax) ||                        \
2057
                        ((e_a - e_b) <= (emin+1)) ||                    \
2058
                         (e_a <= (emin+nbits)))) {                      \
2059
                fe_flag = 1;                                            \
2060
            }                                                           \
2061
                                                                        \
2062
            if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) {        \
2063
                /* XB is not zero because of the above check and */     \
2064
                /* so must be denormalized.                      */     \
2065
                fg_flag = 1;                                            \
2066
            }                                                           \
2067
        }                                                               \
2068
    }                                                                   \
2069
                                                                        \
2070
    env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
2071
}
2072

    
2073
VSX_TDIV(xstdivdp, 1, float64, f64, -1022, 1023, 52)
2074
VSX_TDIV(xvtdivdp, 2, float64, f64, -1022, 1023, 52)
2075
VSX_TDIV(xvtdivsp, 4, float32, f32, -126, 127, 23)
2076

    
2077
/* VSX_TSQRT - VSX floating point test for square root
2078
 *   op    - instruction mnemonic
2079
 *   nels  - number of elements (1, 2 or 4)
2080
 *   tp    - type (float32 or float64)
2081
 *   fld   - vsr_t field (f32 or f64)
2082
 *   emin  - minimum unbiased exponent
2083
 *   emax  - maximum unbiased exponent
2084
 *   nbits - number of fraction bits
2085
 */
2086
#define VSX_TSQRT(op, nels, tp, fld, emin, nbits)                       \
2087
void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
2088
{                                                                       \
2089
    ppc_vsr_t xa, xb;                                                   \
2090
    int i;                                                              \
2091
    int fe_flag = 0;                                                    \
2092
    int fg_flag = 0;                                                    \
2093
                                                                        \
2094
    getVSR(xA(opcode), &xa, env);                                       \
2095
    getVSR(xB(opcode), &xb, env);                                       \
2096
                                                                        \
2097
    for (i = 0; i < nels; i++) {                                        \
2098
        if (unlikely(tp##_is_infinity(xb.fld[i]) ||                     \
2099
                     tp##_is_zero(xb.fld[i]))) {                        \
2100
            fe_flag = 1;                                                \
2101
            fg_flag = 1;                                                \
2102
        } else {                                                        \
2103
            int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]);           \
2104
                                                                        \
2105
            if (unlikely(tp##_is_any_nan(xb.fld[i]))) {                 \
2106
                fe_flag = 1;                                            \
2107
            } else if (unlikely(tp##_is_zero(xb.fld[i]))) {             \
2108
                fe_flag = 1;                                            \
2109
            } else if (unlikely(tp##_is_neg(xb.fld[i]))) {              \
2110
                fe_flag = 1;                                            \
2111
            } else if (!tp##_is_zero(xb.fld[i]) &&                      \
2112
                      (e_b <= (emin+nbits))) {                          \
2113
                fe_flag = 1;                                            \
2114
            }                                                           \
2115
                                                                        \
2116
            if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) {        \
2117
                /* XB is not zero because of the above check and */     \
2118
                /* therefore must be denormalized.               */     \
2119
                fg_flag = 1;                                            \
2120
            }                                                           \
2121
        }                                                               \
2122
    }                                                                   \
2123
                                                                        \
2124
    env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
2125
}
2126

    
2127
VSX_TSQRT(xstsqrtdp, 1, float64, f64, -1022, 52)
2128
VSX_TSQRT(xvtsqrtdp, 2, float64, f64, -1022, 52)
2129
VSX_TSQRT(xvtsqrtsp, 4, float32, f32, -126, 23)
2130

    
2131
/* VSX_MADD - VSX floating point muliply/add variations
2132
 *   op    - instruction mnemonic
2133
 *   nels  - number of elements (1, 2 or 4)
2134
 *   tp    - type (float32 or float64)
2135
 *   fld   - vsr_t field (f32 or f64)
2136
 *   maddflgs - flags for the float*muladd routine that control the
2137
 *           various forms (madd, msub, nmadd, nmsub)
2138
 *   afrm  - A form (1=A, 0=M)
2139
 *   sfprf - set FPRF
2140
 */
2141
#define VSX_MADD(op, nels, tp, fld, maddflgs, afrm, sfprf, r2sp)              \
2142
void helper_##op(CPUPPCState *env, uint32_t opcode)                           \
2143
{                                                                             \
2144
    ppc_vsr_t xt_in, xa, xb, xt_out;                                          \
2145
    ppc_vsr_t *b, *c;                                                         \
2146
    int i;                                                                    \
2147
                                                                              \
2148
    if (afrm) { /* AxB + T */                                                 \
2149
        b = &xb;                                                              \
2150
        c = &xt_in;                                                           \
2151
    } else { /* AxT + B */                                                    \
2152
        b = &xt_in;                                                           \
2153
        c = &xb;                                                              \
2154
    }                                                                         \
2155
                                                                              \
2156
    getVSR(xA(opcode), &xa, env);                                             \
2157
    getVSR(xB(opcode), &xb, env);                                             \
2158
    getVSR(xT(opcode), &xt_in, env);                                          \
2159
                                                                              \
2160
    xt_out = xt_in;                                                           \
2161
                                                                              \
2162
    helper_reset_fpstatus(env);                                               \
2163
                                                                              \
2164
    for (i = 0; i < nels; i++) {                                              \
2165
        float_status tstat = env->fp_status;                                  \
2166
        set_float_exception_flags(0, &tstat);                                 \
2167
        if (r2sp && (tstat.float_rounding_mode == float_round_nearest_even)) {\
2168
            /* Avoid double rounding errors by rounding the intermediate */   \
2169
            /* result to odd.                                            */   \
2170
            set_float_rounding_mode(float_round_to_zero, &tstat);             \
2171
            xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i],      \
2172
                                       maddflgs, &tstat);                     \
2173
            xt_out.fld[i] |= (get_float_exception_flags(&tstat) &             \
2174
                              float_flag_inexact) != 0;                       \
2175
        } else {                                                              \
2176
            xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i],      \
2177
                                        maddflgs, &tstat);                    \
2178
        }                                                                     \
2179
        env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
2180
                                                                              \
2181
        if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
2182
            if (tp##_is_signaling_nan(xa.fld[i]) ||                           \
2183
                tp##_is_signaling_nan(b->fld[i]) ||                           \
2184
                tp##_is_signaling_nan(c->fld[i])) {                           \
2185
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
2186
                tstat.float_exception_flags &= ~float_flag_invalid;           \
2187
            }                                                                 \
2188
            if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(b->fld[i])) ||   \
2189
                (tp##_is_zero(xa.fld[i]) && tp##_is_infinity(b->fld[i]))) {   \
2190
                xt_out.fld[i] = float64_to_##tp(fload_invalid_op_excp(env,    \
2191
                    POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status);          \
2192
                tstat.float_exception_flags &= ~float_flag_invalid;           \
2193
            }                                                                 \
2194
            if ((tstat.float_exception_flags & float_flag_invalid) &&         \
2195
                ((tp##_is_infinity(xa.fld[i]) ||                              \
2196
                  tp##_is_infinity(b->fld[i])) &&                             \
2197
                  tp##_is_infinity(c->fld[i]))) {                             \
2198
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);     \
2199
            }                                                                 \
2200
        }                                                                     \
2201
                                                                              \
2202
        if (r2sp) {                                                           \
2203
            xt_out.fld[i] = helper_frsp(env, xt_out.fld[i]);                  \
2204
        }                                                                     \
2205
                                                                              \
2206
        if (sfprf) {                                                          \
2207
            helper_compute_fprf(env, xt_out.fld[i], sfprf);                   \
2208
        }                                                                     \
2209
    }                                                                         \
2210
    putVSR(xT(opcode), &xt_out, env);                                         \
2211
    helper_float_check_status(env);                                           \
2212
}
2213

    
2214
#define MADD_FLGS 0
2215
#define MSUB_FLGS float_muladd_negate_c
2216
#define NMADD_FLGS float_muladd_negate_result
2217
#define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result)
2218

    
2219
VSX_MADD(xsmaddadp, 1, float64, f64, MADD_FLGS, 1, 1, 0)
2220
VSX_MADD(xsmaddmdp, 1, float64, f64, MADD_FLGS, 0, 1, 0)
2221
VSX_MADD(xsmsubadp, 1, float64, f64, MSUB_FLGS, 1, 1, 0)
2222
VSX_MADD(xsmsubmdp, 1, float64, f64, MSUB_FLGS, 0, 1, 0)
2223
VSX_MADD(xsnmaddadp, 1, float64, f64, NMADD_FLGS, 1, 1, 0)
2224
VSX_MADD(xsnmaddmdp, 1, float64, f64, NMADD_FLGS, 0, 1, 0)
2225
VSX_MADD(xsnmsubadp, 1, float64, f64, NMSUB_FLGS, 1, 1, 0)
2226
VSX_MADD(xsnmsubmdp, 1, float64, f64, NMSUB_FLGS, 0, 1, 0)
2227

    
2228
VSX_MADD(xsmaddasp, 1, float64, f64, MADD_FLGS, 1, 1, 1)
2229
VSX_MADD(xsmaddmsp, 1, float64, f64, MADD_FLGS, 0, 1, 1)
2230
VSX_MADD(xsmsubasp, 1, float64, f64, MSUB_FLGS, 1, 1, 1)
2231
VSX_MADD(xsmsubmsp, 1, float64, f64, MSUB_FLGS, 0, 1, 1)
2232
VSX_MADD(xsnmaddasp, 1, float64, f64, NMADD_FLGS, 1, 1, 1)
2233
VSX_MADD(xsnmaddmsp, 1, float64, f64, NMADD_FLGS, 0, 1, 1)
2234
VSX_MADD(xsnmsubasp, 1, float64, f64, NMSUB_FLGS, 1, 1, 1)
2235
VSX_MADD(xsnmsubmsp, 1, float64, f64, NMSUB_FLGS, 0, 1, 1)
2236

    
2237
VSX_MADD(xvmaddadp, 2, float64, f64, MADD_FLGS, 1, 0, 0)
2238
VSX_MADD(xvmaddmdp, 2, float64, f64, MADD_FLGS, 0, 0, 0)
2239
VSX_MADD(xvmsubadp, 2, float64, f64, MSUB_FLGS, 1, 0, 0)
2240
VSX_MADD(xvmsubmdp, 2, float64, f64, MSUB_FLGS, 0, 0, 0)
2241
VSX_MADD(xvnmaddadp, 2, float64, f64, NMADD_FLGS, 1, 0, 0)
2242
VSX_MADD(xvnmaddmdp, 2, float64, f64, NMADD_FLGS, 0, 0, 0)
2243
VSX_MADD(xvnmsubadp, 2, float64, f64, NMSUB_FLGS, 1, 0, 0)
2244
VSX_MADD(xvnmsubmdp, 2, float64, f64, NMSUB_FLGS, 0, 0, 0)
2245

    
2246
VSX_MADD(xvmaddasp, 4, float32, f32, MADD_FLGS, 1, 0, 0)
2247
VSX_MADD(xvmaddmsp, 4, float32, f32, MADD_FLGS, 0, 0, 0)
2248
VSX_MADD(xvmsubasp, 4, float32, f32, MSUB_FLGS, 1, 0, 0)
2249
VSX_MADD(xvmsubmsp, 4, float32, f32, MSUB_FLGS, 0, 0, 0)
2250
VSX_MADD(xvnmaddasp, 4, float32, f32, NMADD_FLGS, 1, 0, 0)
2251
VSX_MADD(xvnmaddmsp, 4, float32, f32, NMADD_FLGS, 0, 0, 0)
2252
VSX_MADD(xvnmsubasp, 4, float32, f32, NMSUB_FLGS, 1, 0, 0)
2253
VSX_MADD(xvnmsubmsp, 4, float32, f32, NMSUB_FLGS, 0, 0, 0)
2254

    
2255
#define VSX_SCALAR_CMP(op, ordered)                                      \
2256
void helper_##op(CPUPPCState *env, uint32_t opcode)                      \
2257
{                                                                        \
2258
    ppc_vsr_t xa, xb;                                                    \
2259
    uint32_t cc = 0;                                                     \
2260
                                                                         \
2261
    getVSR(xA(opcode), &xa, env);                                        \
2262
    getVSR(xB(opcode), &xb, env);                                        \
2263
                                                                         \
2264
    if (unlikely(float64_is_any_nan(xa.f64[0]) ||                        \
2265
                 float64_is_any_nan(xb.f64[0]))) {                       \
2266
        if (float64_is_signaling_nan(xa.f64[0]) ||                       \
2267
            float64_is_signaling_nan(xb.f64[0])) {                       \
2268
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
2269
        }                                                                \
2270
        if (ordered) {                                                   \
2271
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);         \
2272
        }                                                                \
2273
        cc = 1;                                                          \
2274
    } else {                                                             \
2275
        if (float64_lt(xa.f64[0], xb.f64[0], &env->fp_status)) {         \
2276
            cc = 8;                                                      \
2277
        } else if (!float64_le(xa.f64[0], xb.f64[0], &env->fp_status)) { \
2278
            cc = 4;                                                      \
2279
        } else {                                                         \
2280
            cc = 2;                                                      \
2281
        }                                                                \
2282
    }                                                                    \
2283
                                                                         \
2284
    env->fpscr &= ~(0x0F << FPSCR_FPRF);                                 \
2285
    env->fpscr |= cc << FPSCR_FPRF;                                      \
2286
    env->crf[BF(opcode)] = cc;                                           \
2287
                                                                         \
2288
    helper_float_check_status(env);                                      \
2289
}
2290

    
2291
VSX_SCALAR_CMP(xscmpodp, 1)
2292
VSX_SCALAR_CMP(xscmpudp, 0)
2293

    
2294
#define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ul)
2295
#define float32_snan_to_qnan(x) ((x) | 0x00400000)
2296

    
2297
/* VSX_MAX_MIN - VSX floating point maximum/minimum
2298
 *   name  - instruction mnemonic
2299
 *   op    - operation (max or min)
2300
 *   nels  - number of elements (1, 2 or 4)
2301
 *   tp    - type (float32 or float64)
2302
 *   fld   - vsr_t field (f32 or f64)
2303
 */
2304
#define VSX_MAX_MIN(name, op, nels, tp, fld)                                  \
2305
void helper_##name(CPUPPCState *env, uint32_t opcode)                         \
2306
{                                                                             \
2307
    ppc_vsr_t xt, xa, xb;                                                     \
2308
    int i;                                                                    \
2309
                                                                              \
2310
    getVSR(xA(opcode), &xa, env);                                             \
2311
    getVSR(xB(opcode), &xb, env);                                             \
2312
    getVSR(xT(opcode), &xt, env);                                             \
2313
                                                                              \
2314
    for (i = 0; i < nels; i++) {                                              \
2315
        xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &env->fp_status);         \
2316
        if (unlikely(tp##_is_signaling_nan(xa.fld[i]) ||                      \
2317
                     tp##_is_signaling_nan(xb.fld[i]))) {                     \
2318
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
2319
        }                                                                     \
2320
    }                                                                         \
2321
                                                                              \
2322
    putVSR(xT(opcode), &xt, env);                                             \
2323
    helper_float_check_status(env);                                           \
2324
}
2325

    
2326
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, f64)
2327
VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, f64)
2328
VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, f32)
2329
VSX_MAX_MIN(xsmindp, minnum, 1, float64, f64)
2330
VSX_MAX_MIN(xvmindp, minnum, 2, float64, f64)
2331
VSX_MAX_MIN(xvminsp, minnum, 4, float32, f32)
2332

    
2333
/* VSX_CMP - VSX floating point compare
2334
 *   op    - instruction mnemonic
2335
 *   nels  - number of elements (1, 2 or 4)
2336
 *   tp    - type (float32 or float64)
2337
 *   fld   - vsr_t field (f32 or f64)
2338
 *   cmp   - comparison operation
2339
 *   svxvc - set VXVC bit
2340
 */
2341
#define VSX_CMP(op, nels, tp, fld, cmp, svxvc)                            \
2342
void helper_##op(CPUPPCState *env, uint32_t opcode)                       \
2343
{                                                                         \
2344
    ppc_vsr_t xt, xa, xb;                                                 \
2345
    int i;                                                                \
2346
    int all_true = 1;                                                     \
2347
    int all_false = 1;                                                    \
2348
                                                                          \
2349
    getVSR(xA(opcode), &xa, env);                                         \
2350
    getVSR(xB(opcode), &xb, env);                                         \
2351
    getVSR(xT(opcode), &xt, env);                                         \
2352
                                                                          \
2353
    for (i = 0; i < nels; i++) {                                          \
2354
        if (unlikely(tp##_is_any_nan(xa.fld[i]) ||                        \
2355
                     tp##_is_any_nan(xb.fld[i]))) {                       \
2356
            if (tp##_is_signaling_nan(xa.fld[i]) ||                       \
2357
                tp##_is_signaling_nan(xb.fld[i])) {                       \
2358
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);    \
2359
            }                                                             \
2360
            if (svxvc) {                                                  \
2361
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0);      \
2362
            }                                                             \
2363
            xt.fld[i] = 0;                                                \
2364
            all_true = 0;                                                 \
2365
        } else {                                                          \
2366
            if (tp##_##cmp(xb.fld[i], xa.fld[i], &env->fp_status) == 1) { \
2367
                xt.fld[i] = -1;                                           \
2368
                all_false = 0;                                            \
2369
            } else {                                                      \
2370
                xt.fld[i] = 0;                                            \
2371
                all_true = 0;                                             \
2372
            }                                                             \
2373
        }                                                                 \
2374
    }                                                                     \
2375
                                                                          \
2376
    putVSR(xT(opcode), &xt, env);                                         \
2377
    if ((opcode >> (31-21)) & 1) {                                        \
2378
        env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0);       \
2379
    }                                                                     \
2380
    helper_float_check_status(env);                                       \
2381
 }
2382

    
2383
VSX_CMP(xvcmpeqdp, 2, float64, f64, eq, 0)
2384
VSX_CMP(xvcmpgedp, 2, float64, f64, le, 1)
2385
VSX_CMP(xvcmpgtdp, 2, float64, f64, lt, 1)
2386
VSX_CMP(xvcmpeqsp, 4, float32, f32, eq, 0)
2387
VSX_CMP(xvcmpgesp, 4, float32, f32, le, 1)
2388
VSX_CMP(xvcmpgtsp, 4, float32, f32, lt, 1)
2389

    
2390
#if defined(HOST_WORDS_BIGENDIAN)
2391
#define JOFFSET 0
2392
#else
2393
#define JOFFSET 1
2394
#endif
2395

    
2396
/* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
2397
 *   op    - instruction mnemonic
2398
 *   nels  - number of elements (1, 2 or 4)
2399
 *   stp   - source type (float32 or float64)
2400
 *   ttp   - target type (float32 or float64)
2401
 *   sfld  - source vsr_t field
2402
 *   tfld  - target vsr_t field (f32 or f64)
2403
 *   sfprf - set FPRF
2404
 */
2405
#define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf)    \
2406
void helper_##op(CPUPPCState *env, uint32_t opcode)                \
2407
{                                                                  \
2408
    ppc_vsr_t xt, xb;                                              \
2409
    int i;                                                         \
2410
                                                                   \
2411
    getVSR(xB(opcode), &xb, env);                                  \
2412
    getVSR(xT(opcode), &xt, env);                                  \
2413
                                                                   \
2414
    for (i = 0; i < nels; i++) {                                   \
2415
        int j = 2*i + JOFFSET;                                     \
2416
        xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);        \
2417
        if (unlikely(stp##_is_signaling_nan(xb.sfld))) {           \
2418
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2419
            xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
2420
        }                                                          \
2421
        if (sfprf) {                                               \
2422
            helper_compute_fprf(env, ttp##_to_float64(xt.tfld,     \
2423
                                &env->fp_status), sfprf);          \
2424
        }                                                          \
2425
    }                                                              \
2426
                                                                   \
2427
    putVSR(xT(opcode), &xt, env);                                  \
2428
    helper_float_check_status(env);                                \
2429
}
2430

    
2431
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, f64[i], f32[j], 1)
2432
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, f32[j], f64[i], 1)
2433
VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, f64[i], f32[j], 0)
2434
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, f32[j], f64[i], 0)
2435

    
2436
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
2437
{
2438
    float_status tstat = env->fp_status;
2439
    set_float_exception_flags(0, &tstat);
2440

    
2441
    return (uint64_t)float64_to_float32(xb, &tstat) << 32;
2442
}
2443

    
2444
uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
2445
{
2446
    float_status tstat = env->fp_status;
2447
    set_float_exception_flags(0, &tstat);
2448

    
2449
    return float32_to_float64(xb >> 32, &tstat);
2450
}
2451

    
2452
/* VSX_CVT_FP_TO_INT - VSX floating point to integer conversion
2453
 *   op    - instruction mnemonic
2454
 *   nels  - number of elements (1, 2 or 4)
2455
 *   stp   - source type (float32 or float64)
2456
 *   ttp   - target type (int32, uint32, int64 or uint64)
2457
 *   sfld  - source vsr_t field
2458
 *   tfld  - target vsr_t field
2459
 *   jdef  - definition of the j index (i or 2*i)
2460
 *   rnan  - resulting NaN
2461
 */
2462
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, jdef, rnan)        \
2463
void helper_##op(CPUPPCState *env, uint32_t opcode)                          \
2464
{                                                                            \
2465
    ppc_vsr_t xt, xb;                                                        \
2466
    int i;                                                                   \
2467
                                                                             \
2468
    getVSR(xB(opcode), &xb, env);                                            \
2469
    getVSR(xT(opcode), &xt, env);                                            \
2470
                                                                             \
2471
    for (i = 0; i < nels; i++) {                                             \
2472
        int j = jdef;                                                        \
2473
        if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
2474
            if (stp##_is_signaling_nan(xb.sfld)) {                           \
2475
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
2476
            }                                                                \
2477
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
2478
            xt.tfld = rnan;                                                  \
2479
        } else {                                                             \
2480
            xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);              \
2481
            if (env->fp_status.float_exception_flags & float_flag_invalid) { \
2482
                fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);        \
2483
            }                                                                \
2484
        }                                                                    \
2485
    }                                                                        \
2486
                                                                             \
2487
    putVSR(xT(opcode), &xt, env);                                            \
2488
    helper_float_check_status(env);                                          \
2489
}
2490

    
2491
VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, f64[j], u64[i], i, \
2492
                  0x8000000000000000ul)
2493
VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, f64[i], u32[j], \
2494
                  2*i + JOFFSET, 0x80000000l)
2495
VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, f64[j], u64[i], i, 0ul)
2496
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, f64[i], u32[j], \
2497
                  2*i + JOFFSET, 0)
2498
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, f64[j], u64[i], i, \
2499
                  0x8000000000000000ul)
2500
VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, f64[i], u32[j], \
2501
                  2*i + JOFFSET, 0x80000000l)
2502
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, f64[j], u64[i], i, 0ul)
2503
VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, f64[i], u32[j], \
2504
                  2*i + JOFFSET, 0)
2505
VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, f32[j], u64[i], \
2506
                  2*i + JOFFSET, 0x8000000000000000ul)
2507
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, f32[j], u32[j], i, \
2508
                  0x80000000l)
2509
VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, f32[j], u64[i], \
2510
                  2*i + JOFFSET, 0ul)
2511
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0)
2512

    
2513
/* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
2514
 *   op    - instruction mnemonic
2515
 *   nels  - number of elements (1, 2 or 4)
2516
 *   stp   - source type (int32, uint32, int64 or uint64)
2517
 *   ttp   - target type (float32 or float64)
2518
 *   sfld  - source vsr_t field
2519
 *   tfld  - target vsr_t field
2520
 *   jdef  - definition of the j index (i or 2*i)
2521
 *   sfprf - set FPRF
2522
 */
2523
#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, jdef, sfprf, r2sp) \
2524
void helper_##op(CPUPPCState *env, uint32_t opcode)                     \
2525
{                                                                       \
2526
    ppc_vsr_t xt, xb;                                                   \
2527
    int i;                                                              \
2528
                                                                        \
2529
    getVSR(xB(opcode), &xb, env);                                       \
2530
    getVSR(xT(opcode), &xt, env);                                       \
2531
                                                                        \
2532
    for (i = 0; i < nels; i++) {                                        \
2533
        int j = jdef;                                                   \
2534
        xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);             \
2535
        if (r2sp) {                                                     \
2536
            xt.tfld = helper_frsp(env, xt.tfld);                        \
2537
        }                                                               \
2538
        if (sfprf) {                                                    \
2539
            helper_compute_fprf(env, xt.tfld, sfprf);                   \
2540
        }                                                               \
2541
    }                                                                   \
2542
                                                                        \
2543
    putVSR(xT(opcode), &xt, env);                                       \
2544
    helper_float_check_status(env);                                     \
2545
}
2546

    
2547
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, u64[j], f64[i], i, 1, 0)
2548
VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, u64[j], f64[i], i, 1, 0)
2549
VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, u64[j], f64[i], i, 1, 1)
2550
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, u64[j], f64[i], i, 1, 1)
2551
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, u64[j], f64[i], i, 0, 0)
2552
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, u64[j], f64[i], i, 0, 0)
2553
VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, u32[j], f64[i], \
2554
                  2*i + JOFFSET, 0, 0)
2555
VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, u32[j], f64[i], \
2556
                  2*i + JOFFSET, 0, 0)
2557
VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, u64[i], f32[j], \
2558
                  2*i + JOFFSET, 0, 0)
2559
VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, u64[i], f32[j], \
2560
                  2*i + JOFFSET, 0, 0)
2561
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, u32[j], f32[i], i, 0, 0)
2562
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0, 0)
2563

    
2564
/* For "use current rounding mode", define a value that will not be one of
2565
 * the existing rounding model enums.
2566
 */
2567
#define FLOAT_ROUND_CURRENT (float_round_nearest_even + float_round_down + \
2568
  float_round_up + float_round_to_zero)
2569

    
2570
/* VSX_ROUND - VSX floating point round
2571
 *   op    - instruction mnemonic
2572
 *   nels  - number of elements (1, 2 or 4)
2573
 *   tp    - type (float32 or float64)
2574
 *   fld   - vsr_t field (f32 or f64)
2575
 *   rmode - rounding mode
2576
 *   sfprf - set FPRF
2577
 */
2578
#define VSX_ROUND(op, nels, tp, fld, rmode, sfprf)                     \
2579
void helper_##op(CPUPPCState *env, uint32_t opcode)                    \
2580
{                                                                      \
2581
    ppc_vsr_t xt, xb;                                                  \
2582
    int i;                                                             \
2583
    getVSR(xB(opcode), &xb, env);                                      \
2584
    getVSR(xT(opcode), &xt, env);                                      \
2585
                                                                       \
2586
    if (rmode != FLOAT_ROUND_CURRENT) {                                \
2587
        set_float_rounding_mode(rmode, &env->fp_status);               \
2588
    }                                                                  \
2589
                                                                       \
2590
    for (i = 0; i < nels; i++) {                                       \
2591
        if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) {              \
2592
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);     \
2593
            xt.fld[i] = tp##_snan_to_qnan(xb.fld[i]);                  \
2594
        } else {                                                       \
2595
            xt.fld[i] = tp##_round_to_int(xb.fld[i], &env->fp_status); \
2596
        }                                                              \
2597
        if (sfprf) {                                                   \
2598
            helper_compute_fprf(env, xt.fld[i], sfprf);                \
2599
        }                                                              \
2600
    }                                                                  \
2601
                                                                       \
2602
    /* If this is not a "use current rounding mode" instruction,       \
2603
     * then inhibit setting of the XX bit and restore rounding         \
2604
     * mode from FPSCR */                                              \
2605
    if (rmode != FLOAT_ROUND_CURRENT) {                                \
2606
        fpscr_set_rounding_mode(env);                                  \
2607
        env->fp_status.float_exception_flags &= ~float_flag_inexact;   \
2608
    }                                                                  \
2609
                                                                       \
2610
    putVSR(xT(opcode), &xt, env);                                      \
2611
    helper_float_check_status(env);                                    \
2612
}
2613

    
2614
VSX_ROUND(xsrdpi, 1, float64, f64, float_round_nearest_even, 1)
2615
VSX_ROUND(xsrdpic, 1, float64, f64, FLOAT_ROUND_CURRENT, 1)
2616
VSX_ROUND(xsrdpim, 1, float64, f64, float_round_down, 1)
2617
VSX_ROUND(xsrdpip, 1, float64, f64, float_round_up, 1)
2618
VSX_ROUND(xsrdpiz, 1, float64, f64, float_round_to_zero, 1)
2619

    
2620
VSX_ROUND(xvrdpi, 2, float64, f64, float_round_nearest_even, 0)
2621
VSX_ROUND(xvrdpic, 2, float64, f64, FLOAT_ROUND_CURRENT, 0)
2622
VSX_ROUND(xvrdpim, 2, float64, f64, float_round_down, 0)
2623
VSX_ROUND(xvrdpip, 2, float64, f64, float_round_up, 0)
2624
VSX_ROUND(xvrdpiz, 2, float64, f64, float_round_to_zero, 0)
2625

    
2626
VSX_ROUND(xvrspi, 4, float32, f32, float_round_nearest_even, 0)
2627
VSX_ROUND(xvrspic, 4, float32, f32, FLOAT_ROUND_CURRENT, 0)
2628
VSX_ROUND(xvrspim, 4, float32, f32, float_round_down, 0)
2629
VSX_ROUND(xvrspip, 4, float32, f32, float_round_up, 0)
2630
VSX_ROUND(xvrspiz, 4, float32, f32, float_round_to_zero, 0)
2631

    
2632
uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
2633
{
2634
    helper_reset_fpstatus(env);
2635

    
2636
    uint64_t xt = helper_frsp(env, xb);
2637

    
2638
    helper_compute_fprf(env, xt, 1);
2639
    helper_float_check_status(env);
2640
    return xt;
2641
}