Statistics
| Branch: | Revision:

root / target-ppc / fpu_helper.c @ 7d08d856

History | View | Annotate | Download (48.5 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
{
111
    uint64_t ret = 0;
112
    int ve;
113

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

    
192
static inline void float_zero_divide_excp(CPUPPCState *env)
193
{
194
    env->fpscr |= 1 << FPSCR_ZX;
195
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
196
    /* Update the floating-point exception summary */
197
    env->fpscr |= 1 << FPSCR_FX;
198
    if (fpscr_ze != 0) {
199
        /* Update the floating-point enabled exception summary */
200
        env->fpscr |= 1 << FPSCR_FEX;
201
        if (msr_fe0 != 0 || msr_fe1 != 0) {
202
            helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
203
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
204
        }
205
    }
206
}
207

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

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

    
241
static inline void float_inexact_excp(CPUPPCState *env)
242
{
243
    env->fpscr |= 1 << FPSCR_XX;
244
    /* Update the floating-point exception summary */
245
    env->fpscr |= 1 << FPSCR_FX;
246
    if (fpscr_xe != 0) {
247
        /* Update the floating-point enabled exception summary */
248
        env->fpscr |= 1 << FPSCR_FEX;
249
        /* We must update the target FPR before raising the exception */
250
        env->exception_index = POWERPC_EXCP_PROGRAM;
251
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
252
    }
253
}
254

    
255
static inline void fpscr_set_rounding_mode(CPUPPCState *env)
256
{
257
    int rnd_type;
258

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

    
282
void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
283
{
284
    int prev;
285

    
286
    prev = (env->fpscr >> bit) & 1;
287
    env->fpscr &= ~(1 << bit);
288
    if (prev == 1) {
289
        switch (bit) {
290
        case FPSCR_RN1:
291
        case FPSCR_RN:
292
            fpscr_set_rounding_mode(env);
293
            break;
294
        default:
295
            break;
296
        }
297
    }
298
}
299

    
300
void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
301
{
302
    int prev;
303

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

    
431
void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
432
{
433
    target_ulong prev, new;
434
    int i;
435

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

    
463
void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
464
{
465
    helper_store_fpscr(env, arg, mask);
466
}
467

    
468
void helper_float_check_status(CPUPPCState *env)
469
{
470
    int status = get_float_exception_flags(&env->fp_status);
471

    
472
    if (status & float_flag_divbyzero) {
473
        float_zero_divide_excp(env);
474
    } else if (status & float_flag_overflow) {
475
        float_overflow_excp(env);
476
    } else if (status & float_flag_underflow) {
477
        float_underflow_excp(env);
478
    } else if (status & float_flag_inexact) {
479
        float_inexact_excp(env);
480
    }
481

    
482
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
483
        (env->error_code & POWERPC_EXCP_FP)) {
484
        /* Differred floating-point exception after target FPR update */
485
        if (msr_fe0 != 0 || msr_fe1 != 0) {
486
            helper_raise_exception_err(env, env->exception_index,
487
                                       env->error_code);
488
        }
489
    }
490
}
491

    
492
void helper_reset_fpstatus(CPUPPCState *env)
493
{
494
    set_float_exception_flags(0, &env->fp_status);
495
}
496

    
497
/* fadd - fadd. */
498
uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
499
{
500
    CPU_DoubleU farg1, farg2;
501

    
502
    farg1.ll = arg1;
503
    farg2.ll = arg2;
504

    
505
    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
506
                 float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
507
        /* Magnitude subtraction of infinities */
508
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
509
    } else {
510
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
511
                     float64_is_signaling_nan(farg2.d))) {
512
            /* sNaN addition */
513
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
514
        }
515
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
516
    }
517

    
518
    return farg1.ll;
519
}
520

    
521
/* fsub - fsub. */
522
uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
523
{
524
    CPU_DoubleU farg1, farg2;
525

    
526
    farg1.ll = arg1;
527
    farg2.ll = arg2;
528

    
529
    if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
530
                 float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
531
        /* Magnitude subtraction of infinities */
532
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
533
    } else {
534
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
535
                     float64_is_signaling_nan(farg2.d))) {
536
            /* sNaN subtraction */
537
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
538
        }
539
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
540
    }
541

    
542
    return farg1.ll;
543
}
544

    
545
/* fmul - fmul. */
546
uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
547
{
548
    CPU_DoubleU farg1, farg2;
549

    
550
    farg1.ll = arg1;
551
    farg2.ll = arg2;
552

    
553
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
554
                 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
555
        /* Multiplication of zero by infinity */
556
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
557
    } else {
558
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
559
                     float64_is_signaling_nan(farg2.d))) {
560
            /* sNaN multiplication */
561
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
562
        }
563
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
564
    }
565

    
566
    return farg1.ll;
567
}
568

    
569
/* fdiv - fdiv. */
570
uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
571
{
572
    CPU_DoubleU farg1, farg2;
573

    
574
    farg1.ll = arg1;
575
    farg2.ll = arg2;
576

    
577
    if (unlikely(float64_is_infinity(farg1.d) &&
578
                 float64_is_infinity(farg2.d))) {
579
        /* Division of infinity by infinity */
580
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI);
581
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
582
        /* Division of zero by zero */
583
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ);
584
    } else {
585
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
586
                     float64_is_signaling_nan(farg2.d))) {
587
            /* sNaN division */
588
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
589
        }
590
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
591
    }
592

    
593
    return farg1.ll;
594
}
595

    
596
/* fctiw - fctiw. */
597
uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
598
{
599
    CPU_DoubleU farg;
600

    
601
    farg.ll = arg;
602

    
603
    if (unlikely(float64_is_signaling_nan(farg.d))) {
604
        /* sNaN conversion */
605
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
606
                                        POWERPC_EXCP_FP_VXCVI);
607
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
608
                        float64_is_infinity(farg.d))) {
609
        /* qNan / infinity conversion */
610
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
611
    } else {
612
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
613
        /* XXX: higher bits are not supposed to be significant.
614
         *     to make tests easier, return the same as a real PowerPC 750
615
         */
616
        farg.ll |= 0xFFF80000ULL << 32;
617
    }
618
    return farg.ll;
619
}
620

    
621
/* fctiwz - fctiwz. */
622
uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg)
623
{
624
    CPU_DoubleU farg;
625

    
626
    farg.ll = arg;
627

    
628
    if (unlikely(float64_is_signaling_nan(farg.d))) {
629
        /* sNaN conversion */
630
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
631
                                        POWERPC_EXCP_FP_VXCVI);
632
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
633
                        float64_is_infinity(farg.d))) {
634
        /* qNan / infinity conversion */
635
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
636
    } else {
637
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
638
        /* XXX: higher bits are not supposed to be significant.
639
         *     to make tests easier, return the same as a real PowerPC 750
640
         */
641
        farg.ll |= 0xFFF80000ULL << 32;
642
    }
643
    return farg.ll;
644
}
645

    
646
#if defined(TARGET_PPC64)
647
/* fcfid - fcfid. */
648
uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
649
{
650
    CPU_DoubleU farg;
651

    
652
    farg.d = int64_to_float64(arg, &env->fp_status);
653
    return farg.ll;
654
}
655

    
656
/* fctid - fctid. */
657
uint64_t helper_fctid(CPUPPCState *env, uint64_t arg)
658
{
659
    CPU_DoubleU farg;
660

    
661
    farg.ll = arg;
662

    
663
    if (unlikely(float64_is_signaling_nan(farg.d))) {
664
        /* sNaN conversion */
665
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
666
                                        POWERPC_EXCP_FP_VXCVI);
667
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
668
                        float64_is_infinity(farg.d))) {
669
        /* qNan / infinity conversion */
670
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
671
    } else {
672
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
673
    }
674
    return farg.ll;
675
}
676

    
677
/* fctidz - fctidz. */
678
uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg)
679
{
680
    CPU_DoubleU farg;
681

    
682
    farg.ll = arg;
683

    
684
    if (unlikely(float64_is_signaling_nan(farg.d))) {
685
        /* sNaN conversion */
686
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
687
                                        POWERPC_EXCP_FP_VXCVI);
688
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
689
                        float64_is_infinity(farg.d))) {
690
        /* qNan / infinity conversion */
691
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
692
    } else {
693
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
694
    }
695
    return farg.ll;
696
}
697

    
698
#endif
699

    
700
static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
701
                              int rounding_mode)
702
{
703
    CPU_DoubleU farg;
704

    
705
    farg.ll = arg;
706

    
707
    if (unlikely(float64_is_signaling_nan(farg.d))) {
708
        /* sNaN round */
709
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
710
                                        POWERPC_EXCP_FP_VXCVI);
711
    } else if (unlikely(float64_is_quiet_nan(farg.d) ||
712
                        float64_is_infinity(farg.d))) {
713
        /* qNan / infinity round */
714
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI);
715
    } else {
716
        set_float_rounding_mode(rounding_mode, &env->fp_status);
717
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
718
        /* Restore rounding mode from FPSCR */
719
        fpscr_set_rounding_mode(env);
720
    }
721
    return farg.ll;
722
}
723

    
724
uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
725
{
726
    return do_fri(env, arg, float_round_nearest_even);
727
}
728

    
729
uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
730
{
731
    return do_fri(env, arg, float_round_to_zero);
732
}
733

    
734
uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
735
{
736
    return do_fri(env, arg, float_round_up);
737
}
738

    
739
uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
740
{
741
    return do_fri(env, arg, float_round_down);
742
}
743

    
744
/* fmadd - fmadd. */
745
uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
746
                      uint64_t arg3)
747
{
748
    CPU_DoubleU farg1, farg2, farg3;
749

    
750
    farg1.ll = arg1;
751
    farg2.ll = arg2;
752
    farg3.ll = arg3;
753

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

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

    
783
    return farg1.ll;
784
}
785

    
786
/* fmsub - fmsub. */
787
uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
788
                      uint64_t arg3)
789
{
790
    CPU_DoubleU farg1, farg2, farg3;
791

    
792
    farg1.ll = arg1;
793
    farg2.ll = arg2;
794
    farg3.ll = arg3;
795

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

    
811
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
812
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
813
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
814
        if (unlikely(float128_is_infinity(ft0_128) &&
815
                     float64_is_infinity(farg3.d) &&
816
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
817
            /* Magnitude subtraction of infinities */
818
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
819
        } else {
820
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
821
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
822
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
823
        }
824
    }
825
    return farg1.ll;
826
}
827

    
828
/* fnmadd - fnmadd. */
829
uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
830
                       uint64_t arg3)
831
{
832
    CPU_DoubleU farg1, farg2, farg3;
833

    
834
    farg1.ll = arg1;
835
    farg2.ll = arg2;
836
    farg3.ll = arg3;
837

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

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

    
872
/* fnmsub - fnmsub. */
873
uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
874
                       uint64_t arg3)
875
{
876
    CPU_DoubleU farg1, farg2, farg3;
877

    
878
    farg1.ll = arg1;
879
    farg2.ll = arg2;
880
    farg3.ll = arg3;
881

    
882
    if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
883
                 (float64_is_zero(farg1.d) &&
884
                  float64_is_infinity(farg2.d)))) {
885
        /* Multiplication of zero by infinity */
886
        farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ);
887
    } else {
888
        if (unlikely(float64_is_signaling_nan(farg1.d) ||
889
                     float64_is_signaling_nan(farg2.d) ||
890
                     float64_is_signaling_nan(farg3.d))) {
891
            /* sNaN operation */
892
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
893
        }
894
        /* This is the way the PowerPC specification defines it */
895
        float128 ft0_128, ft1_128;
896

    
897
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
898
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
899
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
900
        if (unlikely(float128_is_infinity(ft0_128) &&
901
                     float64_is_infinity(farg3.d) &&
902
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
903
            /* Magnitude subtraction of infinities */
904
            farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI);
905
        } else {
906
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
907
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
908
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
909
        }
910
        if (likely(!float64_is_any_nan(farg1.d))) {
911
            farg1.d = float64_chs(farg1.d);
912
        }
913
    }
914
    return farg1.ll;
915
}
916

    
917
/* frsp - frsp. */
918
uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
919
{
920
    CPU_DoubleU farg;
921
    float32 f32;
922

    
923
    farg.ll = arg;
924

    
925
    if (unlikely(float64_is_signaling_nan(farg.d))) {
926
        /* sNaN square root */
927
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
928
    }
929
    f32 = float64_to_float32(farg.d, &env->fp_status);
930
    farg.d = float32_to_float64(f32, &env->fp_status);
931

    
932
    return farg.ll;
933
}
934

    
935
/* fsqrt - fsqrt. */
936
uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
937
{
938
    CPU_DoubleU farg;
939

    
940
    farg.ll = arg;
941

    
942
    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
943
        /* Square root of a negative nonzero number */
944
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT);
945
    } else {
946
        if (unlikely(float64_is_signaling_nan(farg.d))) {
947
            /* sNaN square root */
948
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
949
        }
950
        farg.d = float64_sqrt(farg.d, &env->fp_status);
951
    }
952
    return farg.ll;
953
}
954

    
955
/* fre - fre. */
956
uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
957
{
958
    CPU_DoubleU farg;
959

    
960
    farg.ll = arg;
961

    
962
    if (unlikely(float64_is_signaling_nan(farg.d))) {
963
        /* sNaN reciprocal */
964
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
965
    }
966
    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
967
    return farg.d;
968
}
969

    
970
/* fres - fres. */
971
uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
972
{
973
    CPU_DoubleU farg;
974
    float32 f32;
975

    
976
    farg.ll = arg;
977

    
978
    if (unlikely(float64_is_signaling_nan(farg.d))) {
979
        /* sNaN reciprocal */
980
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
981
    }
982
    farg.d = float64_div(float64_one, farg.d, &env->fp_status);
983
    f32 = float64_to_float32(farg.d, &env->fp_status);
984
    farg.d = float32_to_float64(f32, &env->fp_status);
985

    
986
    return farg.ll;
987
}
988

    
989
/* frsqrte  - frsqrte. */
990
uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
991
{
992
    CPU_DoubleU farg;
993
    float32 f32;
994

    
995
    farg.ll = arg;
996

    
997
    if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
998
        /* Reciprocal square root of a negative nonzero number */
999
        farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT);
1000
    } else {
1001
        if (unlikely(float64_is_signaling_nan(farg.d))) {
1002
            /* sNaN reciprocal square root */
1003
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
1004
        }
1005
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1006
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1007
        f32 = float64_to_float32(farg.d, &env->fp_status);
1008
        farg.d = float32_to_float64(f32, &env->fp_status);
1009
    }
1010
    return farg.ll;
1011
}
1012

    
1013
/* fsel - fsel. */
1014
uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1015
                     uint64_t arg3)
1016
{
1017
    CPU_DoubleU farg1;
1018

    
1019
    farg1.ll = arg1;
1020

    
1021
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
1022
        !float64_is_any_nan(farg1.d)) {
1023
        return arg2;
1024
    } else {
1025
        return arg3;
1026
    }
1027
}
1028

    
1029
void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1030
                  uint32_t crfD)
1031
{
1032
    CPU_DoubleU farg1, farg2;
1033
    uint32_t ret = 0;
1034

    
1035
    farg1.ll = arg1;
1036
    farg2.ll = arg2;
1037

    
1038
    if (unlikely(float64_is_any_nan(farg1.d) ||
1039
                 float64_is_any_nan(farg2.d))) {
1040
        ret = 0x01UL;
1041
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1042
        ret = 0x08UL;
1043
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1044
        ret = 0x04UL;
1045
    } else {
1046
        ret = 0x02UL;
1047
    }
1048

    
1049
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1050
    env->fpscr |= ret << FPSCR_FPRF;
1051
    env->crf[crfD] = ret;
1052
    if (unlikely(ret == 0x01UL
1053
                 && (float64_is_signaling_nan(farg1.d) ||
1054
                     float64_is_signaling_nan(farg2.d)))) {
1055
        /* sNaN comparison */
1056
        fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN);
1057
    }
1058
}
1059

    
1060
void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1061
                  uint32_t crfD)
1062
{
1063
    CPU_DoubleU farg1, farg2;
1064
    uint32_t ret = 0;
1065

    
1066
    farg1.ll = arg1;
1067
    farg2.ll = arg2;
1068

    
1069
    if (unlikely(float64_is_any_nan(farg1.d) ||
1070
                 float64_is_any_nan(farg2.d))) {
1071
        ret = 0x01UL;
1072
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1073
        ret = 0x08UL;
1074
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1075
        ret = 0x04UL;
1076
    } else {
1077
        ret = 0x02UL;
1078
    }
1079

    
1080
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1081
    env->fpscr |= ret << FPSCR_FPRF;
1082
    env->crf[crfD] = ret;
1083
    if (unlikely(ret == 0x01UL)) {
1084
        if (float64_is_signaling_nan(farg1.d) ||
1085
            float64_is_signaling_nan(farg2.d)) {
1086
            /* sNaN comparison */
1087
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
1088
                                  POWERPC_EXCP_FP_VXVC);
1089
        } else {
1090
            /* qNaN comparison */
1091
            fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC);
1092
        }
1093
    }
1094
}
1095

    
1096
/* Single-precision floating-point conversions */
1097
static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val)
1098
{
1099
    CPU_FloatU u;
1100

    
1101
    u.f = int32_to_float32(val, &env->vec_status);
1102

    
1103
    return u.l;
1104
}
1105

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

    
1110
    u.f = uint32_to_float32(val, &env->vec_status);
1111

    
1112
    return u.l;
1113
}
1114

    
1115
static inline int32_t efsctsi(CPUPPCState *env, uint32_t val)
1116
{
1117
    CPU_FloatU u;
1118

    
1119
    u.l = val;
1120
    /* NaN are not treated the same way IEEE 754 does */
1121
    if (unlikely(float32_is_quiet_nan(u.f))) {
1122
        return 0;
1123
    }
1124

    
1125
    return float32_to_int32(u.f, &env->vec_status);
1126
}
1127

    
1128
static inline uint32_t efsctui(CPUPPCState *env, uint32_t val)
1129
{
1130
    CPU_FloatU u;
1131

    
1132
    u.l = val;
1133
    /* NaN are not treated the same way IEEE 754 does */
1134
    if (unlikely(float32_is_quiet_nan(u.f))) {
1135
        return 0;
1136
    }
1137

    
1138
    return float32_to_uint32(u.f, &env->vec_status);
1139
}
1140

    
1141
static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val)
1142
{
1143
    CPU_FloatU u;
1144

    
1145
    u.l = val;
1146
    /* NaN are not treated the same way IEEE 754 does */
1147
    if (unlikely(float32_is_quiet_nan(u.f))) {
1148
        return 0;
1149
    }
1150

    
1151
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
1152
}
1153

    
1154
static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val)
1155
{
1156
    CPU_FloatU u;
1157

    
1158
    u.l = val;
1159
    /* NaN are not treated the same way IEEE 754 does */
1160
    if (unlikely(float32_is_quiet_nan(u.f))) {
1161
        return 0;
1162
    }
1163

    
1164
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
1165
}
1166

    
1167
static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val)
1168
{
1169
    CPU_FloatU u;
1170
    float32 tmp;
1171

    
1172
    u.f = int32_to_float32(val, &env->vec_status);
1173
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
1174
    u.f = float32_div(u.f, tmp, &env->vec_status);
1175

    
1176
    return u.l;
1177
}
1178

    
1179
static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val)
1180
{
1181
    CPU_FloatU u;
1182
    float32 tmp;
1183

    
1184
    u.f = uint32_to_float32(val, &env->vec_status);
1185
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1186
    u.f = float32_div(u.f, tmp, &env->vec_status);
1187

    
1188
    return u.l;
1189
}
1190

    
1191
static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val)
1192
{
1193
    CPU_FloatU u;
1194
    float32 tmp;
1195

    
1196
    u.l = val;
1197
    /* NaN are not treated the same way IEEE 754 does */
1198
    if (unlikely(float32_is_quiet_nan(u.f))) {
1199
        return 0;
1200
    }
1201
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1202
    u.f = float32_mul(u.f, tmp, &env->vec_status);
1203

    
1204
    return float32_to_int32(u.f, &env->vec_status);
1205
}
1206

    
1207
static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val)
1208
{
1209
    CPU_FloatU u;
1210
    float32 tmp;
1211

    
1212
    u.l = val;
1213
    /* NaN are not treated the same way IEEE 754 does */
1214
    if (unlikely(float32_is_quiet_nan(u.f))) {
1215
        return 0;
1216
    }
1217
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1218
    u.f = float32_mul(u.f, tmp, &env->vec_status);
1219

    
1220
    return float32_to_uint32(u.f, &env->vec_status);
1221
}
1222

    
1223
#define HELPER_SPE_SINGLE_CONV(name)                              \
1224
    uint32_t helper_e##name(CPUPPCState *env, uint32_t val)       \
1225
    {                                                             \
1226
        return e##name(env, val);                                 \
1227
    }
1228
/* efscfsi */
1229
HELPER_SPE_SINGLE_CONV(fscfsi);
1230
/* efscfui */
1231
HELPER_SPE_SINGLE_CONV(fscfui);
1232
/* efscfuf */
1233
HELPER_SPE_SINGLE_CONV(fscfuf);
1234
/* efscfsf */
1235
HELPER_SPE_SINGLE_CONV(fscfsf);
1236
/* efsctsi */
1237
HELPER_SPE_SINGLE_CONV(fsctsi);
1238
/* efsctui */
1239
HELPER_SPE_SINGLE_CONV(fsctui);
1240
/* efsctsiz */
1241
HELPER_SPE_SINGLE_CONV(fsctsiz);
1242
/* efsctuiz */
1243
HELPER_SPE_SINGLE_CONV(fsctuiz);
1244
/* efsctsf */
1245
HELPER_SPE_SINGLE_CONV(fsctsf);
1246
/* efsctuf */
1247
HELPER_SPE_SINGLE_CONV(fsctuf);
1248

    
1249
#define HELPER_SPE_VECTOR_CONV(name)                            \
1250
    uint64_t helper_ev##name(CPUPPCState *env, uint64_t val)    \
1251
    {                                                           \
1252
        return ((uint64_t)e##name(env, val >> 32) << 32) |      \
1253
            (uint64_t)e##name(env, val);                        \
1254
    }
1255
/* evfscfsi */
1256
HELPER_SPE_VECTOR_CONV(fscfsi);
1257
/* evfscfui */
1258
HELPER_SPE_VECTOR_CONV(fscfui);
1259
/* evfscfuf */
1260
HELPER_SPE_VECTOR_CONV(fscfuf);
1261
/* evfscfsf */
1262
HELPER_SPE_VECTOR_CONV(fscfsf);
1263
/* evfsctsi */
1264
HELPER_SPE_VECTOR_CONV(fsctsi);
1265
/* evfsctui */
1266
HELPER_SPE_VECTOR_CONV(fsctui);
1267
/* evfsctsiz */
1268
HELPER_SPE_VECTOR_CONV(fsctsiz);
1269
/* evfsctuiz */
1270
HELPER_SPE_VECTOR_CONV(fsctuiz);
1271
/* evfsctsf */
1272
HELPER_SPE_VECTOR_CONV(fsctsf);
1273
/* evfsctuf */
1274
HELPER_SPE_VECTOR_CONV(fsctuf);
1275

    
1276
/* Single-precision floating-point arithmetic */
1277
static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2)
1278
{
1279
    CPU_FloatU u1, u2;
1280

    
1281
    u1.l = op1;
1282
    u2.l = op2;
1283
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
1284
    return u1.l;
1285
}
1286

    
1287
static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2)
1288
{
1289
    CPU_FloatU u1, u2;
1290

    
1291
    u1.l = op1;
1292
    u2.l = op2;
1293
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
1294
    return u1.l;
1295
}
1296

    
1297
static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2)
1298
{
1299
    CPU_FloatU u1, u2;
1300

    
1301
    u1.l = op1;
1302
    u2.l = op2;
1303
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
1304
    return u1.l;
1305
}
1306

    
1307
static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2)
1308
{
1309
    CPU_FloatU u1, u2;
1310

    
1311
    u1.l = op1;
1312
    u2.l = op2;
1313
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
1314
    return u1.l;
1315
}
1316

    
1317
#define HELPER_SPE_SINGLE_ARITH(name)                                   \
1318
    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1319
    {                                                                   \
1320
        return e##name(env, op1, op2);                                  \
1321
    }
1322
/* efsadd */
1323
HELPER_SPE_SINGLE_ARITH(fsadd);
1324
/* efssub */
1325
HELPER_SPE_SINGLE_ARITH(fssub);
1326
/* efsmul */
1327
HELPER_SPE_SINGLE_ARITH(fsmul);
1328
/* efsdiv */
1329
HELPER_SPE_SINGLE_ARITH(fsdiv);
1330

    
1331
#define HELPER_SPE_VECTOR_ARITH(name)                                   \
1332
    uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1333
    {                                                                   \
1334
        return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) |   \
1335
            (uint64_t)e##name(env, op1, op2);                           \
1336
    }
1337
/* evfsadd */
1338
HELPER_SPE_VECTOR_ARITH(fsadd);
1339
/* evfssub */
1340
HELPER_SPE_VECTOR_ARITH(fssub);
1341
/* evfsmul */
1342
HELPER_SPE_VECTOR_ARITH(fsmul);
1343
/* evfsdiv */
1344
HELPER_SPE_VECTOR_ARITH(fsdiv);
1345

    
1346
/* Single-precision floating-point comparisons */
1347
static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1348
{
1349
    CPU_FloatU u1, u2;
1350

    
1351
    u1.l = op1;
1352
    u2.l = op2;
1353
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1354
}
1355

    
1356
static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1357
{
1358
    CPU_FloatU u1, u2;
1359

    
1360
    u1.l = op1;
1361
    u2.l = op2;
1362
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
1363
}
1364

    
1365
static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1366
{
1367
    CPU_FloatU u1, u2;
1368

    
1369
    u1.l = op1;
1370
    u2.l = op2;
1371
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1372
}
1373

    
1374
static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1375
{
1376
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1377
    return efscmplt(env, op1, op2);
1378
}
1379

    
1380
static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1381
{
1382
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1383
    return efscmpgt(env, op1, op2);
1384
}
1385

    
1386
static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1387
{
1388
    /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1389
    return efscmpeq(env, op1, op2);
1390
}
1391

    
1392
#define HELPER_SINGLE_SPE_CMP(name)                                     \
1393
    uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1394
    {                                                                   \
1395
        return e##name(env, op1, op2) << 2;                             \
1396
    }
1397
/* efststlt */
1398
HELPER_SINGLE_SPE_CMP(fststlt);
1399
/* efststgt */
1400
HELPER_SINGLE_SPE_CMP(fststgt);
1401
/* efststeq */
1402
HELPER_SINGLE_SPE_CMP(fststeq);
1403
/* efscmplt */
1404
HELPER_SINGLE_SPE_CMP(fscmplt);
1405
/* efscmpgt */
1406
HELPER_SINGLE_SPE_CMP(fscmpgt);
1407
/* efscmpeq */
1408
HELPER_SINGLE_SPE_CMP(fscmpeq);
1409

    
1410
static inline uint32_t evcmp_merge(int t0, int t1)
1411
{
1412
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1413
}
1414

    
1415
#define HELPER_VECTOR_SPE_CMP(name)                                     \
1416
    uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1417
    {                                                                   \
1418
        return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32),          \
1419
                           e##name(env, op1, op2));                     \
1420
    }
1421
/* evfststlt */
1422
HELPER_VECTOR_SPE_CMP(fststlt);
1423
/* evfststgt */
1424
HELPER_VECTOR_SPE_CMP(fststgt);
1425
/* evfststeq */
1426
HELPER_VECTOR_SPE_CMP(fststeq);
1427
/* evfscmplt */
1428
HELPER_VECTOR_SPE_CMP(fscmplt);
1429
/* evfscmpgt */
1430
HELPER_VECTOR_SPE_CMP(fscmpgt);
1431
/* evfscmpeq */
1432
HELPER_VECTOR_SPE_CMP(fscmpeq);
1433

    
1434
/* Double-precision floating-point conversion */
1435
uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val)
1436
{
1437
    CPU_DoubleU u;
1438

    
1439
    u.d = int32_to_float64(val, &env->vec_status);
1440

    
1441
    return u.ll;
1442
}
1443

    
1444
uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val)
1445
{
1446
    CPU_DoubleU u;
1447

    
1448
    u.d = int64_to_float64(val, &env->vec_status);
1449

    
1450
    return u.ll;
1451
}
1452

    
1453
uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val)
1454
{
1455
    CPU_DoubleU u;
1456

    
1457
    u.d = uint32_to_float64(val, &env->vec_status);
1458

    
1459
    return u.ll;
1460
}
1461

    
1462
uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val)
1463
{
1464
    CPU_DoubleU u;
1465

    
1466
    u.d = uint64_to_float64(val, &env->vec_status);
1467

    
1468
    return u.ll;
1469
}
1470

    
1471
uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val)
1472
{
1473
    CPU_DoubleU u;
1474

    
1475
    u.ll = val;
1476
    /* NaN are not treated the same way IEEE 754 does */
1477
    if (unlikely(float64_is_any_nan(u.d))) {
1478
        return 0;
1479
    }
1480

    
1481
    return float64_to_int32(u.d, &env->vec_status);
1482
}
1483

    
1484
uint32_t helper_efdctui(CPUPPCState *env, uint64_t val)
1485
{
1486
    CPU_DoubleU u;
1487

    
1488
    u.ll = val;
1489
    /* NaN are not treated the same way IEEE 754 does */
1490
    if (unlikely(float64_is_any_nan(u.d))) {
1491
        return 0;
1492
    }
1493

    
1494
    return float64_to_uint32(u.d, &env->vec_status);
1495
}
1496

    
1497
uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val)
1498
{
1499
    CPU_DoubleU u;
1500

    
1501
    u.ll = val;
1502
    /* NaN are not treated the same way IEEE 754 does */
1503
    if (unlikely(float64_is_any_nan(u.d))) {
1504
        return 0;
1505
    }
1506

    
1507
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
1508
}
1509

    
1510
uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val)
1511
{
1512
    CPU_DoubleU u;
1513

    
1514
    u.ll = val;
1515
    /* NaN are not treated the same way IEEE 754 does */
1516
    if (unlikely(float64_is_any_nan(u.d))) {
1517
        return 0;
1518
    }
1519

    
1520
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
1521
}
1522

    
1523
uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val)
1524
{
1525
    CPU_DoubleU u;
1526

    
1527
    u.ll = val;
1528
    /* NaN are not treated the same way IEEE 754 does */
1529
    if (unlikely(float64_is_any_nan(u.d))) {
1530
        return 0;
1531
    }
1532

    
1533
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
1534
}
1535

    
1536
uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val)
1537
{
1538
    CPU_DoubleU u;
1539

    
1540
    u.ll = val;
1541
    /* NaN are not treated the same way IEEE 754 does */
1542
    if (unlikely(float64_is_any_nan(u.d))) {
1543
        return 0;
1544
    }
1545

    
1546
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
1547
}
1548

    
1549
uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val)
1550
{
1551
    CPU_DoubleU u;
1552
    float64 tmp;
1553

    
1554
    u.d = int32_to_float64(val, &env->vec_status);
1555
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1556
    u.d = float64_div(u.d, tmp, &env->vec_status);
1557

    
1558
    return u.ll;
1559
}
1560

    
1561
uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val)
1562
{
1563
    CPU_DoubleU u;
1564
    float64 tmp;
1565

    
1566
    u.d = uint32_to_float64(val, &env->vec_status);
1567
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1568
    u.d = float64_div(u.d, tmp, &env->vec_status);
1569

    
1570
    return u.ll;
1571
}
1572

    
1573
uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val)
1574
{
1575
    CPU_DoubleU u;
1576
    float64 tmp;
1577

    
1578
    u.ll = val;
1579
    /* NaN are not treated the same way IEEE 754 does */
1580
    if (unlikely(float64_is_any_nan(u.d))) {
1581
        return 0;
1582
    }
1583
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1584
    u.d = float64_mul(u.d, tmp, &env->vec_status);
1585

    
1586
    return float64_to_int32(u.d, &env->vec_status);
1587
}
1588

    
1589
uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val)
1590
{
1591
    CPU_DoubleU u;
1592
    float64 tmp;
1593

    
1594
    u.ll = val;
1595
    /* NaN are not treated the same way IEEE 754 does */
1596
    if (unlikely(float64_is_any_nan(u.d))) {
1597
        return 0;
1598
    }
1599
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1600
    u.d = float64_mul(u.d, tmp, &env->vec_status);
1601

    
1602
    return float64_to_uint32(u.d, &env->vec_status);
1603
}
1604

    
1605
uint32_t helper_efscfd(CPUPPCState *env, uint64_t val)
1606
{
1607
    CPU_DoubleU u1;
1608
    CPU_FloatU u2;
1609

    
1610
    u1.ll = val;
1611
    u2.f = float64_to_float32(u1.d, &env->vec_status);
1612

    
1613
    return u2.l;
1614
}
1615

    
1616
uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val)
1617
{
1618
    CPU_DoubleU u2;
1619
    CPU_FloatU u1;
1620

    
1621
    u1.l = val;
1622
    u2.d = float32_to_float64(u1.f, &env->vec_status);
1623

    
1624
    return u2.ll;
1625
}
1626

    
1627
/* Double precision fixed-point arithmetic */
1628
uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2)
1629
{
1630
    CPU_DoubleU u1, u2;
1631

    
1632
    u1.ll = op1;
1633
    u2.ll = op2;
1634
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
1635
    return u1.ll;
1636
}
1637

    
1638
uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2)
1639
{
1640
    CPU_DoubleU u1, u2;
1641

    
1642
    u1.ll = op1;
1643
    u2.ll = op2;
1644
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
1645
    return u1.ll;
1646
}
1647

    
1648
uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2)
1649
{
1650
    CPU_DoubleU u1, u2;
1651

    
1652
    u1.ll = op1;
1653
    u2.ll = op2;
1654
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
1655
    return u1.ll;
1656
}
1657

    
1658
uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2)
1659
{
1660
    CPU_DoubleU u1, u2;
1661

    
1662
    u1.ll = op1;
1663
    u2.ll = op2;
1664
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
1665
    return u1.ll;
1666
}
1667

    
1668
/* Double precision floating point helpers */
1669
uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1670
{
1671
    CPU_DoubleU u1, u2;
1672

    
1673
    u1.ll = op1;
1674
    u2.ll = op2;
1675
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1676
}
1677

    
1678
uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1679
{
1680
    CPU_DoubleU u1, u2;
1681

    
1682
    u1.ll = op1;
1683
    u2.ll = op2;
1684
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
1685
}
1686

    
1687
uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1688
{
1689
    CPU_DoubleU u1, u2;
1690

    
1691
    u1.ll = op1;
1692
    u2.ll = op2;
1693
    return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1694
}
1695

    
1696
uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1697
{
1698
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1699
    return helper_efdtstlt(env, op1, op2);
1700
}
1701

    
1702
uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1703
{
1704
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1705
    return helper_efdtstgt(env, op1, op2);
1706
}
1707

    
1708
uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1709
{
1710
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1711
    return helper_efdtsteq(env, op1, op2);
1712
}