target-ppc: VSX Stage 4: add xsrsqrtesp
[qemu/ar7.git] / target-ppc / fpu_helper.c
blob33da46270c161ec9f32c2a07a7e1ea05751a121b
1 /*
2 * PowerPC floating point and SPE emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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/>.
19 #include "cpu.h"
20 #include "helper.h"
22 /*****************************************************************************/
23 /* Floating point operations helpers */
24 uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg)
26 CPU_FloatU f;
27 CPU_DoubleU d;
29 f.l = arg;
30 d.d = float32_to_float64(f.f, &env->fp_status);
31 return d.ll;
34 uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg)
36 CPU_FloatU f;
37 CPU_DoubleU d;
39 d.ll = arg;
40 f.f = float64_to_float32(d.d, &env->fp_status);
41 return f.l;
44 static inline int isden(float64 d)
46 CPU_DoubleU u;
48 u.d = d;
50 return ((u.ll >> 52) & 0x7FF) == 0;
53 uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf)
55 CPU_DoubleU farg;
56 int isneg;
57 int ret;
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;
69 } else if (unlikely(float64_is_infinity(farg.d))) {
70 /* +/- infinity */
71 if (isneg) {
72 ret = 0x09;
73 } else {
74 ret = 0x05;
76 } else {
77 if (float64_is_zero(farg.d)) {
78 /* +/- zero */
79 if (isneg) {
80 ret = 0x12;
81 } else {
82 ret = 0x02;
84 } else {
85 if (isden(farg.d)) {
86 /* Denormalized numbers */
87 ret = 0x10;
88 } else {
89 /* Normalized numbers */
90 ret = 0x00;
92 if (isneg) {
93 ret |= 0x08;
94 } else {
95 ret |= 0x04;
99 if (set_fprf) {
100 /* We update FPSCR_FPRF */
101 env->fpscr &= ~(0x1F << FPSCR_FPRF);
102 env->fpscr |= ret << FPSCR_FPRF;
104 /* We just need fpcc to update Rc1 */
105 return ret & 0xF;
108 /* Floating-point invalid operations exception */
109 static inline uint64_t fload_invalid_op_excp(CPUPPCState *env, int op,
110 int set_fpcc)
112 uint64_t ret = 0;
113 int ve;
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;
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;
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;
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;
182 break;
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);
196 return ret;
199 static inline void float_zero_divide_excp(CPUPPCState *env)
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);
215 static inline void float_overflow_excp(CPUPPCState *env)
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;
233 static inline void float_underflow_excp(CPUPPCState *env)
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;
248 static inline void float_inexact_excp(CPUPPCState *env)
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;
262 static inline void fpscr_set_rounding_mode(CPUPPCState *env)
264 int rnd_type;
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;
286 set_float_rounding_mode(rnd_type, &env->fp_status);
289 void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
291 int prev;
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;
307 void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
309 int prev;
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;
320 break;
321 case FPSCR_OX:
322 env->fpscr |= 1 << FPSCR_FX;
323 if (fpscr_oe) {
324 goto raise_oe;
326 break;
327 case FPSCR_UX:
328 env->fpscr |= 1 << FPSCR_FX;
329 if (fpscr_ue) {
330 goto raise_ue;
332 break;
333 case FPSCR_ZX:
334 env->fpscr |= 1 << FPSCR_FX;
335 if (fpscr_ze) {
336 goto raise_ze;
338 break;
339 case FPSCR_XX:
340 env->fpscr |= 1 << FPSCR_FX;
341 if (fpscr_xe) {
342 goto raise_xe;
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;
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;
367 if (fpscr_vxisi) {
368 env->error_code |= POWERPC_EXCP_FP_VXISI;
370 if (fpscr_vxidi) {
371 env->error_code |= POWERPC_EXCP_FP_VXIDI;
373 if (fpscr_vxzdz) {
374 env->error_code |= POWERPC_EXCP_FP_VXZDZ;
376 if (fpscr_vximz) {
377 env->error_code |= POWERPC_EXCP_FP_VXIMZ;
379 if (fpscr_vxvc) {
380 env->error_code |= POWERPC_EXCP_FP_VXVC;
382 if (fpscr_vxsoft) {
383 env->error_code |= POWERPC_EXCP_FP_VXSOFT;
385 if (fpscr_vxsqrt) {
386 env->error_code |= POWERPC_EXCP_FP_VXSQRT;
388 if (fpscr_vxcvi) {
389 env->error_code |= POWERPC_EXCP_FP_VXCVI;
391 goto raise_excp;
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;
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;
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;
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;
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;
438 void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
440 target_ulong prev, new;
441 int i;
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));
453 /* Update VX and FEX */
454 if (fpscr_ix != 0) {
455 env->fpscr |= 1 << FPSCR_VX;
456 } else {
457 env->fpscr &= ~(1 << FPSCR_VX);
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);
467 fpscr_set_rounding_mode(env);
470 void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
472 helper_store_fpscr(env, arg, mask);
475 void helper_float_check_status(CPUPPCState *env)
477 int status = get_float_exception_flags(&env->fp_status);
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);
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);
499 void helper_reset_fpstatus(CPUPPCState *env)
501 set_float_exception_flags(0, &env->fp_status);
504 /* fadd - fadd. */
505 uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
507 CPU_DoubleU farg1, farg2;
509 farg1.ll = arg1;
510 farg2.ll = arg2;
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);
522 farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
525 return farg1.ll;
528 /* fsub - fsub. */
529 uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
531 CPU_DoubleU farg1, farg2;
533 farg1.ll = arg1;
534 farg2.ll = arg2;
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);
546 farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
549 return farg1.ll;
552 /* fmul - fmul. */
553 uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
555 CPU_DoubleU farg1, farg2;
557 farg1.ll = arg1;
558 farg2.ll = arg2;
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);
570 farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
573 return farg1.ll;
576 /* fdiv - fdiv. */
577 uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
579 CPU_DoubleU farg1, farg2;
581 farg1.ll = arg1;
582 farg2.ll = arg2;
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);
597 farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
600 return farg1.ll;
603 /* fctiw - fctiw. */
604 uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
606 CPU_DoubleU farg;
608 farg.ll = arg;
610 if (unlikely(float64_is_signaling_nan(farg.d))) {
611 /* sNaN conversion */
612 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
613 POWERPC_EXCP_FP_VXCVI, 1);
614 } else if (unlikely(float64_is_quiet_nan(farg.d) ||
615 float64_is_infinity(farg.d))) {
616 /* qNan / infinity conversion */
617 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
618 } else {
619 farg.ll = float64_to_int32(farg.d, &env->fp_status);
620 /* XXX: higher bits are not supposed to be significant.
621 * to make tests easier, return the same as a real PowerPC 750
623 farg.ll |= 0xFFF80000ULL << 32;
625 return farg.ll;
628 /* fctiwz - fctiwz. */
629 uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg)
631 CPU_DoubleU farg;
633 farg.ll = arg;
635 if (unlikely(float64_is_signaling_nan(farg.d))) {
636 /* sNaN conversion */
637 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
638 POWERPC_EXCP_FP_VXCVI, 1);
639 } else if (unlikely(float64_is_quiet_nan(farg.d) ||
640 float64_is_infinity(farg.d))) {
641 /* qNan / infinity conversion */
642 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
643 } else {
644 farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
645 /* XXX: higher bits are not supposed to be significant.
646 * to make tests easier, return the same as a real PowerPC 750
648 farg.ll |= 0xFFF80000ULL << 32;
650 return farg.ll;
653 #if defined(TARGET_PPC64)
654 /* fcfid - fcfid. */
655 uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
657 CPU_DoubleU farg;
659 farg.d = int64_to_float64(arg, &env->fp_status);
660 return farg.ll;
663 /* fctid - fctid. */
664 uint64_t helper_fctid(CPUPPCState *env, uint64_t arg)
666 CPU_DoubleU farg;
668 farg.ll = arg;
670 if (unlikely(float64_is_signaling_nan(farg.d))) {
671 /* sNaN conversion */
672 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
673 POWERPC_EXCP_FP_VXCVI, 1);
674 } else if (unlikely(float64_is_quiet_nan(farg.d) ||
675 float64_is_infinity(farg.d))) {
676 /* qNan / infinity conversion */
677 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
678 } else {
679 farg.ll = float64_to_int64(farg.d, &env->fp_status);
681 return farg.ll;
684 /* fctidz - fctidz. */
685 uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg)
687 CPU_DoubleU farg;
689 farg.ll = arg;
691 if (unlikely(float64_is_signaling_nan(farg.d))) {
692 /* sNaN conversion */
693 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
694 POWERPC_EXCP_FP_VXCVI, 1);
695 } else if (unlikely(float64_is_quiet_nan(farg.d) ||
696 float64_is_infinity(farg.d))) {
697 /* qNan / infinity conversion */
698 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
699 } else {
700 farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
702 return farg.ll;
705 #endif
707 static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
708 int rounding_mode)
710 CPU_DoubleU farg;
712 farg.ll = arg;
714 if (unlikely(float64_is_signaling_nan(farg.d))) {
715 /* sNaN round */
716 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
717 POWERPC_EXCP_FP_VXCVI, 1);
718 } else if (unlikely(float64_is_quiet_nan(farg.d) ||
719 float64_is_infinity(farg.d))) {
720 /* qNan / infinity round */
721 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
722 } else {
723 set_float_rounding_mode(rounding_mode, &env->fp_status);
724 farg.ll = float64_round_to_int(farg.d, &env->fp_status);
725 /* Restore rounding mode from FPSCR */
726 fpscr_set_rounding_mode(env);
728 return farg.ll;
731 uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
733 return do_fri(env, arg, float_round_nearest_even);
736 uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
738 return do_fri(env, arg, float_round_to_zero);
741 uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
743 return do_fri(env, arg, float_round_up);
746 uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
748 return do_fri(env, arg, float_round_down);
751 /* fmadd - fmadd. */
752 uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
753 uint64_t arg3)
755 CPU_DoubleU farg1, farg2, farg3;
757 farg1.ll = arg1;
758 farg2.ll = arg2;
759 farg3.ll = arg3;
761 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
762 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
763 /* Multiplication of zero by infinity */
764 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
765 } else {
766 if (unlikely(float64_is_signaling_nan(farg1.d) ||
767 float64_is_signaling_nan(farg2.d) ||
768 float64_is_signaling_nan(farg3.d))) {
769 /* sNaN operation */
770 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
772 /* This is the way the PowerPC specification defines it */
773 float128 ft0_128, ft1_128;
775 ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
776 ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
777 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
778 if (unlikely(float128_is_infinity(ft0_128) &&
779 float64_is_infinity(farg3.d) &&
780 float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
781 /* Magnitude subtraction of infinities */
782 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
783 } else {
784 ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
785 ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
786 farg1.d = float128_to_float64(ft0_128, &env->fp_status);
790 return farg1.ll;
793 /* fmsub - fmsub. */
794 uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
795 uint64_t arg3)
797 CPU_DoubleU farg1, farg2, farg3;
799 farg1.ll = arg1;
800 farg2.ll = arg2;
801 farg3.ll = arg3;
803 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
804 (float64_is_zero(farg1.d) &&
805 float64_is_infinity(farg2.d)))) {
806 /* Multiplication of zero by infinity */
807 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
808 } else {
809 if (unlikely(float64_is_signaling_nan(farg1.d) ||
810 float64_is_signaling_nan(farg2.d) ||
811 float64_is_signaling_nan(farg3.d))) {
812 /* sNaN operation */
813 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
815 /* This is the way the PowerPC specification defines it */
816 float128 ft0_128, ft1_128;
818 ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
819 ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
820 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
821 if (unlikely(float128_is_infinity(ft0_128) &&
822 float64_is_infinity(farg3.d) &&
823 float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
824 /* Magnitude subtraction of infinities */
825 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
826 } else {
827 ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
828 ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
829 farg1.d = float128_to_float64(ft0_128, &env->fp_status);
832 return farg1.ll;
835 /* fnmadd - fnmadd. */
836 uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
837 uint64_t arg3)
839 CPU_DoubleU farg1, farg2, farg3;
841 farg1.ll = arg1;
842 farg2.ll = arg2;
843 farg3.ll = arg3;
845 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
846 (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
847 /* Multiplication of zero by infinity */
848 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
849 } else {
850 if (unlikely(float64_is_signaling_nan(farg1.d) ||
851 float64_is_signaling_nan(farg2.d) ||
852 float64_is_signaling_nan(farg3.d))) {
853 /* sNaN operation */
854 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
856 /* This is the way the PowerPC specification defines it */
857 float128 ft0_128, ft1_128;
859 ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
860 ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
861 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
862 if (unlikely(float128_is_infinity(ft0_128) &&
863 float64_is_infinity(farg3.d) &&
864 float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
865 /* Magnitude subtraction of infinities */
866 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
867 } else {
868 ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
869 ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
870 farg1.d = float128_to_float64(ft0_128, &env->fp_status);
872 if (likely(!float64_is_any_nan(farg1.d))) {
873 farg1.d = float64_chs(farg1.d);
876 return farg1.ll;
879 /* fnmsub - fnmsub. */
880 uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
881 uint64_t arg3)
883 CPU_DoubleU farg1, farg2, farg3;
885 farg1.ll = arg1;
886 farg2.ll = arg2;
887 farg3.ll = arg3;
889 if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
890 (float64_is_zero(farg1.d) &&
891 float64_is_infinity(farg2.d)))) {
892 /* Multiplication of zero by infinity */
893 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
894 } else {
895 if (unlikely(float64_is_signaling_nan(farg1.d) ||
896 float64_is_signaling_nan(farg2.d) ||
897 float64_is_signaling_nan(farg3.d))) {
898 /* sNaN operation */
899 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
901 /* This is the way the PowerPC specification defines it */
902 float128 ft0_128, ft1_128;
904 ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
905 ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
906 ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
907 if (unlikely(float128_is_infinity(ft0_128) &&
908 float64_is_infinity(farg3.d) &&
909 float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
910 /* Magnitude subtraction of infinities */
911 farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
912 } else {
913 ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
914 ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
915 farg1.d = float128_to_float64(ft0_128, &env->fp_status);
917 if (likely(!float64_is_any_nan(farg1.d))) {
918 farg1.d = float64_chs(farg1.d);
921 return farg1.ll;
924 /* frsp - frsp. */
925 uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
927 CPU_DoubleU farg;
928 float32 f32;
930 farg.ll = arg;
932 if (unlikely(float64_is_signaling_nan(farg.d))) {
933 /* sNaN square root */
934 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
936 f32 = float64_to_float32(farg.d, &env->fp_status);
937 farg.d = float32_to_float64(f32, &env->fp_status);
939 return farg.ll;
942 /* fsqrt - fsqrt. */
943 uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
945 CPU_DoubleU farg;
947 farg.ll = arg;
949 if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
950 /* Square root of a negative nonzero number */
951 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
952 } else {
953 if (unlikely(float64_is_signaling_nan(farg.d))) {
954 /* sNaN square root */
955 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
957 farg.d = float64_sqrt(farg.d, &env->fp_status);
959 return farg.ll;
962 /* fre - fre. */
963 uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
965 CPU_DoubleU farg;
967 farg.ll = arg;
969 if (unlikely(float64_is_signaling_nan(farg.d))) {
970 /* sNaN reciprocal */
971 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
973 farg.d = float64_div(float64_one, farg.d, &env->fp_status);
974 return farg.d;
977 /* fres - fres. */
978 uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
980 CPU_DoubleU farg;
981 float32 f32;
983 farg.ll = arg;
985 if (unlikely(float64_is_signaling_nan(farg.d))) {
986 /* sNaN reciprocal */
987 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
989 farg.d = float64_div(float64_one, farg.d, &env->fp_status);
990 f32 = float64_to_float32(farg.d, &env->fp_status);
991 farg.d = float32_to_float64(f32, &env->fp_status);
993 return farg.ll;
996 /* frsqrte - frsqrte. */
997 uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
999 CPU_DoubleU farg;
1000 float32 f32;
1002 farg.ll = arg;
1004 if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1005 /* Reciprocal square root of a negative nonzero number */
1006 farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
1007 } else {
1008 if (unlikely(float64_is_signaling_nan(farg.d))) {
1009 /* sNaN reciprocal square root */
1010 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
1012 farg.d = float64_sqrt(farg.d, &env->fp_status);
1013 farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1014 f32 = float64_to_float32(farg.d, &env->fp_status);
1015 farg.d = float32_to_float64(f32, &env->fp_status);
1017 return farg.ll;
1020 /* fsel - fsel. */
1021 uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1022 uint64_t arg3)
1024 CPU_DoubleU farg1;
1026 farg1.ll = arg1;
1028 if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
1029 !float64_is_any_nan(farg1.d)) {
1030 return arg2;
1031 } else {
1032 return arg3;
1036 void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1037 uint32_t crfD)
1039 CPU_DoubleU farg1, farg2;
1040 uint32_t ret = 0;
1042 farg1.ll = arg1;
1043 farg2.ll = arg2;
1045 if (unlikely(float64_is_any_nan(farg1.d) ||
1046 float64_is_any_nan(farg2.d))) {
1047 ret = 0x01UL;
1048 } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1049 ret = 0x08UL;
1050 } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1051 ret = 0x04UL;
1052 } else {
1053 ret = 0x02UL;
1056 env->fpscr &= ~(0x0F << FPSCR_FPRF);
1057 env->fpscr |= ret << FPSCR_FPRF;
1058 env->crf[crfD] = ret;
1059 if (unlikely(ret == 0x01UL
1060 && (float64_is_signaling_nan(farg1.d) ||
1061 float64_is_signaling_nan(farg2.d)))) {
1062 /* sNaN comparison */
1063 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
1067 void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
1068 uint32_t crfD)
1070 CPU_DoubleU farg1, farg2;
1071 uint32_t ret = 0;
1073 farg1.ll = arg1;
1074 farg2.ll = arg2;
1076 if (unlikely(float64_is_any_nan(farg1.d) ||
1077 float64_is_any_nan(farg2.d))) {
1078 ret = 0x01UL;
1079 } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1080 ret = 0x08UL;
1081 } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1082 ret = 0x04UL;
1083 } else {
1084 ret = 0x02UL;
1087 env->fpscr &= ~(0x0F << FPSCR_FPRF);
1088 env->fpscr |= ret << FPSCR_FPRF;
1089 env->crf[crfD] = ret;
1090 if (unlikely(ret == 0x01UL)) {
1091 if (float64_is_signaling_nan(farg1.d) ||
1092 float64_is_signaling_nan(farg2.d)) {
1093 /* sNaN comparison */
1094 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
1095 POWERPC_EXCP_FP_VXVC, 1);
1096 } else {
1097 /* qNaN comparison */
1098 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 1);
1103 /* Single-precision floating-point conversions */
1104 static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val)
1106 CPU_FloatU u;
1108 u.f = int32_to_float32(val, &env->vec_status);
1110 return u.l;
1113 static inline uint32_t efscfui(CPUPPCState *env, uint32_t val)
1115 CPU_FloatU u;
1117 u.f = uint32_to_float32(val, &env->vec_status);
1119 return u.l;
1122 static inline int32_t efsctsi(CPUPPCState *env, uint32_t val)
1124 CPU_FloatU u;
1126 u.l = val;
1127 /* NaN are not treated the same way IEEE 754 does */
1128 if (unlikely(float32_is_quiet_nan(u.f))) {
1129 return 0;
1132 return float32_to_int32(u.f, &env->vec_status);
1135 static inline uint32_t efsctui(CPUPPCState *env, uint32_t val)
1137 CPU_FloatU u;
1139 u.l = val;
1140 /* NaN are not treated the same way IEEE 754 does */
1141 if (unlikely(float32_is_quiet_nan(u.f))) {
1142 return 0;
1145 return float32_to_uint32(u.f, &env->vec_status);
1148 static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val)
1150 CPU_FloatU u;
1152 u.l = val;
1153 /* NaN are not treated the same way IEEE 754 does */
1154 if (unlikely(float32_is_quiet_nan(u.f))) {
1155 return 0;
1158 return float32_to_int32_round_to_zero(u.f, &env->vec_status);
1161 static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val)
1163 CPU_FloatU u;
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;
1171 return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
1174 static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val)
1176 CPU_FloatU u;
1177 float32 tmp;
1179 u.f = int32_to_float32(val, &env->vec_status);
1180 tmp = int64_to_float32(1ULL << 32, &env->vec_status);
1181 u.f = float32_div(u.f, tmp, &env->vec_status);
1183 return u.l;
1186 static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val)
1188 CPU_FloatU u;
1189 float32 tmp;
1191 u.f = uint32_to_float32(val, &env->vec_status);
1192 tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1193 u.f = float32_div(u.f, tmp, &env->vec_status);
1195 return u.l;
1198 static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val)
1200 CPU_FloatU u;
1201 float32 tmp;
1203 u.l = val;
1204 /* NaN are not treated the same way IEEE 754 does */
1205 if (unlikely(float32_is_quiet_nan(u.f))) {
1206 return 0;
1208 tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1209 u.f = float32_mul(u.f, tmp, &env->vec_status);
1211 return float32_to_int32(u.f, &env->vec_status);
1214 static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val)
1216 CPU_FloatU u;
1217 float32 tmp;
1219 u.l = val;
1220 /* NaN are not treated the same way IEEE 754 does */
1221 if (unlikely(float32_is_quiet_nan(u.f))) {
1222 return 0;
1224 tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1225 u.f = float32_mul(u.f, tmp, &env->vec_status);
1227 return float32_to_uint32(u.f, &env->vec_status);
1230 #define HELPER_SPE_SINGLE_CONV(name) \
1231 uint32_t helper_e##name(CPUPPCState *env, uint32_t val) \
1233 return e##name(env, val); \
1235 /* efscfsi */
1236 HELPER_SPE_SINGLE_CONV(fscfsi);
1237 /* efscfui */
1238 HELPER_SPE_SINGLE_CONV(fscfui);
1239 /* efscfuf */
1240 HELPER_SPE_SINGLE_CONV(fscfuf);
1241 /* efscfsf */
1242 HELPER_SPE_SINGLE_CONV(fscfsf);
1243 /* efsctsi */
1244 HELPER_SPE_SINGLE_CONV(fsctsi);
1245 /* efsctui */
1246 HELPER_SPE_SINGLE_CONV(fsctui);
1247 /* efsctsiz */
1248 HELPER_SPE_SINGLE_CONV(fsctsiz);
1249 /* efsctuiz */
1250 HELPER_SPE_SINGLE_CONV(fsctuiz);
1251 /* efsctsf */
1252 HELPER_SPE_SINGLE_CONV(fsctsf);
1253 /* efsctuf */
1254 HELPER_SPE_SINGLE_CONV(fsctuf);
1256 #define HELPER_SPE_VECTOR_CONV(name) \
1257 uint64_t helper_ev##name(CPUPPCState *env, uint64_t val) \
1259 return ((uint64_t)e##name(env, val >> 32) << 32) | \
1260 (uint64_t)e##name(env, val); \
1262 /* evfscfsi */
1263 HELPER_SPE_VECTOR_CONV(fscfsi);
1264 /* evfscfui */
1265 HELPER_SPE_VECTOR_CONV(fscfui);
1266 /* evfscfuf */
1267 HELPER_SPE_VECTOR_CONV(fscfuf);
1268 /* evfscfsf */
1269 HELPER_SPE_VECTOR_CONV(fscfsf);
1270 /* evfsctsi */
1271 HELPER_SPE_VECTOR_CONV(fsctsi);
1272 /* evfsctui */
1273 HELPER_SPE_VECTOR_CONV(fsctui);
1274 /* evfsctsiz */
1275 HELPER_SPE_VECTOR_CONV(fsctsiz);
1276 /* evfsctuiz */
1277 HELPER_SPE_VECTOR_CONV(fsctuiz);
1278 /* evfsctsf */
1279 HELPER_SPE_VECTOR_CONV(fsctsf);
1280 /* evfsctuf */
1281 HELPER_SPE_VECTOR_CONV(fsctuf);
1283 /* Single-precision floating-point arithmetic */
1284 static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2)
1286 CPU_FloatU u1, u2;
1288 u1.l = op1;
1289 u2.l = op2;
1290 u1.f = float32_add(u1.f, u2.f, &env->vec_status);
1291 return u1.l;
1294 static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2)
1296 CPU_FloatU u1, u2;
1298 u1.l = op1;
1299 u2.l = op2;
1300 u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
1301 return u1.l;
1304 static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2)
1306 CPU_FloatU u1, u2;
1308 u1.l = op1;
1309 u2.l = op2;
1310 u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
1311 return u1.l;
1314 static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2)
1316 CPU_FloatU u1, u2;
1318 u1.l = op1;
1319 u2.l = op2;
1320 u1.f = float32_div(u1.f, u2.f, &env->vec_status);
1321 return u1.l;
1324 #define HELPER_SPE_SINGLE_ARITH(name) \
1325 uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1327 return e##name(env, op1, op2); \
1329 /* efsadd */
1330 HELPER_SPE_SINGLE_ARITH(fsadd);
1331 /* efssub */
1332 HELPER_SPE_SINGLE_ARITH(fssub);
1333 /* efsmul */
1334 HELPER_SPE_SINGLE_ARITH(fsmul);
1335 /* efsdiv */
1336 HELPER_SPE_SINGLE_ARITH(fsdiv);
1338 #define HELPER_SPE_VECTOR_ARITH(name) \
1339 uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1341 return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) | \
1342 (uint64_t)e##name(env, op1, op2); \
1344 /* evfsadd */
1345 HELPER_SPE_VECTOR_ARITH(fsadd);
1346 /* evfssub */
1347 HELPER_SPE_VECTOR_ARITH(fssub);
1348 /* evfsmul */
1349 HELPER_SPE_VECTOR_ARITH(fsmul);
1350 /* evfsdiv */
1351 HELPER_SPE_VECTOR_ARITH(fsdiv);
1353 /* Single-precision floating-point comparisons */
1354 static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1356 CPU_FloatU u1, u2;
1358 u1.l = op1;
1359 u2.l = op2;
1360 return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1363 static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1365 CPU_FloatU u1, u2;
1367 u1.l = op1;
1368 u2.l = op2;
1369 return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
1372 static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1374 CPU_FloatU u1, u2;
1376 u1.l = op1;
1377 u2.l = op2;
1378 return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1381 static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1383 /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1384 return efscmplt(env, op1, op2);
1387 static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1389 /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1390 return efscmpgt(env, op1, op2);
1393 static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1395 /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1396 return efscmpeq(env, op1, op2);
1399 #define HELPER_SINGLE_SPE_CMP(name) \
1400 uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1402 return e##name(env, op1, op2) << 2; \
1404 /* efststlt */
1405 HELPER_SINGLE_SPE_CMP(fststlt);
1406 /* efststgt */
1407 HELPER_SINGLE_SPE_CMP(fststgt);
1408 /* efststeq */
1409 HELPER_SINGLE_SPE_CMP(fststeq);
1410 /* efscmplt */
1411 HELPER_SINGLE_SPE_CMP(fscmplt);
1412 /* efscmpgt */
1413 HELPER_SINGLE_SPE_CMP(fscmpgt);
1414 /* efscmpeq */
1415 HELPER_SINGLE_SPE_CMP(fscmpeq);
1417 static inline uint32_t evcmp_merge(int t0, int t1)
1419 return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1422 #define HELPER_VECTOR_SPE_CMP(name) \
1423 uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1425 return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32), \
1426 e##name(env, op1, op2)); \
1428 /* evfststlt */
1429 HELPER_VECTOR_SPE_CMP(fststlt);
1430 /* evfststgt */
1431 HELPER_VECTOR_SPE_CMP(fststgt);
1432 /* evfststeq */
1433 HELPER_VECTOR_SPE_CMP(fststeq);
1434 /* evfscmplt */
1435 HELPER_VECTOR_SPE_CMP(fscmplt);
1436 /* evfscmpgt */
1437 HELPER_VECTOR_SPE_CMP(fscmpgt);
1438 /* evfscmpeq */
1439 HELPER_VECTOR_SPE_CMP(fscmpeq);
1441 /* Double-precision floating-point conversion */
1442 uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val)
1444 CPU_DoubleU u;
1446 u.d = int32_to_float64(val, &env->vec_status);
1448 return u.ll;
1451 uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val)
1453 CPU_DoubleU u;
1455 u.d = int64_to_float64(val, &env->vec_status);
1457 return u.ll;
1460 uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val)
1462 CPU_DoubleU u;
1464 u.d = uint32_to_float64(val, &env->vec_status);
1466 return u.ll;
1469 uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val)
1471 CPU_DoubleU u;
1473 u.d = uint64_to_float64(val, &env->vec_status);
1475 return u.ll;
1478 uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val)
1480 CPU_DoubleU u;
1482 u.ll = val;
1483 /* NaN are not treated the same way IEEE 754 does */
1484 if (unlikely(float64_is_any_nan(u.d))) {
1485 return 0;
1488 return float64_to_int32(u.d, &env->vec_status);
1491 uint32_t helper_efdctui(CPUPPCState *env, uint64_t val)
1493 CPU_DoubleU u;
1495 u.ll = val;
1496 /* NaN are not treated the same way IEEE 754 does */
1497 if (unlikely(float64_is_any_nan(u.d))) {
1498 return 0;
1501 return float64_to_uint32(u.d, &env->vec_status);
1504 uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val)
1506 CPU_DoubleU u;
1508 u.ll = val;
1509 /* NaN are not treated the same way IEEE 754 does */
1510 if (unlikely(float64_is_any_nan(u.d))) {
1511 return 0;
1514 return float64_to_int32_round_to_zero(u.d, &env->vec_status);
1517 uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val)
1519 CPU_DoubleU u;
1521 u.ll = val;
1522 /* NaN are not treated the same way IEEE 754 does */
1523 if (unlikely(float64_is_any_nan(u.d))) {
1524 return 0;
1527 return float64_to_int64_round_to_zero(u.d, &env->vec_status);
1530 uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val)
1532 CPU_DoubleU u;
1534 u.ll = val;
1535 /* NaN are not treated the same way IEEE 754 does */
1536 if (unlikely(float64_is_any_nan(u.d))) {
1537 return 0;
1540 return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
1543 uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val)
1545 CPU_DoubleU u;
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;
1553 return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
1556 uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val)
1558 CPU_DoubleU u;
1559 float64 tmp;
1561 u.d = int32_to_float64(val, &env->vec_status);
1562 tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1563 u.d = float64_div(u.d, tmp, &env->vec_status);
1565 return u.ll;
1568 uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val)
1570 CPU_DoubleU u;
1571 float64 tmp;
1573 u.d = uint32_to_float64(val, &env->vec_status);
1574 tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1575 u.d = float64_div(u.d, tmp, &env->vec_status);
1577 return u.ll;
1580 uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val)
1582 CPU_DoubleU u;
1583 float64 tmp;
1585 u.ll = val;
1586 /* NaN are not treated the same way IEEE 754 does */
1587 if (unlikely(float64_is_any_nan(u.d))) {
1588 return 0;
1590 tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1591 u.d = float64_mul(u.d, tmp, &env->vec_status);
1593 return float64_to_int32(u.d, &env->vec_status);
1596 uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val)
1598 CPU_DoubleU u;
1599 float64 tmp;
1601 u.ll = val;
1602 /* NaN are not treated the same way IEEE 754 does */
1603 if (unlikely(float64_is_any_nan(u.d))) {
1604 return 0;
1606 tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1607 u.d = float64_mul(u.d, tmp, &env->vec_status);
1609 return float64_to_uint32(u.d, &env->vec_status);
1612 uint32_t helper_efscfd(CPUPPCState *env, uint64_t val)
1614 CPU_DoubleU u1;
1615 CPU_FloatU u2;
1617 u1.ll = val;
1618 u2.f = float64_to_float32(u1.d, &env->vec_status);
1620 return u2.l;
1623 uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val)
1625 CPU_DoubleU u2;
1626 CPU_FloatU u1;
1628 u1.l = val;
1629 u2.d = float32_to_float64(u1.f, &env->vec_status);
1631 return u2.ll;
1634 /* Double precision fixed-point arithmetic */
1635 uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2)
1637 CPU_DoubleU u1, u2;
1639 u1.ll = op1;
1640 u2.ll = op2;
1641 u1.d = float64_add(u1.d, u2.d, &env->vec_status);
1642 return u1.ll;
1645 uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2)
1647 CPU_DoubleU u1, u2;
1649 u1.ll = op1;
1650 u2.ll = op2;
1651 u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
1652 return u1.ll;
1655 uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2)
1657 CPU_DoubleU u1, u2;
1659 u1.ll = op1;
1660 u2.ll = op2;
1661 u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
1662 return u1.ll;
1665 uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2)
1667 CPU_DoubleU u1, u2;
1669 u1.ll = op1;
1670 u2.ll = op2;
1671 u1.d = float64_div(u1.d, u2.d, &env->vec_status);
1672 return u1.ll;
1675 /* Double precision floating point helpers */
1676 uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1678 CPU_DoubleU u1, u2;
1680 u1.ll = op1;
1681 u2.ll = op2;
1682 return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1685 uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1687 CPU_DoubleU u1, u2;
1689 u1.ll = op1;
1690 u2.ll = op2;
1691 return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
1694 uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1696 CPU_DoubleU u1, u2;
1698 u1.ll = op1;
1699 u2.ll = op2;
1700 return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1703 uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1705 /* XXX: TODO: test special values (NaN, infinites, ...) */
1706 return helper_efdtstlt(env, op1, op2);
1709 uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1711 /* XXX: TODO: test special values (NaN, infinites, ...) */
1712 return helper_efdtstgt(env, op1, op2);
1715 uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1717 /* XXX: TODO: test special values (NaN, infinites, ...) */
1718 return helper_efdtsteq(env, op1, op2);
1721 #define DECODE_SPLIT(opcode, shift1, nb1, shift2, nb2) \
1722 (((((opcode) >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \
1723 (((opcode) >> (shift2)) & ((1 << (nb2)) - 1)))
1725 #define xT(opcode) DECODE_SPLIT(opcode, 0, 1, 21, 5)
1726 #define xA(opcode) DECODE_SPLIT(opcode, 2, 1, 16, 5)
1727 #define xB(opcode) DECODE_SPLIT(opcode, 1, 1, 11, 5)
1728 #define xC(opcode) DECODE_SPLIT(opcode, 3, 1, 6, 5)
1729 #define BF(opcode) (((opcode) >> (31-8)) & 7)
1731 typedef union _ppc_vsr_t {
1732 uint64_t u64[2];
1733 uint32_t u32[4];
1734 float32 f32[4];
1735 float64 f64[2];
1736 } ppc_vsr_t;
1738 static void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
1740 if (n < 32) {
1741 vsr->f64[0] = env->fpr[n];
1742 vsr->u64[1] = env->vsr[n];
1743 } else {
1744 vsr->u64[0] = env->avr[n-32].u64[0];
1745 vsr->u64[1] = env->avr[n-32].u64[1];
1749 static void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
1751 if (n < 32) {
1752 env->fpr[n] = vsr->f64[0];
1753 env->vsr[n] = vsr->u64[1];
1754 } else {
1755 env->avr[n-32].u64[0] = vsr->u64[0];
1756 env->avr[n-32].u64[1] = vsr->u64[1];
1760 #define float64_to_float64(x, env) x
1763 /* VSX_ADD_SUB - VSX floating point add/subract
1764 * name - instruction mnemonic
1765 * op - operation (add or sub)
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
1771 #define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \
1772 void helper_##name(CPUPPCState *env, uint32_t opcode) \
1774 ppc_vsr_t xt, xa, xb; \
1775 int i; \
1777 getVSR(xA(opcode), &xa, env); \
1778 getVSR(xB(opcode), &xb, env); \
1779 getVSR(xT(opcode), &xt, env); \
1780 helper_reset_fpstatus(env); \
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##_##op(xa.fld[i], xb.fld[i], &tstat); \
1786 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1788 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
1789 if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) {\
1790 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
1791 } else if (tp##_is_signaling_nan(xa.fld[i]) || \
1792 tp##_is_signaling_nan(xb.fld[i])) { \
1793 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
1797 if (r2sp) { \
1798 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
1801 if (sfprf) { \
1802 helper_compute_fprf(env, xt.fld[i], sfprf); \
1805 putVSR(xT(opcode), &xt, env); \
1806 helper_float_check_status(env); \
1809 VSX_ADD_SUB(xsadddp, add, 1, float64, f64, 1, 0)
1810 VSX_ADD_SUB(xsaddsp, add, 1, float64, f64, 1, 1)
1811 VSX_ADD_SUB(xvadddp, add, 2, float64, f64, 0, 0)
1812 VSX_ADD_SUB(xvaddsp, add, 4, float32, f32, 0, 0)
1813 VSX_ADD_SUB(xssubdp, sub, 1, float64, f64, 1, 0)
1814 VSX_ADD_SUB(xssubsp, sub, 1, float64, f64, 1, 1)
1815 VSX_ADD_SUB(xvsubdp, sub, 2, float64, f64, 0, 0)
1816 VSX_ADD_SUB(xvsubsp, sub, 4, float32, f32, 0, 0)
1818 /* VSX_MUL - VSX floating point multiply
1819 * op - instruction mnemonic
1820 * nels - number of elements (1, 2 or 4)
1821 * tp - type (float32 or float64)
1822 * fld - vsr_t field (f32 or f64)
1823 * sfprf - set FPRF
1825 #define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \
1826 void helper_##op(CPUPPCState *env, uint32_t opcode) \
1828 ppc_vsr_t xt, xa, xb; \
1829 int i; \
1831 getVSR(xA(opcode), &xa, env); \
1832 getVSR(xB(opcode), &xb, env); \
1833 getVSR(xT(opcode), &xt, env); \
1834 helper_reset_fpstatus(env); \
1836 for (i = 0; i < nels; i++) { \
1837 float_status tstat = env->fp_status; \
1838 set_float_exception_flags(0, &tstat); \
1839 xt.fld[i] = tp##_mul(xa.fld[i], xb.fld[i], &tstat); \
1840 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1842 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
1843 if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(xb.fld[i])) || \
1844 (tp##_is_infinity(xb.fld[i]) && tp##_is_zero(xa.fld[i]))) { \
1845 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 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); \
1852 if (r2sp) { \
1853 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
1856 if (sfprf) { \
1857 helper_compute_fprf(env, xt.fld[i], sfprf); \
1861 putVSR(xT(opcode), &xt, env); \
1862 helper_float_check_status(env); \
1865 VSX_MUL(xsmuldp, 1, float64, f64, 1, 0)
1866 VSX_MUL(xsmulsp, 1, float64, f64, 1, 1)
1867 VSX_MUL(xvmuldp, 2, float64, f64, 0, 0)
1868 VSX_MUL(xvmulsp, 4, float32, f32, 0, 0)
1870 /* VSX_DIV - VSX floating point divide
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
1877 #define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \
1878 void helper_##op(CPUPPCState *env, uint32_t opcode) \
1880 ppc_vsr_t xt, xa, xb; \
1881 int i; \
1883 getVSR(xA(opcode), &xa, env); \
1884 getVSR(xB(opcode), &xb, env); \
1885 getVSR(xT(opcode), &xt, env); \
1886 helper_reset_fpstatus(env); \
1888 for (i = 0; i < nels; i++) { \
1889 float_status tstat = env->fp_status; \
1890 set_float_exception_flags(0, &tstat); \
1891 xt.fld[i] = tp##_div(xa.fld[i], xb.fld[i], &tstat); \
1892 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1894 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
1895 if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) { \
1896 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf); \
1897 } else if (tp##_is_zero(xa.fld[i]) && \
1898 tp##_is_zero(xb.fld[i])) { \
1899 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf); \
1900 } else if (tp##_is_signaling_nan(xa.fld[i]) || \
1901 tp##_is_signaling_nan(xb.fld[i])) { \
1902 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
1906 if (r2sp) { \
1907 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
1910 if (sfprf) { \
1911 helper_compute_fprf(env, xt.fld[i], sfprf); \
1915 putVSR(xT(opcode), &xt, env); \
1916 helper_float_check_status(env); \
1919 VSX_DIV(xsdivdp, 1, float64, f64, 1, 0)
1920 VSX_DIV(xsdivsp, 1, float64, f64, 1, 1)
1921 VSX_DIV(xvdivdp, 2, float64, f64, 0, 0)
1922 VSX_DIV(xvdivsp, 4, float32, f32, 0, 0)
1924 /* VSX_RE - VSX floating point reciprocal estimate
1925 * op - instruction mnemonic
1926 * nels - number of elements (1, 2 or 4)
1927 * tp - type (float32 or float64)
1928 * fld - vsr_t field (f32 or f64)
1929 * sfprf - set FPRF
1931 #define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
1932 void helper_##op(CPUPPCState *env, uint32_t opcode) \
1934 ppc_vsr_t xt, xb; \
1935 int i; \
1937 getVSR(xB(opcode), &xb, env); \
1938 getVSR(xT(opcode), &xt, env); \
1939 helper_reset_fpstatus(env); \
1941 for (i = 0; i < nels; i++) { \
1942 if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
1943 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
1945 xt.fld[i] = tp##_div(tp##_one, xb.fld[i], &env->fp_status); \
1947 if (r2sp) { \
1948 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
1951 if (sfprf) { \
1952 helper_compute_fprf(env, xt.fld[0], sfprf); \
1956 putVSR(xT(opcode), &xt, env); \
1957 helper_float_check_status(env); \
1960 VSX_RE(xsredp, 1, float64, f64, 1, 0)
1961 VSX_RE(xsresp, 1, float64, f64, 1, 1)
1962 VSX_RE(xvredp, 2, float64, f64, 0, 0)
1963 VSX_RE(xvresp, 4, float32, f32, 0, 0)
1965 /* VSX_SQRT - VSX floating point square root
1966 * op - instruction mnemonic
1967 * nels - number of elements (1, 2 or 4)
1968 * tp - type (float32 or float64)
1969 * fld - vsr_t field (f32 or f64)
1970 * sfprf - set FPRF
1972 #define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
1973 void helper_##op(CPUPPCState *env, uint32_t opcode) \
1975 ppc_vsr_t xt, xb; \
1976 int i; \
1978 getVSR(xB(opcode), &xb, env); \
1979 getVSR(xT(opcode), &xt, env); \
1980 helper_reset_fpstatus(env); \
1982 for (i = 0; i < nels; i++) { \
1983 float_status tstat = env->fp_status; \
1984 set_float_exception_flags(0, &tstat); \
1985 xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
1986 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1988 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
1989 if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
1990 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
1991 } else if (tp##_is_signaling_nan(xb.fld[i])) { \
1992 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
1996 if (r2sp) { \
1997 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
2000 if (sfprf) { \
2001 helper_compute_fprf(env, xt.fld[i], sfprf); \
2005 putVSR(xT(opcode), &xt, env); \
2006 helper_float_check_status(env); \
2009 VSX_SQRT(xssqrtdp, 1, float64, f64, 1, 0)
2010 VSX_SQRT(xssqrtsp, 1, float64, f64, 1, 1)
2011 VSX_SQRT(xvsqrtdp, 2, float64, f64, 0, 0)
2012 VSX_SQRT(xvsqrtsp, 4, float32, f32, 0, 0)
2014 /* VSX_RSQRTE - VSX floating point reciprocal square root estimate
2015 * op - instruction mnemonic
2016 * nels - number of elements (1, 2 or 4)
2017 * tp - type (float32 or float64)
2018 * fld - vsr_t field (f32 or f64)
2019 * sfprf - set FPRF
2021 #define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
2022 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2024 ppc_vsr_t xt, xb; \
2025 int i; \
2027 getVSR(xB(opcode), &xb, env); \
2028 getVSR(xT(opcode), &xt, env); \
2029 helper_reset_fpstatus(env); \
2031 for (i = 0; i < nels; i++) { \
2032 float_status tstat = env->fp_status; \
2033 set_float_exception_flags(0, &tstat); \
2034 xt.fld[i] = tp##_sqrt(xb.fld[i], &tstat); \
2035 xt.fld[i] = tp##_div(tp##_one, xt.fld[i], &tstat); \
2036 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
2038 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
2039 if (tp##_is_neg(xb.fld[i]) && !tp##_is_zero(xb.fld[i])) { \
2040 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf); \
2041 } else if (tp##_is_signaling_nan(xb.fld[i])) { \
2042 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
2046 if (r2sp) { \
2047 xt.fld[i] = helper_frsp(env, xt.fld[i]); \
2050 if (sfprf) { \
2051 helper_compute_fprf(env, xt.fld[i], sfprf); \
2055 putVSR(xT(opcode), &xt, env); \
2056 helper_float_check_status(env); \
2059 VSX_RSQRTE(xsrsqrtedp, 1, float64, f64, 1, 0)
2060 VSX_RSQRTE(xsrsqrtesp, 1, float64, f64, 1, 1)
2061 VSX_RSQRTE(xvrsqrtedp, 2, float64, f64, 0, 0)
2062 VSX_RSQRTE(xvrsqrtesp, 4, float32, f32, 0, 0)
2064 static inline int ppc_float32_get_unbiased_exp(float32 f)
2066 return ((f >> 23) & 0xFF) - 127;
2069 static inline int ppc_float64_get_unbiased_exp(float64 f)
2071 return ((f >> 52) & 0x7FF) - 1023;
2074 /* VSX_TDIV - VSX floating point test for divide
2075 * op - instruction mnemonic
2076 * nels - number of elements (1, 2 or 4)
2077 * tp - type (float32 or float64)
2078 * fld - vsr_t field (f32 or f64)
2079 * emin - minimum unbiased exponent
2080 * emax - maximum unbiased exponent
2081 * nbits - number of fraction bits
2083 #define VSX_TDIV(op, nels, tp, fld, emin, emax, nbits) \
2084 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2086 ppc_vsr_t xa, xb; \
2087 int i; \
2088 int fe_flag = 0; \
2089 int fg_flag = 0; \
2091 getVSR(xA(opcode), &xa, env); \
2092 getVSR(xB(opcode), &xb, env); \
2094 for (i = 0; i < nels; i++) { \
2095 if (unlikely(tp##_is_infinity(xa.fld[i]) || \
2096 tp##_is_infinity(xb.fld[i]) || \
2097 tp##_is_zero(xb.fld[i]))) { \
2098 fe_flag = 1; \
2099 fg_flag = 1; \
2100 } else { \
2101 int e_a = ppc_##tp##_get_unbiased_exp(xa.fld[i]); \
2102 int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
2104 if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
2105 tp##_is_any_nan(xb.fld[i]))) { \
2106 fe_flag = 1; \
2107 } else if ((e_b <= emin) || (e_b >= (emax-2))) { \
2108 fe_flag = 1; \
2109 } else if (!tp##_is_zero(xa.fld[i]) && \
2110 (((e_a - e_b) >= emax) || \
2111 ((e_a - e_b) <= (emin+1)) || \
2112 (e_a <= (emin+nbits)))) { \
2113 fe_flag = 1; \
2116 if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
2117 /* XB is not zero because of the above check and */ \
2118 /* so must be denormalized. */ \
2119 fg_flag = 1; \
2124 env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
2127 VSX_TDIV(xstdivdp, 1, float64, f64, -1022, 1023, 52)
2128 VSX_TDIV(xvtdivdp, 2, float64, f64, -1022, 1023, 52)
2129 VSX_TDIV(xvtdivsp, 4, float32, f32, -126, 127, 23)
2131 /* VSX_TSQRT - VSX floating point test for square root
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 * emin - minimum unbiased exponent
2137 * emax - maximum unbiased exponent
2138 * nbits - number of fraction bits
2140 #define VSX_TSQRT(op, nels, tp, fld, emin, nbits) \
2141 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2143 ppc_vsr_t xa, xb; \
2144 int i; \
2145 int fe_flag = 0; \
2146 int fg_flag = 0; \
2148 getVSR(xA(opcode), &xa, env); \
2149 getVSR(xB(opcode), &xb, env); \
2151 for (i = 0; i < nels; i++) { \
2152 if (unlikely(tp##_is_infinity(xb.fld[i]) || \
2153 tp##_is_zero(xb.fld[i]))) { \
2154 fe_flag = 1; \
2155 fg_flag = 1; \
2156 } else { \
2157 int e_b = ppc_##tp##_get_unbiased_exp(xb.fld[i]); \
2159 if (unlikely(tp##_is_any_nan(xb.fld[i]))) { \
2160 fe_flag = 1; \
2161 } else if (unlikely(tp##_is_zero(xb.fld[i]))) { \
2162 fe_flag = 1; \
2163 } else if (unlikely(tp##_is_neg(xb.fld[i]))) { \
2164 fe_flag = 1; \
2165 } else if (!tp##_is_zero(xb.fld[i]) && \
2166 (e_b <= (emin+nbits))) { \
2167 fe_flag = 1; \
2170 if (unlikely(tp##_is_zero_or_denormal(xb.fld[i]))) { \
2171 /* XB is not zero because of the above check and */ \
2172 /* therefore must be denormalized. */ \
2173 fg_flag = 1; \
2178 env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
2181 VSX_TSQRT(xstsqrtdp, 1, float64, f64, -1022, 52)
2182 VSX_TSQRT(xvtsqrtdp, 2, float64, f64, -1022, 52)
2183 VSX_TSQRT(xvtsqrtsp, 4, float32, f32, -126, 23)
2185 /* VSX_MADD - VSX floating point muliply/add variations
2186 * op - instruction mnemonic
2187 * nels - number of elements (1, 2 or 4)
2188 * tp - type (float32 or float64)
2189 * fld - vsr_t field (f32 or f64)
2190 * maddflgs - flags for the float*muladd routine that control the
2191 * various forms (madd, msub, nmadd, nmsub)
2192 * afrm - A form (1=A, 0=M)
2193 * sfprf - set FPRF
2195 #define VSX_MADD(op, nels, tp, fld, maddflgs, afrm, sfprf) \
2196 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2198 ppc_vsr_t xt_in, xa, xb, xt_out; \
2199 ppc_vsr_t *b, *c; \
2200 int i; \
2202 if (afrm) { /* AxB + T */ \
2203 b = &xb; \
2204 c = &xt_in; \
2205 } else { /* AxT + B */ \
2206 b = &xt_in; \
2207 c = &xb; \
2210 getVSR(xA(opcode), &xa, env); \
2211 getVSR(xB(opcode), &xb, env); \
2212 getVSR(xT(opcode), &xt_in, env); \
2214 xt_out = xt_in; \
2216 helper_reset_fpstatus(env); \
2218 for (i = 0; i < nels; i++) { \
2219 float_status tstat = env->fp_status; \
2220 set_float_exception_flags(0, &tstat); \
2221 xt_out.fld[i] = tp##_muladd(xa.fld[i], b->fld[i], c->fld[i], \
2222 maddflgs, &tstat); \
2223 env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
2225 if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
2226 if (tp##_is_signaling_nan(xa.fld[i]) || \
2227 tp##_is_signaling_nan(b->fld[i]) || \
2228 tp##_is_signaling_nan(c->fld[i])) { \
2229 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
2230 tstat.float_exception_flags &= ~float_flag_invalid; \
2232 if ((tp##_is_infinity(xa.fld[i]) && tp##_is_zero(b->fld[i])) || \
2233 (tp##_is_zero(xa.fld[i]) && tp##_is_infinity(b->fld[i]))) { \
2234 xt_out.fld[i] = float64_to_##tp(fload_invalid_op_excp(env, \
2235 POWERPC_EXCP_FP_VXIMZ, sfprf), &env->fp_status); \
2236 tstat.float_exception_flags &= ~float_flag_invalid; \
2238 if ((tstat.float_exception_flags & float_flag_invalid) && \
2239 ((tp##_is_infinity(xa.fld[i]) || \
2240 tp##_is_infinity(b->fld[i])) && \
2241 tp##_is_infinity(c->fld[i]))) { \
2242 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf); \
2245 if (sfprf) { \
2246 helper_compute_fprf(env, xt_out.fld[i], sfprf); \
2249 putVSR(xT(opcode), &xt_out, env); \
2250 helper_float_check_status(env); \
2253 #define MADD_FLGS 0
2254 #define MSUB_FLGS float_muladd_negate_c
2255 #define NMADD_FLGS float_muladd_negate_result
2256 #define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result)
2258 VSX_MADD(xsmaddadp, 1, float64, f64, MADD_FLGS, 1, 1)
2259 VSX_MADD(xsmaddmdp, 1, float64, f64, MADD_FLGS, 0, 1)
2260 VSX_MADD(xsmsubadp, 1, float64, f64, MSUB_FLGS, 1, 1)
2261 VSX_MADD(xsmsubmdp, 1, float64, f64, MSUB_FLGS, 0, 1)
2262 VSX_MADD(xsnmaddadp, 1, float64, f64, NMADD_FLGS, 1, 1)
2263 VSX_MADD(xsnmaddmdp, 1, float64, f64, NMADD_FLGS, 0, 1)
2264 VSX_MADD(xsnmsubadp, 1, float64, f64, NMSUB_FLGS, 1, 1)
2265 VSX_MADD(xsnmsubmdp, 1, float64, f64, NMSUB_FLGS, 0, 1)
2267 VSX_MADD(xvmaddadp, 2, float64, f64, MADD_FLGS, 1, 0)
2268 VSX_MADD(xvmaddmdp, 2, float64, f64, MADD_FLGS, 0, 0)
2269 VSX_MADD(xvmsubadp, 2, float64, f64, MSUB_FLGS, 1, 0)
2270 VSX_MADD(xvmsubmdp, 2, float64, f64, MSUB_FLGS, 0, 0)
2271 VSX_MADD(xvnmaddadp, 2, float64, f64, NMADD_FLGS, 1, 0)
2272 VSX_MADD(xvnmaddmdp, 2, float64, f64, NMADD_FLGS, 0, 0)
2273 VSX_MADD(xvnmsubadp, 2, float64, f64, NMSUB_FLGS, 1, 0)
2274 VSX_MADD(xvnmsubmdp, 2, float64, f64, NMSUB_FLGS, 0, 0)
2276 VSX_MADD(xvmaddasp, 4, float32, f32, MADD_FLGS, 1, 0)
2277 VSX_MADD(xvmaddmsp, 4, float32, f32, MADD_FLGS, 0, 0)
2278 VSX_MADD(xvmsubasp, 4, float32, f32, MSUB_FLGS, 1, 0)
2279 VSX_MADD(xvmsubmsp, 4, float32, f32, MSUB_FLGS, 0, 0)
2280 VSX_MADD(xvnmaddasp, 4, float32, f32, NMADD_FLGS, 1, 0)
2281 VSX_MADD(xvnmaddmsp, 4, float32, f32, NMADD_FLGS, 0, 0)
2282 VSX_MADD(xvnmsubasp, 4, float32, f32, NMSUB_FLGS, 1, 0)
2283 VSX_MADD(xvnmsubmsp, 4, float32, f32, NMSUB_FLGS, 0, 0)
2285 #define VSX_SCALAR_CMP(op, ordered) \
2286 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2288 ppc_vsr_t xa, xb; \
2289 uint32_t cc = 0; \
2291 getVSR(xA(opcode), &xa, env); \
2292 getVSR(xB(opcode), &xb, env); \
2294 if (unlikely(float64_is_any_nan(xa.f64[0]) || \
2295 float64_is_any_nan(xb.f64[0]))) { \
2296 if (float64_is_signaling_nan(xa.f64[0]) || \
2297 float64_is_signaling_nan(xb.f64[0])) { \
2298 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2300 if (ordered) { \
2301 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \
2303 cc = 1; \
2304 } else { \
2305 if (float64_lt(xa.f64[0], xb.f64[0], &env->fp_status)) { \
2306 cc = 8; \
2307 } else if (!float64_le(xa.f64[0], xb.f64[0], &env->fp_status)) { \
2308 cc = 4; \
2309 } else { \
2310 cc = 2; \
2314 env->fpscr &= ~(0x0F << FPSCR_FPRF); \
2315 env->fpscr |= cc << FPSCR_FPRF; \
2316 env->crf[BF(opcode)] = cc; \
2318 helper_float_check_status(env); \
2321 VSX_SCALAR_CMP(xscmpodp, 1)
2322 VSX_SCALAR_CMP(xscmpudp, 0)
2324 #define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ul)
2325 #define float32_snan_to_qnan(x) ((x) | 0x00400000)
2327 /* VSX_MAX_MIN - VSX floating point maximum/minimum
2328 * name - instruction mnemonic
2329 * op - operation (max or min)
2330 * nels - number of elements (1, 2 or 4)
2331 * tp - type (float32 or float64)
2332 * fld - vsr_t field (f32 or f64)
2334 #define VSX_MAX_MIN(name, op, nels, tp, fld) \
2335 void helper_##name(CPUPPCState *env, uint32_t opcode) \
2337 ppc_vsr_t xt, xa, xb; \
2338 int i; \
2340 getVSR(xA(opcode), &xa, env); \
2341 getVSR(xB(opcode), &xb, env); \
2342 getVSR(xT(opcode), &xt, env); \
2344 for (i = 0; i < nels; i++) { \
2345 xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &env->fp_status); \
2346 if (unlikely(tp##_is_signaling_nan(xa.fld[i]) || \
2347 tp##_is_signaling_nan(xb.fld[i]))) { \
2348 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2352 putVSR(xT(opcode), &xt, env); \
2353 helper_float_check_status(env); \
2356 VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, f64)
2357 VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, f64)
2358 VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, f32)
2359 VSX_MAX_MIN(xsmindp, minnum, 1, float64, f64)
2360 VSX_MAX_MIN(xvmindp, minnum, 2, float64, f64)
2361 VSX_MAX_MIN(xvminsp, minnum, 4, float32, f32)
2363 /* VSX_CMP - VSX floating point compare
2364 * op - instruction mnemonic
2365 * nels - number of elements (1, 2 or 4)
2366 * tp - type (float32 or float64)
2367 * fld - vsr_t field (f32 or f64)
2368 * cmp - comparison operation
2369 * svxvc - set VXVC bit
2371 #define VSX_CMP(op, nels, tp, fld, cmp, svxvc) \
2372 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2374 ppc_vsr_t xt, xa, xb; \
2375 int i; \
2376 int all_true = 1; \
2377 int all_false = 1; \
2379 getVSR(xA(opcode), &xa, env); \
2380 getVSR(xB(opcode), &xb, env); \
2381 getVSR(xT(opcode), &xt, env); \
2383 for (i = 0; i < nels; i++) { \
2384 if (unlikely(tp##_is_any_nan(xa.fld[i]) || \
2385 tp##_is_any_nan(xb.fld[i]))) { \
2386 if (tp##_is_signaling_nan(xa.fld[i]) || \
2387 tp##_is_signaling_nan(xb.fld[i])) { \
2388 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2390 if (svxvc) { \
2391 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXVC, 0); \
2393 xt.fld[i] = 0; \
2394 all_true = 0; \
2395 } else { \
2396 if (tp##_##cmp(xb.fld[i], xa.fld[i], &env->fp_status) == 1) { \
2397 xt.fld[i] = -1; \
2398 all_false = 0; \
2399 } else { \
2400 xt.fld[i] = 0; \
2401 all_true = 0; \
2406 putVSR(xT(opcode), &xt, env); \
2407 if ((opcode >> (31-21)) & 1) { \
2408 env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0); \
2410 helper_float_check_status(env); \
2413 VSX_CMP(xvcmpeqdp, 2, float64, f64, eq, 0)
2414 VSX_CMP(xvcmpgedp, 2, float64, f64, le, 1)
2415 VSX_CMP(xvcmpgtdp, 2, float64, f64, lt, 1)
2416 VSX_CMP(xvcmpeqsp, 4, float32, f32, eq, 0)
2417 VSX_CMP(xvcmpgesp, 4, float32, f32, le, 1)
2418 VSX_CMP(xvcmpgtsp, 4, float32, f32, lt, 1)
2420 #if defined(HOST_WORDS_BIGENDIAN)
2421 #define JOFFSET 0
2422 #else
2423 #define JOFFSET 1
2424 #endif
2426 /* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
2427 * op - instruction mnemonic
2428 * nels - number of elements (1, 2 or 4)
2429 * stp - source type (float32 or float64)
2430 * ttp - target type (float32 or float64)
2431 * sfld - source vsr_t field
2432 * tfld - target vsr_t field (f32 or f64)
2433 * sfprf - set FPRF
2435 #define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf) \
2436 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2438 ppc_vsr_t xt, xb; \
2439 int i; \
2441 getVSR(xB(opcode), &xb, env); \
2442 getVSR(xT(opcode), &xt, env); \
2444 for (i = 0; i < nels; i++) { \
2445 int j = 2*i + JOFFSET; \
2446 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
2447 if (unlikely(stp##_is_signaling_nan(xb.sfld))) { \
2448 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2449 xt.tfld = ttp##_snan_to_qnan(xt.tfld); \
2451 if (sfprf) { \
2452 helper_compute_fprf(env, ttp##_to_float64(xt.tfld, \
2453 &env->fp_status), sfprf); \
2457 putVSR(xT(opcode), &xt, env); \
2458 helper_float_check_status(env); \
2461 VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, f64[i], f32[j], 1)
2462 VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, f32[j], f64[i], 1)
2463 VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, f64[i], f32[j], 0)
2464 VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, f32[j], f64[i], 0)
2466 /* VSX_CVT_FP_TO_INT - VSX floating point to integer conversion
2467 * op - instruction mnemonic
2468 * nels - number of elements (1, 2 or 4)
2469 * stp - source type (float32 or float64)
2470 * ttp - target type (int32, uint32, int64 or uint64)
2471 * sfld - source vsr_t field
2472 * tfld - target vsr_t field
2473 * jdef - definition of the j index (i or 2*i)
2474 * rnan - resulting NaN
2476 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, jdef, rnan) \
2477 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2479 ppc_vsr_t xt, xb; \
2480 int i; \
2482 getVSR(xB(opcode), &xb, env); \
2483 getVSR(xT(opcode), &xt, env); \
2485 for (i = 0; i < nels; i++) { \
2486 int j = jdef; \
2487 if (unlikely(stp##_is_any_nan(xb.sfld))) { \
2488 if (stp##_is_signaling_nan(xb.sfld)) { \
2489 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2491 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
2492 xt.tfld = rnan; \
2493 } else { \
2494 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
2495 if (env->fp_status.float_exception_flags & float_flag_invalid) { \
2496 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0); \
2501 putVSR(xT(opcode), &xt, env); \
2502 helper_float_check_status(env); \
2505 VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, f64[j], u64[i], i, \
2506 0x8000000000000000ul)
2507 VSX_CVT_FP_TO_INT(xscvdpsxws, 1, float64, int32, f64[i], u32[j], \
2508 2*i + JOFFSET, 0x80000000l)
2509 VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, f64[j], u64[i], i, 0ul)
2510 VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, f64[i], u32[j], \
2511 2*i + JOFFSET, 0)
2512 VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, f64[j], u64[i], i, \
2513 0x8000000000000000ul)
2514 VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, f64[i], u32[j], \
2515 2*i + JOFFSET, 0x80000000l)
2516 VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, f64[j], u64[i], i, 0ul)
2517 VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, f64[i], u32[j], \
2518 2*i + JOFFSET, 0)
2519 VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, f32[j], u64[i], \
2520 2*i + JOFFSET, 0x8000000000000000ul)
2521 VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, f32[j], u32[j], i, \
2522 0x80000000l)
2523 VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, f32[j], u64[i], \
2524 2*i + JOFFSET, 0ul)
2525 VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, f32[j], u32[i], i, 0)
2527 /* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
2528 * op - instruction mnemonic
2529 * nels - number of elements (1, 2 or 4)
2530 * stp - source type (int32, uint32, int64 or uint64)
2531 * ttp - target type (float32 or float64)
2532 * sfld - source vsr_t field
2533 * tfld - target vsr_t field
2534 * jdef - definition of the j index (i or 2*i)
2535 * sfprf - set FPRF
2537 #define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, jdef, sfprf) \
2538 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2540 ppc_vsr_t xt, xb; \
2541 int i; \
2543 getVSR(xB(opcode), &xb, env); \
2544 getVSR(xT(opcode), &xt, env); \
2546 for (i = 0; i < nels; i++) { \
2547 int j = jdef; \
2548 xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status); \
2549 if (sfprf) { \
2550 helper_compute_fprf(env, xt.tfld, sfprf); \
2554 putVSR(xT(opcode), &xt, env); \
2555 helper_float_check_status(env); \
2558 VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, u64[j], f64[i], i, 1)
2559 VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, u64[j], f64[i], i, 1)
2560 VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, u64[j], f64[i], i, 0)
2561 VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, u64[j], f64[i], i, 0)
2562 VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, u32[j], f64[i], \
2563 2*i + JOFFSET, 0)
2564 VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, u32[j], f64[i], \
2565 2*i + JOFFSET, 0)
2566 VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, u64[i], f32[j], \
2567 2*i + JOFFSET, 0)
2568 VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, u64[i], f32[j], \
2569 2*i + JOFFSET, 0)
2570 VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, u32[j], f32[i], i, 0)
2571 VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, u32[j], f32[i], i, 0)
2573 /* For "use current rounding mode", define a value that will not be one of
2574 * the existing rounding model enums.
2576 #define FLOAT_ROUND_CURRENT (float_round_nearest_even + float_round_down + \
2577 float_round_up + float_round_to_zero)
2579 /* VSX_ROUND - VSX floating point round
2580 * op - instruction mnemonic
2581 * nels - number of elements (1, 2 or 4)
2582 * tp - type (float32 or float64)
2583 * fld - vsr_t field (f32 or f64)
2584 * rmode - rounding mode
2585 * sfprf - set FPRF
2587 #define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \
2588 void helper_##op(CPUPPCState *env, uint32_t opcode) \
2590 ppc_vsr_t xt, xb; \
2591 int i; \
2592 getVSR(xB(opcode), &xb, env); \
2593 getVSR(xT(opcode), &xt, env); \
2595 if (rmode != FLOAT_ROUND_CURRENT) { \
2596 set_float_rounding_mode(rmode, &env->fp_status); \
2599 for (i = 0; i < nels; i++) { \
2600 if (unlikely(tp##_is_signaling_nan(xb.fld[i]))) { \
2601 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
2602 xt.fld[i] = tp##_snan_to_qnan(xb.fld[i]); \
2603 } else { \
2604 xt.fld[i] = tp##_round_to_int(xb.fld[i], &env->fp_status); \
2606 if (sfprf) { \
2607 helper_compute_fprf(env, xt.fld[i], sfprf); \
2611 /* If this is not a "use current rounding mode" instruction, \
2612 * then inhibit setting of the XX bit and restore rounding \
2613 * mode from FPSCR */ \
2614 if (rmode != FLOAT_ROUND_CURRENT) { \
2615 fpscr_set_rounding_mode(env); \
2616 env->fp_status.float_exception_flags &= ~float_flag_inexact; \
2619 putVSR(xT(opcode), &xt, env); \
2620 helper_float_check_status(env); \
2623 VSX_ROUND(xsrdpi, 1, float64, f64, float_round_nearest_even, 1)
2624 VSX_ROUND(xsrdpic, 1, float64, f64, FLOAT_ROUND_CURRENT, 1)
2625 VSX_ROUND(xsrdpim, 1, float64, f64, float_round_down, 1)
2626 VSX_ROUND(xsrdpip, 1, float64, f64, float_round_up, 1)
2627 VSX_ROUND(xsrdpiz, 1, float64, f64, float_round_to_zero, 1)
2629 VSX_ROUND(xvrdpi, 2, float64, f64, float_round_nearest_even, 0)
2630 VSX_ROUND(xvrdpic, 2, float64, f64, FLOAT_ROUND_CURRENT, 0)
2631 VSX_ROUND(xvrdpim, 2, float64, f64, float_round_down, 0)
2632 VSX_ROUND(xvrdpip, 2, float64, f64, float_round_up, 0)
2633 VSX_ROUND(xvrdpiz, 2, float64, f64, float_round_to_zero, 0)
2635 VSX_ROUND(xvrspi, 4, float32, f32, float_round_nearest_even, 0)
2636 VSX_ROUND(xvrspic, 4, float32, f32, FLOAT_ROUND_CURRENT, 0)
2637 VSX_ROUND(xvrspim, 4, float32, f32, float_round_down, 0)
2638 VSX_ROUND(xvrspip, 4, float32, f32, float_round_up, 0)
2639 VSX_ROUND(xvrspiz, 4, float32, f32, float_round_to_zero, 0)