]> Git Repo - qemu.git/blob - target-ppc/op_helper.c
ppc: Fix coding style in op_helper.c
[qemu.git] / target-ppc / op_helper.c
1 /*
2  *  PowerPC emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <string.h>
20 #include "cpu.h"
21 #include "dyngen-exec.h"
22 #include "host-utils.h"
23 #include "helper.h"
24
25 #include "helper_regs.h"
26
27 #if !defined(CONFIG_USER_ONLY)
28 #include "softmmu_exec.h"
29 #endif /* !defined(CONFIG_USER_ONLY) */
30
31 //#define DEBUG_OP
32 //#define DEBUG_EXCEPTIONS
33 //#define DEBUG_SOFTWARE_TLB
34
35 #ifdef DEBUG_SOFTWARE_TLB
36 #  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
37 #else
38 #  define LOG_SWTLB(...) do { } while (0)
39 #endif
40
41
42 /*****************************************************************************/
43 /* Exceptions processing helpers */
44
45 void helper_raise_exception_err(uint32_t exception, uint32_t error_code)
46 {
47 #if 0
48     printf("Raise exception %3x code : %d\n", exception, error_code);
49 #endif
50     env->exception_index = exception;
51     env->error_code = error_code;
52     cpu_loop_exit(env);
53 }
54
55 void helper_raise_exception(uint32_t exception)
56 {
57     helper_raise_exception_err(exception, 0);
58 }
59
60 /*****************************************************************************/
61 /* SPR accesses */
62 void helper_load_dump_spr(uint32_t sprn)
63 {
64     qemu_log("Read SPR %d %03x => " TARGET_FMT_lx "\n", sprn, sprn,
65              env->spr[sprn]);
66 }
67
68 void helper_store_dump_spr(uint32_t sprn)
69 {
70     qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
71              env->spr[sprn]);
72 }
73
74 target_ulong helper_load_tbl(void)
75 {
76     return (target_ulong)cpu_ppc_load_tbl(env);
77 }
78
79 target_ulong helper_load_tbu(void)
80 {
81     return cpu_ppc_load_tbu(env);
82 }
83
84 target_ulong helper_load_atbl(void)
85 {
86     return (target_ulong)cpu_ppc_load_atbl(env);
87 }
88
89 target_ulong helper_load_atbu(void)
90 {
91     return cpu_ppc_load_atbu(env);
92 }
93
94 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
95 target_ulong helper_load_purr(void)
96 {
97     return (target_ulong)cpu_ppc_load_purr(env);
98 }
99 #endif
100
101 target_ulong helper_load_601_rtcl(void)
102 {
103     return cpu_ppc601_load_rtcl(env);
104 }
105
106 target_ulong helper_load_601_rtcu(void)
107 {
108     return cpu_ppc601_load_rtcu(env);
109 }
110
111 #if !defined(CONFIG_USER_ONLY)
112 #if defined(TARGET_PPC64)
113 void helper_store_asr(target_ulong val)
114 {
115     ppc_store_asr(env, val);
116 }
117 #endif
118
119 void helper_store_sdr1(target_ulong val)
120 {
121     ppc_store_sdr1(env, val);
122 }
123
124 void helper_store_tbl(target_ulong val)
125 {
126     cpu_ppc_store_tbl(env, val);
127 }
128
129 void helper_store_tbu(target_ulong val)
130 {
131     cpu_ppc_store_tbu(env, val);
132 }
133
134 void helper_store_atbl(target_ulong val)
135 {
136     cpu_ppc_store_atbl(env, val);
137 }
138
139 void helper_store_atbu(target_ulong val)
140 {
141     cpu_ppc_store_atbu(env, val);
142 }
143
144 void helper_store_601_rtcl(target_ulong val)
145 {
146     cpu_ppc601_store_rtcl(env, val);
147 }
148
149 void helper_store_601_rtcu(target_ulong val)
150 {
151     cpu_ppc601_store_rtcu(env, val);
152 }
153
154 target_ulong helper_load_decr(void)
155 {
156     return cpu_ppc_load_decr(env);
157 }
158
159 void helper_store_decr(target_ulong val)
160 {
161     cpu_ppc_store_decr(env, val);
162 }
163
164 void helper_store_hid0_601(target_ulong val)
165 {
166     target_ulong hid0;
167
168     hid0 = env->spr[SPR_HID0];
169     if ((val ^ hid0) & 0x00000008) {
170         /* Change current endianness */
171         env->hflags &= ~(1 << MSR_LE);
172         env->hflags_nmsr &= ~(1 << MSR_LE);
173         env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
174         env->hflags |= env->hflags_nmsr;
175         qemu_log("%s: set endianness to %c => " TARGET_FMT_lx "\n", __func__,
176                  val & 0x8 ? 'l' : 'b', env->hflags);
177     }
178     env->spr[SPR_HID0] = (uint32_t)val;
179 }
180
181 void helper_store_403_pbr(uint32_t num, target_ulong value)
182 {
183     if (likely(env->pb[num] != value)) {
184         env->pb[num] = value;
185         /* Should be optimized */
186         tlb_flush(env, 1);
187     }
188 }
189
190 target_ulong helper_load_40x_pit(void)
191 {
192     return load_40x_pit(env);
193 }
194
195 void helper_store_40x_pit(target_ulong val)
196 {
197     store_40x_pit(env, val);
198 }
199
200 void helper_store_40x_dbcr0(target_ulong val)
201 {
202     store_40x_dbcr0(env, val);
203 }
204
205 void helper_store_40x_sler(target_ulong val)
206 {
207     store_40x_sler(env, val);
208 }
209
210 void helper_store_booke_tcr(target_ulong val)
211 {
212     store_booke_tcr(env, val);
213 }
214
215 void helper_store_booke_tsr(target_ulong val)
216 {
217     store_booke_tsr(env, val);
218 }
219
220 void helper_store_ibatu(uint32_t nr, target_ulong val)
221 {
222     ppc_store_ibatu(env, nr, val);
223 }
224
225 void helper_store_ibatl(uint32_t nr, target_ulong val)
226 {
227     ppc_store_ibatl(env, nr, val);
228 }
229
230 void helper_store_dbatu(uint32_t nr, target_ulong val)
231 {
232     ppc_store_dbatu(env, nr, val);
233 }
234
235 void helper_store_dbatl(uint32_t nr, target_ulong val)
236 {
237     ppc_store_dbatl(env, nr, val);
238 }
239
240 void helper_store_601_batl(uint32_t nr, target_ulong val)
241 {
242     ppc_store_ibatl_601(env, nr, val);
243 }
244
245 void helper_store_601_batu(uint32_t nr, target_ulong val)
246 {
247     ppc_store_ibatu_601(env, nr, val);
248 }
249 #endif
250
251 /*****************************************************************************/
252 /* Memory load and stores */
253
254 static inline target_ulong addr_add(target_ulong addr, target_long arg)
255 {
256 #if defined(TARGET_PPC64)
257     if (!msr_sf) {
258         return (uint32_t)(addr + arg);
259     } else
260 #endif
261     {
262         return addr + arg;
263     }
264 }
265
266 void helper_lmw(target_ulong addr, uint32_t reg)
267 {
268     for (; reg < 32; reg++) {
269         if (msr_le) {
270             env->gpr[reg] = bswap32(ldl(addr));
271         } else {
272             env->gpr[reg] = ldl(addr);
273         }
274         addr = addr_add(addr, 4);
275     }
276 }
277
278 void helper_stmw(target_ulong addr, uint32_t reg)
279 {
280     for (; reg < 32; reg++) {
281         if (msr_le) {
282             stl(addr, bswap32((uint32_t)env->gpr[reg]));
283         } else {
284             stl(addr, (uint32_t)env->gpr[reg]);
285         }
286         addr = addr_add(addr, 4);
287     }
288 }
289
290 void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
291 {
292     int sh;
293
294     for (; nb > 3; nb -= 4) {
295         env->gpr[reg] = ldl(addr);
296         reg = (reg + 1) % 32;
297         addr = addr_add(addr, 4);
298     }
299     if (unlikely(nb > 0)) {
300         env->gpr[reg] = 0;
301         for (sh = 24; nb > 0; nb--, sh -= 8) {
302             env->gpr[reg] |= ldub(addr) << sh;
303             addr = addr_add(addr, 1);
304         }
305     }
306 }
307 /* PPC32 specification says we must generate an exception if
308  * rA is in the range of registers to be loaded.
309  * In an other hand, IBM says this is valid, but rA won't be loaded.
310  * For now, I'll follow the spec...
311  */
312 void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
313 {
314     if (likely(xer_bc != 0)) {
315         if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
316                      (reg < rb && (reg + xer_bc) > rb))) {
317             helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
318                                        POWERPC_EXCP_INVAL |
319                                        POWERPC_EXCP_INVAL_LSWX);
320         } else {
321             helper_lsw(addr, xer_bc, reg);
322         }
323     }
324 }
325
326 void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
327 {
328     int sh;
329
330     for (; nb > 3; nb -= 4) {
331         stl(addr, env->gpr[reg]);
332         reg = (reg + 1) % 32;
333         addr = addr_add(addr, 4);
334     }
335     if (unlikely(nb > 0)) {
336         for (sh = 24; nb > 0; nb--, sh -= 8) {
337             stb(addr, (env->gpr[reg] >> sh) & 0xFF);
338             addr = addr_add(addr, 1);
339         }
340     }
341 }
342
343 static void do_dcbz(target_ulong addr, int dcache_line_size)
344 {
345     int i;
346
347     addr &= ~(dcache_line_size - 1);
348     for (i = 0; i < dcache_line_size; i += 4) {
349         stl(addr + i, 0);
350     }
351     if (env->reserve_addr == addr) {
352         env->reserve_addr = (target_ulong)-1ULL;
353     }
354 }
355
356 void helper_dcbz(target_ulong addr)
357 {
358     do_dcbz(addr, env->dcache_line_size);
359 }
360
361 void helper_dcbz_970(target_ulong addr)
362 {
363     if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
364         do_dcbz(addr, 32);
365     } else {
366         do_dcbz(addr, env->dcache_line_size);
367     }
368 }
369
370 void helper_icbi(target_ulong addr)
371 {
372     addr &= ~(env->dcache_line_size - 1);
373     /* Invalidate one cache line :
374      * PowerPC specification says this is to be treated like a load
375      * (not a fetch) by the MMU. To be sure it will be so,
376      * do the load "by hand".
377      */
378     ldl(addr);
379 }
380
381 /* XXX: to be tested */
382 target_ulong helper_lscbx(target_ulong addr, uint32_t reg, uint32_t ra,
383                           uint32_t rb)
384 {
385     int i, c, d;
386
387     d = 24;
388     for (i = 0; i < xer_bc; i++) {
389         c = ldub(addr);
390         addr = addr_add(addr, 1);
391         /* ra (if not 0) and rb are never modified */
392         if (likely(reg != rb && (ra == 0 || reg != ra))) {
393             env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
394         }
395         if (unlikely(c == xer_cmp)) {
396             break;
397         }
398         if (likely(d != 0)) {
399             d -= 8;
400         } else {
401             d = 24;
402             reg++;
403             reg = reg & 0x1F;
404         }
405     }
406     return i;
407 }
408
409 /*****************************************************************************/
410 /* Fixed point operations helpers */
411 #if defined(TARGET_PPC64)
412
413 /* multiply high word */
414 uint64_t helper_mulhd(uint64_t arg1, uint64_t arg2)
415 {
416     uint64_t tl, th;
417
418     muls64(&tl, &th, arg1, arg2);
419     return th;
420 }
421
422 /* multiply high word unsigned */
423 uint64_t helper_mulhdu(uint64_t arg1, uint64_t arg2)
424 {
425     uint64_t tl, th;
426
427     mulu64(&tl, &th, arg1, arg2);
428     return th;
429 }
430
431 uint64_t helper_mulldo(uint64_t arg1, uint64_t arg2)
432 {
433     int64_t th;
434     uint64_t tl;
435
436     muls64(&tl, (uint64_t *)&th, arg1, arg2);
437     /* If th != 0 && th != -1, then we had an overflow */
438     if (likely((uint64_t)(th + 1) <= 1)) {
439         env->xer &= ~(1 << XER_OV);
440     } else {
441         env->xer |= (1 << XER_OV) | (1 << XER_SO);
442     }
443     return (int64_t)tl;
444 }
445 #endif
446
447 target_ulong helper_cntlzw(target_ulong t)
448 {
449     return clz32(t);
450 }
451
452 #if defined(TARGET_PPC64)
453 target_ulong helper_cntlzd(target_ulong t)
454 {
455     return clz64(t);
456 }
457 #endif
458
459 /* shift right arithmetic helper */
460 target_ulong helper_sraw(target_ulong value, target_ulong shift)
461 {
462     int32_t ret;
463
464     if (likely(!(shift & 0x20))) {
465         if (likely((uint32_t)shift != 0)) {
466             shift &= 0x1f;
467             ret = (int32_t)value >> shift;
468             if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
469                 env->xer &= ~(1 << XER_CA);
470             } else {
471                 env->xer |= (1 << XER_CA);
472             }
473         } else {
474             ret = (int32_t)value;
475             env->xer &= ~(1 << XER_CA);
476         }
477     } else {
478         ret = (int32_t)value >> 31;
479         if (ret) {
480             env->xer |= (1 << XER_CA);
481         } else {
482             env->xer &= ~(1 << XER_CA);
483         }
484     }
485     return (target_long)ret;
486 }
487
488 #if defined(TARGET_PPC64)
489 target_ulong helper_srad(target_ulong value, target_ulong shift)
490 {
491     int64_t ret;
492
493     if (likely(!(shift & 0x40))) {
494         if (likely((uint64_t)shift != 0)) {
495             shift &= 0x3f;
496             ret = (int64_t)value >> shift;
497             if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
498                 env->xer &= ~(1 << XER_CA);
499             } else {
500                 env->xer |= (1 << XER_CA);
501             }
502         } else {
503             ret = (int64_t)value;
504             env->xer &= ~(1 << XER_CA);
505         }
506     } else {
507         ret = (int64_t)value >> 63;
508         if (ret) {
509             env->xer |= (1 << XER_CA);
510         } else {
511             env->xer &= ~(1 << XER_CA);
512         }
513     }
514     return ret;
515 }
516 #endif
517
518 #if defined(TARGET_PPC64)
519 target_ulong helper_popcntb(target_ulong val)
520 {
521     val = (val & 0x5555555555555555ULL) + ((val >>  1) &
522                                            0x5555555555555555ULL);
523     val = (val & 0x3333333333333333ULL) + ((val >>  2) &
524                                            0x3333333333333333ULL);
525     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
526                                            0x0f0f0f0f0f0f0f0fULL);
527     return val;
528 }
529
530 target_ulong helper_popcntw(target_ulong val)
531 {
532     val = (val & 0x5555555555555555ULL) + ((val >>  1) &
533                                            0x5555555555555555ULL);
534     val = (val & 0x3333333333333333ULL) + ((val >>  2) &
535                                            0x3333333333333333ULL);
536     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
537                                            0x0f0f0f0f0f0f0f0fULL);
538     val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
539                                            0x00ff00ff00ff00ffULL);
540     val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
541                                            0x0000ffff0000ffffULL);
542     return val;
543 }
544
545 target_ulong helper_popcntd(target_ulong val)
546 {
547     return ctpop64(val);
548 }
549 #else
550 target_ulong helper_popcntb(target_ulong val)
551 {
552     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
553     val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
554     val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
555     return val;
556 }
557
558 target_ulong helper_popcntw(target_ulong val)
559 {
560     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
561     val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
562     val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
563     val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
564     val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
565     return val;
566 }
567 #endif
568
569 /*****************************************************************************/
570 /* Floating point operations helpers */
571 uint64_t helper_float32_to_float64(uint32_t arg)
572 {
573     CPU_FloatU f;
574     CPU_DoubleU d;
575
576     f.l = arg;
577     d.d = float32_to_float64(f.f, &env->fp_status);
578     return d.ll;
579 }
580
581 uint32_t helper_float64_to_float32(uint64_t arg)
582 {
583     CPU_FloatU f;
584     CPU_DoubleU d;
585
586     d.ll = arg;
587     f.f = float64_to_float32(d.d, &env->fp_status);
588     return f.l;
589 }
590
591 static inline int isden(float64 d)
592 {
593     CPU_DoubleU u;
594
595     u.d = d;
596
597     return ((u.ll >> 52) & 0x7FF) == 0;
598 }
599
600 uint32_t helper_compute_fprf(uint64_t arg, uint32_t set_fprf)
601 {
602     CPU_DoubleU farg;
603     int isneg;
604     int ret;
605
606     farg.ll = arg;
607     isneg = float64_is_neg(farg.d);
608     if (unlikely(float64_is_any_nan(farg.d))) {
609         if (float64_is_signaling_nan(farg.d)) {
610             /* Signaling NaN: flags are undefined */
611             ret = 0x00;
612         } else {
613             /* Quiet NaN */
614             ret = 0x11;
615         }
616     } else if (unlikely(float64_is_infinity(farg.d))) {
617         /* +/- infinity */
618         if (isneg) {
619             ret = 0x09;
620         } else {
621             ret = 0x05;
622         }
623     } else {
624         if (float64_is_zero(farg.d)) {
625             /* +/- zero */
626             if (isneg) {
627                 ret = 0x12;
628             } else {
629                 ret = 0x02;
630             }
631         } else {
632             if (isden(farg.d)) {
633                 /* Denormalized numbers */
634                 ret = 0x10;
635             } else {
636                 /* Normalized numbers */
637                 ret = 0x00;
638             }
639             if (isneg) {
640                 ret |= 0x08;
641             } else {
642                 ret |= 0x04;
643             }
644         }
645     }
646     if (set_fprf) {
647         /* We update FPSCR_FPRF */
648         env->fpscr &= ~(0x1F << FPSCR_FPRF);
649         env->fpscr |= ret << FPSCR_FPRF;
650     }
651     /* We just need fpcc to update Rc1 */
652     return ret & 0xF;
653 }
654
655 /* Floating-point invalid operations exception */
656 static inline uint64_t fload_invalid_op_excp(int op)
657 {
658     uint64_t ret = 0;
659     int ve;
660
661     ve = fpscr_ve;
662     switch (op) {
663     case POWERPC_EXCP_FP_VXSNAN:
664         env->fpscr |= 1 << FPSCR_VXSNAN;
665         break;
666     case POWERPC_EXCP_FP_VXSOFT:
667         env->fpscr |= 1 << FPSCR_VXSOFT;
668         break;
669     case POWERPC_EXCP_FP_VXISI:
670         /* Magnitude subtraction of infinities */
671         env->fpscr |= 1 << FPSCR_VXISI;
672         goto update_arith;
673     case POWERPC_EXCP_FP_VXIDI:
674         /* Division of infinity by infinity */
675         env->fpscr |= 1 << FPSCR_VXIDI;
676         goto update_arith;
677     case POWERPC_EXCP_FP_VXZDZ:
678         /* Division of zero by zero */
679         env->fpscr |= 1 << FPSCR_VXZDZ;
680         goto update_arith;
681     case POWERPC_EXCP_FP_VXIMZ:
682         /* Multiplication of zero by infinity */
683         env->fpscr |= 1 << FPSCR_VXIMZ;
684         goto update_arith;
685     case POWERPC_EXCP_FP_VXVC:
686         /* Ordered comparison of NaN */
687         env->fpscr |= 1 << FPSCR_VXVC;
688         env->fpscr &= ~(0xF << FPSCR_FPCC);
689         env->fpscr |= 0x11 << FPSCR_FPCC;
690         /* We must update the target FPR before raising the exception */
691         if (ve != 0) {
692             env->exception_index = POWERPC_EXCP_PROGRAM;
693             env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
694             /* Update the floating-point enabled exception summary */
695             env->fpscr |= 1 << FPSCR_FEX;
696             /* Exception is differed */
697             ve = 0;
698         }
699         break;
700     case POWERPC_EXCP_FP_VXSQRT:
701         /* Square root of a negative number */
702         env->fpscr |= 1 << FPSCR_VXSQRT;
703     update_arith:
704         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
705         if (ve == 0) {
706             /* Set the result to quiet NaN */
707             ret = 0x7FF8000000000000ULL;
708             env->fpscr &= ~(0xF << FPSCR_FPCC);
709             env->fpscr |= 0x11 << FPSCR_FPCC;
710         }
711         break;
712     case POWERPC_EXCP_FP_VXCVI:
713         /* Invalid conversion */
714         env->fpscr |= 1 << FPSCR_VXCVI;
715         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
716         if (ve == 0) {
717             /* Set the result to quiet NaN */
718             ret = 0x7FF8000000000000ULL;
719             env->fpscr &= ~(0xF << FPSCR_FPCC);
720             env->fpscr |= 0x11 << FPSCR_FPCC;
721         }
722         break;
723     }
724     /* Update the floating-point invalid operation summary */
725     env->fpscr |= 1 << FPSCR_VX;
726     /* Update the floating-point exception summary */
727     env->fpscr |= 1 << FPSCR_FX;
728     if (ve != 0) {
729         /* Update the floating-point enabled exception summary */
730         env->fpscr |= 1 << FPSCR_FEX;
731         if (msr_fe0 != 0 || msr_fe1 != 0) {
732             helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
733                                        POWERPC_EXCP_FP | op);
734         }
735     }
736     return ret;
737 }
738
739 static inline void float_zero_divide_excp(void)
740 {
741     env->fpscr |= 1 << FPSCR_ZX;
742     env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
743     /* Update the floating-point exception summary */
744     env->fpscr |= 1 << FPSCR_FX;
745     if (fpscr_ze != 0) {
746         /* Update the floating-point enabled exception summary */
747         env->fpscr |= 1 << FPSCR_FEX;
748         if (msr_fe0 != 0 || msr_fe1 != 0) {
749             helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
750                                        POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
751         }
752     }
753 }
754
755 static inline void float_overflow_excp(void)
756 {
757     env->fpscr |= 1 << FPSCR_OX;
758     /* Update the floating-point exception summary */
759     env->fpscr |= 1 << FPSCR_FX;
760     if (fpscr_oe != 0) {
761         /* XXX: should adjust the result */
762         /* Update the floating-point enabled exception summary */
763         env->fpscr |= 1 << FPSCR_FEX;
764         /* We must update the target FPR before raising the exception */
765         env->exception_index = POWERPC_EXCP_PROGRAM;
766         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
767     } else {
768         env->fpscr |= 1 << FPSCR_XX;
769         env->fpscr |= 1 << FPSCR_FI;
770     }
771 }
772
773 static inline void float_underflow_excp(void)
774 {
775     env->fpscr |= 1 << FPSCR_UX;
776     /* Update the floating-point exception summary */
777     env->fpscr |= 1 << FPSCR_FX;
778     if (fpscr_ue != 0) {
779         /* XXX: should adjust the result */
780         /* Update the floating-point enabled exception summary */
781         env->fpscr |= 1 << FPSCR_FEX;
782         /* We must update the target FPR before raising the exception */
783         env->exception_index = POWERPC_EXCP_PROGRAM;
784         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
785     }
786 }
787
788 static inline void float_inexact_excp(void)
789 {
790     env->fpscr |= 1 << FPSCR_XX;
791     /* Update the floating-point exception summary */
792     env->fpscr |= 1 << FPSCR_FX;
793     if (fpscr_xe != 0) {
794         /* Update the floating-point enabled exception summary */
795         env->fpscr |= 1 << FPSCR_FEX;
796         /* We must update the target FPR before raising the exception */
797         env->exception_index = POWERPC_EXCP_PROGRAM;
798         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
799     }
800 }
801
802 static inline void fpscr_set_rounding_mode(void)
803 {
804     int rnd_type;
805
806     /* Set rounding mode */
807     switch (fpscr_rn) {
808     case 0:
809         /* Best approximation (round to nearest) */
810         rnd_type = float_round_nearest_even;
811         break;
812     case 1:
813         /* Smaller magnitude (round toward zero) */
814         rnd_type = float_round_to_zero;
815         break;
816     case 2:
817         /* Round toward +infinite */
818         rnd_type = float_round_up;
819         break;
820     default:
821     case 3:
822         /* Round toward -infinite */
823         rnd_type = float_round_down;
824         break;
825     }
826     set_float_rounding_mode(rnd_type, &env->fp_status);
827 }
828
829 void helper_fpscr_clrbit(uint32_t bit)
830 {
831     int prev;
832
833     prev = (env->fpscr >> bit) & 1;
834     env->fpscr &= ~(1 << bit);
835     if (prev == 1) {
836         switch (bit) {
837         case FPSCR_RN1:
838         case FPSCR_RN:
839             fpscr_set_rounding_mode();
840             break;
841         default:
842             break;
843         }
844     }
845 }
846
847 void helper_fpscr_setbit(uint32_t bit)
848 {
849     int prev;
850
851     prev = (env->fpscr >> bit) & 1;
852     env->fpscr |= 1 << bit;
853     if (prev == 0) {
854         switch (bit) {
855         case FPSCR_VX:
856             env->fpscr |= 1 << FPSCR_FX;
857             if (fpscr_ve) {
858                 goto raise_ve;
859             }
860         case FPSCR_OX:
861             env->fpscr |= 1 << FPSCR_FX;
862             if (fpscr_oe) {
863                 goto raise_oe;
864             }
865             break;
866         case FPSCR_UX:
867             env->fpscr |= 1 << FPSCR_FX;
868             if (fpscr_ue) {
869                 goto raise_ue;
870             }
871             break;
872         case FPSCR_ZX:
873             env->fpscr |= 1 << FPSCR_FX;
874             if (fpscr_ze) {
875                 goto raise_ze;
876             }
877             break;
878         case FPSCR_XX:
879             env->fpscr |= 1 << FPSCR_FX;
880             if (fpscr_xe) {
881                 goto raise_xe;
882             }
883             break;
884         case FPSCR_VXSNAN:
885         case FPSCR_VXISI:
886         case FPSCR_VXIDI:
887         case FPSCR_VXZDZ:
888         case FPSCR_VXIMZ:
889         case FPSCR_VXVC:
890         case FPSCR_VXSOFT:
891         case FPSCR_VXSQRT:
892         case FPSCR_VXCVI:
893             env->fpscr |= 1 << FPSCR_VX;
894             env->fpscr |= 1 << FPSCR_FX;
895             if (fpscr_ve != 0) {
896                 goto raise_ve;
897             }
898             break;
899         case FPSCR_VE:
900             if (fpscr_vx != 0) {
901             raise_ve:
902                 env->error_code = POWERPC_EXCP_FP;
903                 if (fpscr_vxsnan) {
904                     env->error_code |= POWERPC_EXCP_FP_VXSNAN;
905                 }
906                 if (fpscr_vxisi) {
907                     env->error_code |= POWERPC_EXCP_FP_VXISI;
908                 }
909                 if (fpscr_vxidi) {
910                     env->error_code |= POWERPC_EXCP_FP_VXIDI;
911                 }
912                 if (fpscr_vxzdz) {
913                     env->error_code |= POWERPC_EXCP_FP_VXZDZ;
914                 }
915                 if (fpscr_vximz) {
916                     env->error_code |= POWERPC_EXCP_FP_VXIMZ;
917                 }
918                 if (fpscr_vxvc) {
919                     env->error_code |= POWERPC_EXCP_FP_VXVC;
920                 }
921                 if (fpscr_vxsoft) {
922                     env->error_code |= POWERPC_EXCP_FP_VXSOFT;
923                 }
924                 if (fpscr_vxsqrt) {
925                     env->error_code |= POWERPC_EXCP_FP_VXSQRT;
926                 }
927                 if (fpscr_vxcvi) {
928                     env->error_code |= POWERPC_EXCP_FP_VXCVI;
929                 }
930                 goto raise_excp;
931             }
932             break;
933         case FPSCR_OE:
934             if (fpscr_ox != 0) {
935             raise_oe:
936                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
937                 goto raise_excp;
938             }
939             break;
940         case FPSCR_UE:
941             if (fpscr_ux != 0) {
942             raise_ue:
943                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
944                 goto raise_excp;
945             }
946             break;
947         case FPSCR_ZE:
948             if (fpscr_zx != 0) {
949             raise_ze:
950                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
951                 goto raise_excp;
952             }
953             break;
954         case FPSCR_XE:
955             if (fpscr_xx != 0) {
956             raise_xe:
957                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
958                 goto raise_excp;
959             }
960             break;
961         case FPSCR_RN1:
962         case FPSCR_RN:
963             fpscr_set_rounding_mode();
964             break;
965         default:
966             break;
967         raise_excp:
968             /* Update the floating-point enabled exception summary */
969             env->fpscr |= 1 << FPSCR_FEX;
970             /* We have to update Rc1 before raising the exception */
971             env->exception_index = POWERPC_EXCP_PROGRAM;
972             break;
973         }
974     }
975 }
976
977 void helper_store_fpscr(uint64_t arg, uint32_t mask)
978 {
979     /*
980      * We use only the 32 LSB of the incoming fpr
981      */
982     uint32_t prev, new;
983     int i;
984
985     prev = env->fpscr;
986     new = (uint32_t)arg;
987     new &= ~0x60000000;
988     new |= prev & 0x60000000;
989     for (i = 0; i < 8; i++) {
990         if (mask & (1 << i)) {
991             env->fpscr &= ~(0xF << (4 * i));
992             env->fpscr |= new & (0xF << (4 * i));
993         }
994     }
995     /* Update VX and FEX */
996     if (fpscr_ix != 0) {
997         env->fpscr |= 1 << FPSCR_VX;
998     } else {
999         env->fpscr &= ~(1 << FPSCR_VX);
1000     }
1001     if ((fpscr_ex & fpscr_eex) != 0) {
1002         env->fpscr |= 1 << FPSCR_FEX;
1003         env->exception_index = POWERPC_EXCP_PROGRAM;
1004         /* XXX: we should compute it properly */
1005         env->error_code = POWERPC_EXCP_FP;
1006     } else {
1007         env->fpscr &= ~(1 << FPSCR_FEX);
1008     }
1009     fpscr_set_rounding_mode();
1010 }
1011
1012 void helper_float_check_status(void)
1013 {
1014     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
1015         (env->error_code & POWERPC_EXCP_FP)) {
1016         /* Differred floating-point exception after target FPR update */
1017         if (msr_fe0 != 0 || msr_fe1 != 0) {
1018             helper_raise_exception_err(env->exception_index, env->error_code);
1019         }
1020     } else {
1021         int status = get_float_exception_flags(&env->fp_status);
1022         if (status & float_flag_divbyzero) {
1023             float_zero_divide_excp();
1024         } else if (status & float_flag_overflow) {
1025             float_overflow_excp();
1026         } else if (status & float_flag_underflow) {
1027             float_underflow_excp();
1028         } else if (status & float_flag_inexact) {
1029             float_inexact_excp();
1030         }
1031     }
1032 }
1033
1034 void helper_reset_fpstatus(void)
1035 {
1036     set_float_exception_flags(0, &env->fp_status);
1037 }
1038
1039 /* fadd - fadd. */
1040 uint64_t helper_fadd(uint64_t arg1, uint64_t arg2)
1041 {
1042     CPU_DoubleU farg1, farg2;
1043
1044     farg1.ll = arg1;
1045     farg2.ll = arg2;
1046
1047     if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1048                  float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
1049         /* Magnitude subtraction of infinities */
1050         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1051     } else {
1052         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1053                      float64_is_signaling_nan(farg2.d))) {
1054             /* sNaN addition */
1055             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1056         }
1057         farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1058     }
1059
1060     return farg1.ll;
1061 }
1062
1063 /* fsub - fsub. */
1064 uint64_t helper_fsub(uint64_t arg1, uint64_t arg2)
1065 {
1066     CPU_DoubleU farg1, farg2;
1067
1068     farg1.ll = arg1;
1069     farg2.ll = arg2;
1070
1071     if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1072                  float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1073         /* Magnitude subtraction of infinities */
1074         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1075     } else {
1076         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1077                      float64_is_signaling_nan(farg2.d))) {
1078             /* sNaN subtraction */
1079             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1080         }
1081         farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1082     }
1083
1084     return farg1.ll;
1085 }
1086
1087 /* fmul - fmul. */
1088 uint64_t helper_fmul(uint64_t arg1, uint64_t arg2)
1089 {
1090     CPU_DoubleU farg1, farg2;
1091
1092     farg1.ll = arg1;
1093     farg2.ll = arg2;
1094
1095     if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1096                  (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1097         /* Multiplication of zero by infinity */
1098         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1099     } else {
1100         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1101                      float64_is_signaling_nan(farg2.d))) {
1102             /* sNaN multiplication */
1103             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1104         }
1105         farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1106     }
1107
1108     return farg1.ll;
1109 }
1110
1111 /* fdiv - fdiv. */
1112 uint64_t helper_fdiv(uint64_t arg1, uint64_t arg2)
1113 {
1114     CPU_DoubleU farg1, farg2;
1115
1116     farg1.ll = arg1;
1117     farg2.ll = arg2;
1118
1119     if (unlikely(float64_is_infinity(farg1.d) &&
1120                  float64_is_infinity(farg2.d))) {
1121         /* Division of infinity by infinity */
1122         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1123     } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
1124         /* Division of zero by zero */
1125         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1126     } else {
1127         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1128                      float64_is_signaling_nan(farg2.d))) {
1129             /* sNaN division */
1130             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1131         }
1132         farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1133     }
1134
1135     return farg1.ll;
1136 }
1137
1138 /* fabs */
1139 uint64_t helper_fabs(uint64_t arg)
1140 {
1141     CPU_DoubleU farg;
1142
1143     farg.ll = arg;
1144     farg.d = float64_abs(farg.d);
1145     return farg.ll;
1146 }
1147
1148 /* fnabs */
1149 uint64_t helper_fnabs(uint64_t arg)
1150 {
1151     CPU_DoubleU farg;
1152
1153     farg.ll = arg;
1154     farg.d = float64_abs(farg.d);
1155     farg.d = float64_chs(farg.d);
1156     return farg.ll;
1157 }
1158
1159 /* fneg */
1160 uint64_t helper_fneg(uint64_t arg)
1161 {
1162     CPU_DoubleU farg;
1163
1164     farg.ll = arg;
1165     farg.d = float64_chs(farg.d);
1166     return farg.ll;
1167 }
1168
1169 /* fctiw - fctiw. */
1170 uint64_t helper_fctiw(uint64_t arg)
1171 {
1172     CPU_DoubleU farg;
1173
1174     farg.ll = arg;
1175
1176     if (unlikely(float64_is_signaling_nan(farg.d))) {
1177         /* sNaN conversion */
1178         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1179                                         POWERPC_EXCP_FP_VXCVI);
1180     } else if (unlikely(float64_is_quiet_nan(farg.d) ||
1181                         float64_is_infinity(farg.d))) {
1182         /* qNan / infinity conversion */
1183         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1184     } else {
1185         farg.ll = float64_to_int32(farg.d, &env->fp_status);
1186         /* XXX: higher bits are not supposed to be significant.
1187          *     to make tests easier, return the same as a real PowerPC 750
1188          */
1189         farg.ll |= 0xFFF80000ULL << 32;
1190     }
1191     return farg.ll;
1192 }
1193
1194 /* fctiwz - fctiwz. */
1195 uint64_t helper_fctiwz(uint64_t arg)
1196 {
1197     CPU_DoubleU farg;
1198
1199     farg.ll = arg;
1200
1201     if (unlikely(float64_is_signaling_nan(farg.d))) {
1202         /* sNaN conversion */
1203         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1204                                         POWERPC_EXCP_FP_VXCVI);
1205     } else if (unlikely(float64_is_quiet_nan(farg.d) ||
1206                         float64_is_infinity(farg.d))) {
1207         /* qNan / infinity conversion */
1208         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1209     } else {
1210         farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1211         /* XXX: higher bits are not supposed to be significant.
1212          *     to make tests easier, return the same as a real PowerPC 750
1213          */
1214         farg.ll |= 0xFFF80000ULL << 32;
1215     }
1216     return farg.ll;
1217 }
1218
1219 #if defined(TARGET_PPC64)
1220 /* fcfid - fcfid. */
1221 uint64_t helper_fcfid(uint64_t arg)
1222 {
1223     CPU_DoubleU farg;
1224
1225     farg.d = int64_to_float64(arg, &env->fp_status);
1226     return farg.ll;
1227 }
1228
1229 /* fctid - fctid. */
1230 uint64_t helper_fctid(uint64_t arg)
1231 {
1232     CPU_DoubleU farg;
1233
1234     farg.ll = arg;
1235
1236     if (unlikely(float64_is_signaling_nan(farg.d))) {
1237         /* sNaN conversion */
1238         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1239                                         POWERPC_EXCP_FP_VXCVI);
1240     } else if (unlikely(float64_is_quiet_nan(farg.d) ||
1241                         float64_is_infinity(farg.d))) {
1242         /* qNan / infinity conversion */
1243         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1244     } else {
1245         farg.ll = float64_to_int64(farg.d, &env->fp_status);
1246     }
1247     return farg.ll;
1248 }
1249
1250 /* fctidz - fctidz. */
1251 uint64_t helper_fctidz(uint64_t arg)
1252 {
1253     CPU_DoubleU farg;
1254
1255     farg.ll = arg;
1256
1257     if (unlikely(float64_is_signaling_nan(farg.d))) {
1258         /* sNaN conversion */
1259         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1260                                         POWERPC_EXCP_FP_VXCVI);
1261     } else if (unlikely(float64_is_quiet_nan(farg.d) ||
1262                         float64_is_infinity(farg.d))) {
1263         /* qNan / infinity conversion */
1264         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1265     } else {
1266         farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1267     }
1268     return farg.ll;
1269 }
1270
1271 #endif
1272
1273 static inline uint64_t do_fri(uint64_t arg, int rounding_mode)
1274 {
1275     CPU_DoubleU farg;
1276
1277     farg.ll = arg;
1278
1279     if (unlikely(float64_is_signaling_nan(farg.d))) {
1280         /* sNaN round */
1281         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1282                                         POWERPC_EXCP_FP_VXCVI);
1283     } else if (unlikely(float64_is_quiet_nan(farg.d) ||
1284                         float64_is_infinity(farg.d))) {
1285         /* qNan / infinity round */
1286         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1287     } else {
1288         set_float_rounding_mode(rounding_mode, &env->fp_status);
1289         farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1290         /* Restore rounding mode from FPSCR */
1291         fpscr_set_rounding_mode();
1292     }
1293     return farg.ll;
1294 }
1295
1296 uint64_t helper_frin(uint64_t arg)
1297 {
1298     return do_fri(arg, float_round_nearest_even);
1299 }
1300
1301 uint64_t helper_friz(uint64_t arg)
1302 {
1303     return do_fri(arg, float_round_to_zero);
1304 }
1305
1306 uint64_t helper_frip(uint64_t arg)
1307 {
1308     return do_fri(arg, float_round_up);
1309 }
1310
1311 uint64_t helper_frim(uint64_t arg)
1312 {
1313     return do_fri(arg, float_round_down);
1314 }
1315
1316 /* fmadd - fmadd. */
1317 uint64_t helper_fmadd(uint64_t arg1, uint64_t arg2, uint64_t arg3)
1318 {
1319     CPU_DoubleU farg1, farg2, farg3;
1320
1321     farg1.ll = arg1;
1322     farg2.ll = arg2;
1323     farg3.ll = arg3;
1324
1325     if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1326                  (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1327         /* Multiplication of zero by infinity */
1328         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1329     } else {
1330         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1331                      float64_is_signaling_nan(farg2.d) ||
1332                      float64_is_signaling_nan(farg3.d))) {
1333             /* sNaN operation */
1334             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1335         }
1336         /* This is the way the PowerPC specification defines it */
1337         float128 ft0_128, ft1_128;
1338
1339         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1340         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1341         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1342         if (unlikely(float128_is_infinity(ft0_128) &&
1343                      float64_is_infinity(farg3.d) &&
1344                      float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1345             /* Magnitude subtraction of infinities */
1346             farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1347         } else {
1348             ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1349             ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1350             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1351         }
1352     }
1353
1354     return farg1.ll;
1355 }
1356
1357 /* fmsub - fmsub. */
1358 uint64_t helper_fmsub(uint64_t arg1, uint64_t arg2, uint64_t arg3)
1359 {
1360     CPU_DoubleU farg1, farg2, farg3;
1361
1362     farg1.ll = arg1;
1363     farg2.ll = arg2;
1364     farg3.ll = arg3;
1365
1366     if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1367                  (float64_is_zero(farg1.d) &&
1368                   float64_is_infinity(farg2.d)))) {
1369         /* Multiplication of zero by infinity */
1370         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1371     } else {
1372         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1373                      float64_is_signaling_nan(farg2.d) ||
1374                      float64_is_signaling_nan(farg3.d))) {
1375             /* sNaN operation */
1376             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1377         }
1378         /* This is the way the PowerPC specification defines it */
1379         float128 ft0_128, ft1_128;
1380
1381         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1382         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1383         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1384         if (unlikely(float128_is_infinity(ft0_128) &&
1385                      float64_is_infinity(farg3.d) &&
1386                      float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1387             /* Magnitude subtraction of infinities */
1388             farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1389         } else {
1390             ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1391             ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1392             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1393         }
1394     }
1395     return farg1.ll;
1396 }
1397
1398 /* fnmadd - fnmadd. */
1399 uint64_t helper_fnmadd(uint64_t arg1, uint64_t arg2, uint64_t arg3)
1400 {
1401     CPU_DoubleU farg1, farg2, farg3;
1402
1403     farg1.ll = arg1;
1404     farg2.ll = arg2;
1405     farg3.ll = arg3;
1406
1407     if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1408                  (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1409         /* Multiplication of zero by infinity */
1410         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1411     } else {
1412         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1413                      float64_is_signaling_nan(farg2.d) ||
1414                      float64_is_signaling_nan(farg3.d))) {
1415             /* sNaN operation */
1416             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1417         }
1418         /* This is the way the PowerPC specification defines it */
1419         float128 ft0_128, ft1_128;
1420
1421         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1422         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1423         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1424         if (unlikely(float128_is_infinity(ft0_128) &&
1425                      float64_is_infinity(farg3.d) &&
1426                      float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1427             /* Magnitude subtraction of infinities */
1428             farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1429         } else {
1430             ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1431             ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1432             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1433         }
1434         if (likely(!float64_is_any_nan(farg1.d))) {
1435             farg1.d = float64_chs(farg1.d);
1436         }
1437     }
1438     return farg1.ll;
1439 }
1440
1441 /* fnmsub - fnmsub. */
1442 uint64_t helper_fnmsub(uint64_t arg1, uint64_t arg2, uint64_t arg3)
1443 {
1444     CPU_DoubleU farg1, farg2, farg3;
1445
1446     farg1.ll = arg1;
1447     farg2.ll = arg2;
1448     farg3.ll = arg3;
1449
1450     if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1451                  (float64_is_zero(farg1.d) &&
1452                   float64_is_infinity(farg2.d)))) {
1453         /* Multiplication of zero by infinity */
1454         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1455     } else {
1456         if (unlikely(float64_is_signaling_nan(farg1.d) ||
1457                      float64_is_signaling_nan(farg2.d) ||
1458                      float64_is_signaling_nan(farg3.d))) {
1459             /* sNaN operation */
1460             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1461         }
1462         /* This is the way the PowerPC specification defines it */
1463         float128 ft0_128, ft1_128;
1464
1465         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1466         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1467         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1468         if (unlikely(float128_is_infinity(ft0_128) &&
1469                      float64_is_infinity(farg3.d) &&
1470                      float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1471             /* Magnitude subtraction of infinities */
1472             farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1473         } else {
1474             ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1475             ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1476             farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1477         }
1478         if (likely(!float64_is_any_nan(farg1.d))) {
1479             farg1.d = float64_chs(farg1.d);
1480         }
1481     }
1482     return farg1.ll;
1483 }
1484
1485 /* frsp - frsp. */
1486 uint64_t helper_frsp(uint64_t arg)
1487 {
1488     CPU_DoubleU farg;
1489     float32 f32;
1490
1491     farg.ll = arg;
1492
1493     if (unlikely(float64_is_signaling_nan(farg.d))) {
1494         /* sNaN square root */
1495         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1496     }
1497     f32 = float64_to_float32(farg.d, &env->fp_status);
1498     farg.d = float32_to_float64(f32, &env->fp_status);
1499
1500     return farg.ll;
1501 }
1502
1503 /* fsqrt - fsqrt. */
1504 uint64_t helper_fsqrt(uint64_t arg)
1505 {
1506     CPU_DoubleU farg;
1507
1508     farg.ll = arg;
1509
1510     if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1511         /* Square root of a negative nonzero number */
1512         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1513     } else {
1514         if (unlikely(float64_is_signaling_nan(farg.d))) {
1515             /* sNaN square root */
1516             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1517         }
1518         farg.d = float64_sqrt(farg.d, &env->fp_status);
1519     }
1520     return farg.ll;
1521 }
1522
1523 /* fre - fre. */
1524 uint64_t helper_fre(uint64_t arg)
1525 {
1526     CPU_DoubleU farg;
1527
1528     farg.ll = arg;
1529
1530     if (unlikely(float64_is_signaling_nan(farg.d))) {
1531         /* sNaN reciprocal */
1532         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1533     }
1534     farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1535     return farg.d;
1536 }
1537
1538 /* fres - fres. */
1539 uint64_t helper_fres(uint64_t arg)
1540 {
1541     CPU_DoubleU farg;
1542     float32 f32;
1543
1544     farg.ll = arg;
1545
1546     if (unlikely(float64_is_signaling_nan(farg.d))) {
1547         /* sNaN reciprocal */
1548         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1549     }
1550     farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1551     f32 = float64_to_float32(farg.d, &env->fp_status);
1552     farg.d = float32_to_float64(f32, &env->fp_status);
1553
1554     return farg.ll;
1555 }
1556
1557 /* frsqrte  - frsqrte. */
1558 uint64_t helper_frsqrte(uint64_t arg)
1559 {
1560     CPU_DoubleU farg;
1561     float32 f32;
1562
1563     farg.ll = arg;
1564
1565     if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1566         /* Reciprocal square root of a negative nonzero number */
1567         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1568     } else {
1569         if (unlikely(float64_is_signaling_nan(farg.d))) {
1570             /* sNaN reciprocal square root */
1571             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1572         }
1573         farg.d = float64_sqrt(farg.d, &env->fp_status);
1574         farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1575         f32 = float64_to_float32(farg.d, &env->fp_status);
1576         farg.d = float32_to_float64(f32, &env->fp_status);
1577     }
1578     return farg.ll;
1579 }
1580
1581 /* fsel - fsel. */
1582 uint64_t helper_fsel(uint64_t arg1, uint64_t arg2, uint64_t arg3)
1583 {
1584     CPU_DoubleU farg1;
1585
1586     farg1.ll = arg1;
1587
1588     if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
1589         !float64_is_any_nan(farg1.d)) {
1590         return arg2;
1591     } else {
1592         return arg3;
1593     }
1594 }
1595
1596 void helper_fcmpu(uint64_t arg1, uint64_t arg2, uint32_t crfD)
1597 {
1598     CPU_DoubleU farg1, farg2;
1599     uint32_t ret = 0;
1600
1601     farg1.ll = arg1;
1602     farg2.ll = arg2;
1603
1604     if (unlikely(float64_is_any_nan(farg1.d) ||
1605                  float64_is_any_nan(farg2.d))) {
1606         ret = 0x01UL;
1607     } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1608         ret = 0x08UL;
1609     } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1610         ret = 0x04UL;
1611     } else {
1612         ret = 0x02UL;
1613     }
1614
1615     env->fpscr &= ~(0x0F << FPSCR_FPRF);
1616     env->fpscr |= ret << FPSCR_FPRF;
1617     env->crf[crfD] = ret;
1618     if (unlikely(ret == 0x01UL
1619                  && (float64_is_signaling_nan(farg1.d) ||
1620                      float64_is_signaling_nan(farg2.d)))) {
1621         /* sNaN comparison */
1622         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1623     }
1624 }
1625
1626 void helper_fcmpo(uint64_t arg1, uint64_t arg2, uint32_t crfD)
1627 {
1628     CPU_DoubleU farg1, farg2;
1629     uint32_t ret = 0;
1630
1631     farg1.ll = arg1;
1632     farg2.ll = arg2;
1633
1634     if (unlikely(float64_is_any_nan(farg1.d) ||
1635                  float64_is_any_nan(farg2.d))) {
1636         ret = 0x01UL;
1637     } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1638         ret = 0x08UL;
1639     } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1640         ret = 0x04UL;
1641     } else {
1642         ret = 0x02UL;
1643     }
1644
1645     env->fpscr &= ~(0x0F << FPSCR_FPRF);
1646     env->fpscr |= ret << FPSCR_FPRF;
1647     env->crf[crfD] = ret;
1648     if (unlikely(ret == 0x01UL)) {
1649         if (float64_is_signaling_nan(farg1.d) ||
1650             float64_is_signaling_nan(farg2.d)) {
1651             /* sNaN comparison */
1652             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1653                                   POWERPC_EXCP_FP_VXVC);
1654         } else {
1655             /* qNaN comparison */
1656             fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1657         }
1658     }
1659 }
1660
1661 #if !defined(CONFIG_USER_ONLY)
1662 void helper_store_msr(target_ulong val)
1663 {
1664     val = hreg_store_msr(env, val, 0);
1665     if (val != 0) {
1666         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1667         helper_raise_exception(val);
1668     }
1669 }
1670
1671 static inline void do_rfi(target_ulong nip, target_ulong msr,
1672                           target_ulong msrm, int keep_msrh)
1673 {
1674 #if defined(TARGET_PPC64)
1675     if (msr & (1ULL << MSR_SF)) {
1676         nip = (uint64_t)nip;
1677         msr &= (uint64_t)msrm;
1678     } else {
1679         nip = (uint32_t)nip;
1680         msr = (uint32_t)(msr & msrm);
1681         if (keep_msrh) {
1682             msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1683         }
1684     }
1685 #else
1686     nip = (uint32_t)nip;
1687     msr &= (uint32_t)msrm;
1688 #endif
1689     /* XXX: beware: this is false if VLE is supported */
1690     env->nip = nip & ~((target_ulong)0x00000003);
1691     hreg_store_msr(env, msr, 1);
1692 #if defined(DEBUG_OP)
1693     cpu_dump_rfi(env->nip, env->msr);
1694 #endif
1695     /* No need to raise an exception here,
1696      * as rfi is always the last insn of a TB
1697      */
1698     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1699 }
1700
1701 void helper_rfi(void)
1702 {
1703     do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1704            ~((target_ulong)0x783F0000), 1);
1705 }
1706
1707 #if defined(TARGET_PPC64)
1708 void helper_rfid(void)
1709 {
1710     do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1711            ~((target_ulong)0x783F0000), 0);
1712 }
1713
1714 void helper_hrfid(void)
1715 {
1716     do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1717            ~((target_ulong)0x783F0000), 0);
1718 }
1719 #endif
1720 #endif
1721
1722 void helper_tw(target_ulong arg1, target_ulong arg2, uint32_t flags)
1723 {
1724     if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1725                   ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1726                   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1727                   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1728                   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1729         helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1730     }
1731 }
1732
1733 #if defined(TARGET_PPC64)
1734 void helper_td(target_ulong arg1, target_ulong arg2, uint32_t flags)
1735 {
1736     if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1737                   ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1738                   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1739                   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1740                   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1741         helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1742     }
1743 }
1744 #endif
1745
1746 /*****************************************************************************/
1747 /* PowerPC 601 specific instructions (POWER bridge) */
1748
1749 target_ulong helper_clcs(uint32_t arg)
1750 {
1751     switch (arg) {
1752     case 0x0CUL:
1753         /* Instruction cache line size */
1754         return env->icache_line_size;
1755         break;
1756     case 0x0DUL:
1757         /* Data cache line size */
1758         return env->dcache_line_size;
1759         break;
1760     case 0x0EUL:
1761         /* Minimum cache line size */
1762         return (env->icache_line_size < env->dcache_line_size) ?
1763             env->icache_line_size : env->dcache_line_size;
1764         break;
1765     case 0x0FUL:
1766         /* Maximum cache line size */
1767         return (env->icache_line_size > env->dcache_line_size) ?
1768             env->icache_line_size : env->dcache_line_size;
1769         break;
1770     default:
1771         /* Undefined */
1772         return 0;
1773         break;
1774     }
1775 }
1776
1777 target_ulong helper_div(target_ulong arg1, target_ulong arg2)
1778 {
1779     uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1780
1781     if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1782         (int32_t)arg2 == 0) {
1783         env->spr[SPR_MQ] = 0;
1784         return INT32_MIN;
1785     } else {
1786         env->spr[SPR_MQ] = tmp % arg2;
1787         return  tmp / (int32_t)arg2;
1788     }
1789 }
1790
1791 target_ulong helper_divo(target_ulong arg1, target_ulong arg2)
1792 {
1793     uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1794
1795     if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1796         (int32_t)arg2 == 0) {
1797         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1798         env->spr[SPR_MQ] = 0;
1799         return INT32_MIN;
1800     } else {
1801         env->spr[SPR_MQ] = tmp % arg2;
1802         tmp /= (int32_t)arg2;
1803         if ((int32_t)tmp != tmp) {
1804             env->xer |= (1 << XER_OV) | (1 << XER_SO);
1805         } else {
1806             env->xer &= ~(1 << XER_OV);
1807         }
1808         return tmp;
1809     }
1810 }
1811
1812 target_ulong helper_divs(target_ulong arg1, target_ulong arg2)
1813 {
1814     if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1815         (int32_t)arg2 == 0) {
1816         env->spr[SPR_MQ] = 0;
1817         return INT32_MIN;
1818     } else {
1819         env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1820         return (int32_t)arg1 / (int32_t)arg2;
1821     }
1822 }
1823
1824 target_ulong helper_divso(target_ulong arg1, target_ulong arg2)
1825 {
1826     if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1827         (int32_t)arg2 == 0) {
1828         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1829         env->spr[SPR_MQ] = 0;
1830         return INT32_MIN;
1831     } else {
1832         env->xer &= ~(1 << XER_OV);
1833         env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1834         return (int32_t)arg1 / (int32_t)arg2;
1835     }
1836 }
1837
1838 #if !defined(CONFIG_USER_ONLY)
1839 target_ulong helper_rac(target_ulong addr)
1840 {
1841     mmu_ctx_t ctx;
1842     int nb_BATs;
1843     target_ulong ret = 0;
1844
1845     /* We don't have to generate many instances of this instruction,
1846      * as rac is supervisor only.
1847      */
1848     /* XXX: FIX THIS: Pretend we have no BAT */
1849     nb_BATs = env->nb_BATs;
1850     env->nb_BATs = 0;
1851     if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
1852         ret = ctx.raddr;
1853     }
1854     env->nb_BATs = nb_BATs;
1855     return ret;
1856 }
1857
1858 void helper_rfsvc(void)
1859 {
1860     do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1861 }
1862 #endif
1863
1864 /*****************************************************************************/
1865 /* 602 specific instructions */
1866 /* mfrom is the most crazy instruction ever seen, imho ! */
1867 /* Real implementation uses a ROM table. Do the same */
1868 /* Extremely decomposed:
1869  *                      -arg / 256
1870  * return 256 * log10(10           + 1.0) + 0.5
1871  */
1872 #if !defined(CONFIG_USER_ONLY)
1873 target_ulong helper_602_mfrom(target_ulong arg)
1874 {
1875     if (likely(arg < 602)) {
1876 #include "mfrom_table.c"
1877         return mfrom_ROM_table[arg];
1878     } else {
1879         return 0;
1880     }
1881 }
1882 #endif
1883
1884 /*****************************************************************************/
1885 /* Embedded PowerPC specific helpers */
1886
1887 /* XXX: to be improved to check access rights when in user-mode */
1888 target_ulong helper_load_dcr(target_ulong dcrn)
1889 {
1890     uint32_t val = 0;
1891
1892     if (unlikely(env->dcr_env == NULL)) {
1893         qemu_log("No DCR environment\n");
1894         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1895                                    POWERPC_EXCP_INVAL |
1896                                    POWERPC_EXCP_INVAL_INVAL);
1897     } else if (unlikely(ppc_dcr_read(env->dcr_env,
1898                                      (uint32_t)dcrn, &val) != 0)) {
1899         qemu_log("DCR read error %d %03x\n", (uint32_t)dcrn, (uint32_t)dcrn);
1900         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1901                                    POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1902     }
1903     return val;
1904 }
1905
1906 void helper_store_dcr(target_ulong dcrn, target_ulong val)
1907 {
1908     if (unlikely(env->dcr_env == NULL)) {
1909         qemu_log("No DCR environment\n");
1910         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1911                                    POWERPC_EXCP_INVAL |
1912                                    POWERPC_EXCP_INVAL_INVAL);
1913     } else if (unlikely(ppc_dcr_write(env->dcr_env, (uint32_t)dcrn,
1914                                       (uint32_t)val) != 0)) {
1915         qemu_log("DCR write error %d %03x\n", (uint32_t)dcrn, (uint32_t)dcrn);
1916         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1917                                    POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1918     }
1919 }
1920
1921 #if !defined(CONFIG_USER_ONLY)
1922 void helper_40x_rfci(void)
1923 {
1924     do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1925            ~((target_ulong)0xFFFF0000), 0);
1926 }
1927
1928 void helper_rfci(void)
1929 {
1930     do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1931            ~((target_ulong)0x3FFF0000), 0);
1932 }
1933
1934 void helper_rfdi(void)
1935 {
1936     do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1937            ~((target_ulong)0x3FFF0000), 0);
1938 }
1939
1940 void helper_rfmci(void)
1941 {
1942     do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1943            ~((target_ulong)0x3FFF0000), 0);
1944 }
1945 #endif
1946
1947 /* 440 specific */
1948 target_ulong helper_dlmzb(target_ulong high, target_ulong low,
1949                           uint32_t update_Rc)
1950 {
1951     target_ulong mask;
1952     int i;
1953
1954     i = 1;
1955     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1956         if ((high & mask) == 0) {
1957             if (update_Rc) {
1958                 env->crf[0] = 0x4;
1959             }
1960             goto done;
1961         }
1962         i++;
1963     }
1964     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1965         if ((low & mask) == 0) {
1966             if (update_Rc) {
1967                 env->crf[0] = 0x8;
1968             }
1969             goto done;
1970         }
1971         i++;
1972     }
1973     if (update_Rc) {
1974         env->crf[0] = 0x2;
1975     }
1976  done:
1977     env->xer = (env->xer & ~0x7F) | i;
1978     if (update_Rc) {
1979         env->crf[0] |= xer_so;
1980     }
1981     return i;
1982 }
1983
1984 /*****************************************************************************/
1985 /* Altivec extension helpers */
1986 #if defined(HOST_WORDS_BIGENDIAN)
1987 #define HI_IDX 0
1988 #define LO_IDX 1
1989 #else
1990 #define HI_IDX 1
1991 #define LO_IDX 0
1992 #endif
1993
1994 #if defined(HOST_WORDS_BIGENDIAN)
1995 #define VECTOR_FOR_INORDER_I(index, element)                    \
1996     for (index = 0; index < ARRAY_SIZE(r->element); index++)
1997 #else
1998 #define VECTOR_FOR_INORDER_I(index, element)                    \
1999     for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
2000 #endif
2001
2002 /* If X is a NaN, store the corresponding QNaN into RESULT.  Otherwise,
2003  * execute the following block.  */
2004 #define DO_HANDLE_NAN(result, x)                        \
2005     if (float32_is_any_nan(x)) {                        \
2006         CPU_FloatU __f;                                 \
2007         __f.f = x;                                      \
2008         __f.l = __f.l | (1 << 22);  /* Set QNaN bit. */ \
2009         result = __f.f;                                 \
2010     } else
2011
2012 #define HANDLE_NAN1(result, x)                  \
2013     DO_HANDLE_NAN(result, x)
2014 #define HANDLE_NAN2(result, x, y)                       \
2015     DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
2016 #define HANDLE_NAN3(result, x, y, z)                                    \
2017     DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
2018
2019 /* Saturating arithmetic helpers.  */
2020 #define SATCVT(from, to, from_type, to_type, min, max)          \
2021     static inline to_type cvt##from##to(from_type x, int *sat)  \
2022     {                                                           \
2023         to_type r;                                              \
2024                                                                 \
2025         if (x < (from_type)min) {                               \
2026             r = min;                                            \
2027             *sat = 1;                                           \
2028         } else if (x > (from_type)max) {                        \
2029             r = max;                                            \
2030             *sat = 1;                                           \
2031         } else {                                                \
2032             r = x;                                              \
2033         }                                                       \
2034         return r;                                               \
2035     }
2036 #define SATCVTU(from, to, from_type, to_type, min, max)         \
2037     static inline to_type cvt##from##to(from_type x, int *sat)  \
2038     {                                                           \
2039         to_type r;                                              \
2040                                                                 \
2041         if (x > (from_type)max) {                               \
2042             r = max;                                            \
2043             *sat = 1;                                           \
2044         } else {                                                \
2045             r = x;                                              \
2046         }                                                       \
2047         return r;                                               \
2048     }
2049 SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
2050 SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
2051 SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
2052
2053 SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
2054 SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
2055 SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
2056 SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
2057 SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
2058 SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
2059 #undef SATCVT
2060 #undef SATCVTU
2061
2062 #define LVE(name, access, swap, element)                        \
2063     void helper_##name(ppc_avr_t *r, target_ulong addr)         \
2064     {                                                           \
2065         size_t n_elems = ARRAY_SIZE(r->element);                \
2066         int adjust = HI_IDX*(n_elems - 1);                      \
2067         int sh = sizeof(r->element[0]) >> 1;                    \
2068         int index = (addr & 0xf) >> sh;                         \
2069                                                                 \
2070         if (msr_le) {                                           \
2071             r->element[LO_IDX ? index : (adjust - index)] =     \
2072                 swap(access(addr));                             \
2073         } else {                                                \
2074             r->element[LO_IDX ? index : (adjust - index)] =     \
2075                 access(addr);                                   \
2076         }                                                       \
2077     }
2078 #define I(x) (x)
2079 LVE(lvebx, ldub, I, u8)
2080 LVE(lvehx, lduw, bswap16, u16)
2081 LVE(lvewx, ldl, bswap32, u32)
2082 #undef I
2083 #undef LVE
2084
2085 void helper_lvsl(ppc_avr_t *r, target_ulong sh)
2086 {
2087     int i, j = (sh & 0xf);
2088
2089     VECTOR_FOR_INORDER_I(i, u8) {
2090         r->u8[i] = j++;
2091     }
2092 }
2093
2094 void helper_lvsr(ppc_avr_t *r, target_ulong sh)
2095 {
2096     int i, j = 0x10 - (sh & 0xf);
2097
2098     VECTOR_FOR_INORDER_I(i, u8) {
2099         r->u8[i] = j++;
2100     }
2101 }
2102
2103 #define STVE(name, access, swap, element)                               \
2104     void helper_##name(ppc_avr_t *r, target_ulong addr)                 \
2105     {                                                                   \
2106         size_t n_elems = ARRAY_SIZE(r->element);                        \
2107         int adjust = HI_IDX * (n_elems - 1);                            \
2108         int sh = sizeof(r->element[0]) >> 1;                            \
2109         int index = (addr & 0xf) >> sh;                                 \
2110                                                                         \
2111         if (msr_le) {                                                   \
2112             access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
2113         } else {                                                        \
2114             access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
2115         }                                                               \
2116     }
2117 #define I(x) (x)
2118 STVE(stvebx, stb, I, u8)
2119 STVE(stvehx, stw, bswap16, u16)
2120 STVE(stvewx, stl, bswap32, u32)
2121 #undef I
2122 #undef LVE
2123
2124 void helper_mtvscr(ppc_avr_t *r)
2125 {
2126 #if defined(HOST_WORDS_BIGENDIAN)
2127     env->vscr = r->u32[3];
2128 #else
2129     env->vscr = r->u32[0];
2130 #endif
2131     set_flush_to_zero(vscr_nj, &env->vec_status);
2132 }
2133
2134 void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2135 {
2136     int i;
2137
2138     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2139         r->u32[i] = ~a->u32[i] < b->u32[i];
2140     }
2141 }
2142
2143 #define VARITH_DO(name, op, element)                                    \
2144     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2145     {                                                                   \
2146         int i;                                                          \
2147                                                                         \
2148         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2149             r->element[i] = a->element[i] op b->element[i];             \
2150         }                                                               \
2151     }
2152 #define VARITH(suffix, element)                 \
2153     VARITH_DO(add##suffix, +, element)          \
2154     VARITH_DO(sub##suffix, -, element)
2155 VARITH(ubm, u8)
2156 VARITH(uhm, u16)
2157 VARITH(uwm, u32)
2158 #undef VARITH_DO
2159 #undef VARITH
2160
2161 #define VARITHFP(suffix, func)                                          \
2162     void helper_v##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)     \
2163     {                                                                   \
2164         int i;                                                          \
2165                                                                         \
2166         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2167             HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2168                 r->f[i] = func(a->f[i], b->f[i], &env->vec_status);     \
2169             }                                                           \
2170         }                                                               \
2171     }
2172 VARITHFP(addfp, float32_add)
2173 VARITHFP(subfp, float32_sub)
2174 #undef VARITHFP
2175
2176 #define VARITHSAT_CASE(type, op, cvt, element)                          \
2177     {                                                                   \
2178         type result = (type)a->element[i] op (type)b->element[i];       \
2179         r->element[i] = cvt(result, &sat);                              \
2180     }
2181
2182 #define VARITHSAT_DO(name, op, optype, cvt, element)                    \
2183     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2184     {                                                                   \
2185         int sat = 0;                                                    \
2186         int i;                                                          \
2187                                                                         \
2188         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2189             switch (sizeof(r->element[0])) {                            \
2190             case 1:                                                     \
2191                 VARITHSAT_CASE(optype, op, cvt, element);               \
2192                 break;                                                  \
2193             case 2:                                                     \
2194                 VARITHSAT_CASE(optype, op, cvt, element);               \
2195                 break;                                                  \
2196             case 4:                                                     \
2197                 VARITHSAT_CASE(optype, op, cvt, element);               \
2198                 break;                                                  \
2199             }                                                           \
2200         }                                                               \
2201         if (sat) {                                                      \
2202             env->vscr |= (1 << VSCR_SAT);                               \
2203         }                                                               \
2204     }
2205 #define VARITHSAT_SIGNED(suffix, element, optype, cvt)          \
2206     VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)      \
2207     VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
2208 #define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)        \
2209     VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)      \
2210     VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
2211 VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
2212 VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
2213 VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
2214 VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
2215 VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
2216 VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
2217 #undef VARITHSAT_CASE
2218 #undef VARITHSAT_DO
2219 #undef VARITHSAT_SIGNED
2220 #undef VARITHSAT_UNSIGNED
2221
2222 #define VAVG_DO(name, element, etype)                                   \
2223     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2224     {                                                                   \
2225         int i;                                                          \
2226                                                                         \
2227         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2228             etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
2229             r->element[i] = x >> 1;                                     \
2230         }                                                               \
2231     }
2232
2233 #define VAVG(type, signed_element, signed_type, unsigned_element,       \
2234              unsigned_type)                                             \
2235     VAVG_DO(avgs##type, signed_element, signed_type)                    \
2236     VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2237 VAVG(b, s8, int16_t, u8, uint16_t)
2238 VAVG(h, s16, int32_t, u16, uint32_t)
2239 VAVG(w, s32, int64_t, u32, uint64_t)
2240 #undef VAVG_DO
2241 #undef VAVG
2242
2243 #define VCF(suffix, cvt, element)                                       \
2244     void helper_vcf##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)   \
2245     {                                                                   \
2246         int i;                                                          \
2247                                                                         \
2248         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2249             float32 t = cvt(b->element[i], &env->vec_status);           \
2250             r->f[i] = float32_scalbn(t, -uim, &env->vec_status);        \
2251         }                                                               \
2252     }
2253 VCF(ux, uint32_to_float32, u32)
2254 VCF(sx, int32_to_float32, s32)
2255 #undef VCF
2256
2257 #define VCMP_DO(suffix, compare, element, record)                       \
2258     void helper_vcmp##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2259     {                                                                   \
2260         uint32_t ones = (uint32_t)-1;                                   \
2261         uint32_t all = ones;                                            \
2262         uint32_t none = 0;                                              \
2263         int i;                                                          \
2264                                                                         \
2265         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2266             uint32_t result = (a->element[i] compare b->element[i] ?    \
2267                                ones : 0x0);                             \
2268             switch (sizeof(a->element[0])) {                            \
2269             case 4:                                                     \
2270                 r->u32[i] = result;                                     \
2271                 break;                                                  \
2272             case 2:                                                     \
2273                 r->u16[i] = result;                                     \
2274                 break;                                                  \
2275             case 1:                                                     \
2276                 r->u8[i] = result;                                      \
2277                 break;                                                  \
2278             }                                                           \
2279             all &= result;                                              \
2280             none |= result;                                             \
2281         }                                                               \
2282         if (record) {                                                   \
2283             env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2284         }                                                               \
2285     }
2286 #define VCMP(suffix, compare, element)          \
2287     VCMP_DO(suffix, compare, element, 0)        \
2288     VCMP_DO(suffix##_dot, compare, element, 1)
2289 VCMP(equb, ==, u8)
2290 VCMP(equh, ==, u16)
2291 VCMP(equw, ==, u32)
2292 VCMP(gtub, >, u8)
2293 VCMP(gtuh, >, u16)
2294 VCMP(gtuw, >, u32)
2295 VCMP(gtsb, >, s8)
2296 VCMP(gtsh, >, s16)
2297 VCMP(gtsw, >, s32)
2298 #undef VCMP_DO
2299 #undef VCMP
2300
2301 #define VCMPFP_DO(suffix, compare, order, record)                       \
2302     void helper_vcmp##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2303     {                                                                   \
2304         uint32_t ones = (uint32_t)-1;                                   \
2305         uint32_t all = ones;                                            \
2306         uint32_t none = 0;                                              \
2307         int i;                                                          \
2308                                                                         \
2309         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2310             uint32_t result;                                            \
2311             int rel = float32_compare_quiet(a->f[i], b->f[i],           \
2312                                             &env->vec_status);          \
2313             if (rel == float_relation_unordered) {                      \
2314                 result = 0;                                             \
2315             } else if (rel compare order) {                             \
2316                 result = ones;                                          \
2317             } else {                                                    \
2318                 result = 0;                                             \
2319             }                                                           \
2320             r->u32[i] = result;                                         \
2321             all &= result;                                              \
2322             none |= result;                                             \
2323         }                                                               \
2324         if (record) {                                                   \
2325             env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2326         }                                                               \
2327     }
2328 #define VCMPFP(suffix, compare, order)          \
2329     VCMPFP_DO(suffix, compare, order, 0)        \
2330     VCMPFP_DO(suffix##_dot, compare, order, 1)
2331 VCMPFP(eqfp, ==, float_relation_equal)
2332 VCMPFP(gefp, !=, float_relation_less)
2333 VCMPFP(gtfp, ==, float_relation_greater)
2334 #undef VCMPFP_DO
2335 #undef VCMPFP
2336
2337 static inline void vcmpbfp_internal(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
2338                                     int record)
2339 {
2340     int i;
2341     int all_in = 0;
2342
2343     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2344         int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
2345         if (le_rel == float_relation_unordered) {
2346             r->u32[i] = 0xc0000000;
2347             /* ALL_IN does not need to be updated here.  */
2348         } else {
2349             float32 bneg = float32_chs(b->f[i]);
2350             int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
2351             int le = le_rel != float_relation_greater;
2352             int ge = ge_rel != float_relation_less;
2353
2354             r->u32[i] = ((!le) << 31) | ((!ge) << 30);
2355             all_in |= (!le | !ge);
2356         }
2357     }
2358     if (record) {
2359         env->crf[6] = (all_in == 0) << 1;
2360     }
2361 }
2362
2363 void helper_vcmpbfp(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2364 {
2365     vcmpbfp_internal(r, a, b, 0);
2366 }
2367
2368 void helper_vcmpbfp_dot(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2369 {
2370     vcmpbfp_internal(r, a, b, 1);
2371 }
2372
2373 #define VCT(suffix, satcvt, element)                                    \
2374     void helper_vct##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)   \
2375     {                                                                   \
2376         int i;                                                          \
2377         int sat = 0;                                                    \
2378         float_status s = env->vec_status;                               \
2379                                                                         \
2380         set_float_rounding_mode(float_round_to_zero, &s);               \
2381         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2382             if (float32_is_any_nan(b->f[i])) {                          \
2383                 r->element[i] = 0;                                      \
2384             } else {                                                    \
2385                 float64 t = float32_to_float64(b->f[i], &s);            \
2386                 int64_t j;                                              \
2387                                                                         \
2388                 t = float64_scalbn(t, uim, &s);                         \
2389                 j = float64_to_int64(t, &s);                            \
2390                 r->element[i] = satcvt(j, &sat);                        \
2391             }                                                           \
2392         }                                                               \
2393         if (sat) {                                                      \
2394             env->vscr |= (1 << VSCR_SAT);                               \
2395         }                                                               \
2396     }
2397 VCT(uxs, cvtsduw, u32)
2398 VCT(sxs, cvtsdsw, s32)
2399 #undef VCT
2400
2401 void helper_vmaddfp(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2402 {
2403     int i;
2404
2405     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2406         HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2407             /* Need to do the computation in higher precision and round
2408              * once at the end.  */
2409             float64 af, bf, cf, t;
2410
2411             af = float32_to_float64(a->f[i], &env->vec_status);
2412             bf = float32_to_float64(b->f[i], &env->vec_status);
2413             cf = float32_to_float64(c->f[i], &env->vec_status);
2414             t = float64_mul(af, cf, &env->vec_status);
2415             t = float64_add(t, bf, &env->vec_status);
2416             r->f[i] = float64_to_float32(t, &env->vec_status);
2417         }
2418     }
2419 }
2420
2421 void helper_vmhaddshs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2422 {
2423     int sat = 0;
2424     int i;
2425
2426     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2427         int32_t prod = a->s16[i] * b->s16[i];
2428         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2429
2430         r->s16[i] = cvtswsh(t, &sat);
2431     }
2432
2433     if (sat) {
2434         env->vscr |= (1 << VSCR_SAT);
2435     }
2436 }
2437
2438 void helper_vmhraddshs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2439 {
2440     int sat = 0;
2441     int i;
2442
2443     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2444         int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2445         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2446         r->s16[i] = cvtswsh(t, &sat);
2447     }
2448
2449     if (sat) {
2450         env->vscr |= (1 << VSCR_SAT);
2451     }
2452 }
2453
2454 #define VMINMAX_DO(name, compare, element)                              \
2455     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2456     {                                                                   \
2457         int i;                                                          \
2458                                                                         \
2459         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2460             if (a->element[i] compare b->element[i]) {                  \
2461                 r->element[i] = b->element[i];                          \
2462             } else {                                                    \
2463                 r->element[i] = a->element[i];                          \
2464             }                                                           \
2465         }                                                               \
2466     }
2467 #define VMINMAX(suffix, element)                \
2468     VMINMAX_DO(min##suffix, >, element)         \
2469     VMINMAX_DO(max##suffix, <, element)
2470 VMINMAX(sb, s8)
2471 VMINMAX(sh, s16)
2472 VMINMAX(sw, s32)
2473 VMINMAX(ub, u8)
2474 VMINMAX(uh, u16)
2475 VMINMAX(uw, u32)
2476 #undef VMINMAX_DO
2477 #undef VMINMAX
2478
2479 #define VMINMAXFP(suffix, rT, rF)                                       \
2480     void helper_v##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)     \
2481     {                                                                   \
2482         int i;                                                          \
2483                                                                         \
2484         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2485             HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2486                 if (float32_lt_quiet(a->f[i], b->f[i],                  \
2487                                      &env->vec_status)) {               \
2488                     r->f[i] = rT->f[i];                                 \
2489                 } else {                                                \
2490                     r->f[i] = rF->f[i];                                 \
2491                 }                                                       \
2492             }                                                           \
2493         }                                                               \
2494     }
2495 VMINMAXFP(minfp, a, b)
2496 VMINMAXFP(maxfp, b, a)
2497 #undef VMINMAXFP
2498
2499 void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2500 {
2501     int i;
2502
2503     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2504         int32_t prod = a->s16[i] * b->s16[i];
2505         r->s16[i] = (int16_t) (prod + c->s16[i]);
2506     }
2507 }
2508
2509 #define VMRG_DO(name, element, highp)                                   \
2510     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2511     {                                                                   \
2512         ppc_avr_t result;                                               \
2513         int i;                                                          \
2514         size_t n_elems = ARRAY_SIZE(r->element);                        \
2515                                                                         \
2516         for (i = 0; i < n_elems / 2; i++) {                             \
2517             if (highp) {                                                \
2518                 result.element[i*2+HI_IDX] = a->element[i];             \
2519                 result.element[i*2+LO_IDX] = b->element[i];             \
2520             } else {                                                    \
2521                 result.element[n_elems - i * 2 - (1 + HI_IDX)] =        \
2522                     b->element[n_elems - i - 1];                        \
2523                 result.element[n_elems - i * 2 - (1 + LO_IDX)] =        \
2524                     a->element[n_elems - i - 1];                        \
2525             }                                                           \
2526         }                                                               \
2527         *r = result;                                                    \
2528     }
2529 #if defined(HOST_WORDS_BIGENDIAN)
2530 #define MRGHI 0
2531 #define MRGLO 1
2532 #else
2533 #define MRGHI 1
2534 #define MRGLO 0
2535 #endif
2536 #define VMRG(suffix, element)                   \
2537     VMRG_DO(mrgl##suffix, element, MRGHI)       \
2538     VMRG_DO(mrgh##suffix, element, MRGLO)
2539 VMRG(b, u8)
2540 VMRG(h, u16)
2541 VMRG(w, u32)
2542 #undef VMRG_DO
2543 #undef VMRG
2544 #undef MRGHI
2545 #undef MRGLO
2546
2547 void helper_vmsummbm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2548 {
2549     int32_t prod[16];
2550     int i;
2551
2552     for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2553         prod[i] = (int32_t)a->s8[i] * b->u8[i];
2554     }
2555
2556     VECTOR_FOR_INORDER_I(i, s32) {
2557         r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
2558             prod[4 * i + 2] + prod[4 * i + 3];
2559     }
2560 }
2561
2562 void helper_vmsumshm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2563 {
2564     int32_t prod[8];
2565     int i;
2566
2567     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2568         prod[i] = a->s16[i] * b->s16[i];
2569     }
2570
2571     VECTOR_FOR_INORDER_I(i, s32) {
2572         r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
2573     }
2574 }
2575
2576 void helper_vmsumshs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2577 {
2578     int32_t prod[8];
2579     int i;
2580     int sat = 0;
2581
2582     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2583         prod[i] = (int32_t)a->s16[i] * b->s16[i];
2584     }
2585
2586     VECTOR_FOR_INORDER_I(i, s32) {
2587         int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
2588
2589         r->u32[i] = cvtsdsw(t, &sat);
2590     }
2591
2592     if (sat) {
2593         env->vscr |= (1 << VSCR_SAT);
2594     }
2595 }
2596
2597 void helper_vmsumubm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2598 {
2599     uint16_t prod[16];
2600     int i;
2601
2602     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2603         prod[i] = a->u8[i] * b->u8[i];
2604     }
2605
2606     VECTOR_FOR_INORDER_I(i, u32) {
2607         r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
2608             prod[4 * i + 2] + prod[4 * i + 3];
2609     }
2610 }
2611
2612 void helper_vmsumuhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2613 {
2614     uint32_t prod[8];
2615     int i;
2616
2617     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2618         prod[i] = a->u16[i] * b->u16[i];
2619     }
2620
2621     VECTOR_FOR_INORDER_I(i, u32) {
2622         r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
2623     }
2624 }
2625
2626 void helper_vmsumuhs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2627 {
2628     uint32_t prod[8];
2629     int i;
2630     int sat = 0;
2631
2632     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2633         prod[i] = a->u16[i] * b->u16[i];
2634     }
2635
2636     VECTOR_FOR_INORDER_I(i, s32) {
2637         uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
2638
2639         r->u32[i] = cvtuduw(t, &sat);
2640     }
2641
2642     if (sat) {
2643         env->vscr |= (1 << VSCR_SAT);
2644     }
2645 }
2646
2647 #define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2648     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
2649     {                                                                   \
2650         int i;                                                          \
2651                                                                         \
2652         VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2653             if (evenp) {                                                \
2654                 r->prod_element[i] = a->mul_element[i * 2 + HI_IDX] *   \
2655                     b->mul_element[i * 2 + HI_IDX];                     \
2656             } else {                                                    \
2657                 r->prod_element[i] = a->mul_element[i * 2 + LO_IDX] *   \
2658                     b->mul_element[i * 2 + LO_IDX];                     \
2659             }                                                           \
2660         }                                                               \
2661     }
2662 #define VMUL(suffix, mul_element, prod_element)         \
2663     VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2664     VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2665 VMUL(sb, s8, s16)
2666 VMUL(sh, s16, s32)
2667 VMUL(ub, u8, u16)
2668 VMUL(uh, u16, u32)
2669 #undef VMUL_DO
2670 #undef VMUL
2671
2672 void helper_vnmsubfp(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2673 {
2674     int i;
2675
2676     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2677         HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2678             /* Need to do the computation is higher precision and round
2679              * once at the end.  */
2680             float64 af, bf, cf, t;
2681
2682             af = float32_to_float64(a->f[i], &env->vec_status);
2683             bf = float32_to_float64(b->f[i], &env->vec_status);
2684             cf = float32_to_float64(c->f[i], &env->vec_status);
2685             t = float64_mul(af, cf, &env->vec_status);
2686             t = float64_sub(t, bf, &env->vec_status);
2687             t = float64_chs(t);
2688             r->f[i] = float64_to_float32(t, &env->vec_status);
2689         }
2690     }
2691 }
2692
2693 void helper_vperm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2694 {
2695     ppc_avr_t result;
2696     int i;
2697
2698     VECTOR_FOR_INORDER_I(i, u8) {
2699         int s = c->u8[i] & 0x1f;
2700 #if defined(HOST_WORDS_BIGENDIAN)
2701         int index = s & 0xf;
2702 #else
2703         int index = 15 - (s & 0xf);
2704 #endif
2705
2706         if (s & 0x10) {
2707             result.u8[i] = b->u8[index];
2708         } else {
2709             result.u8[i] = a->u8[index];
2710         }
2711     }
2712     *r = result;
2713 }
2714
2715 #if defined(HOST_WORDS_BIGENDIAN)
2716 #define PKBIG 1
2717 #else
2718 #define PKBIG 0
2719 #endif
2720 void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2721 {
2722     int i, j;
2723     ppc_avr_t result;
2724 #if defined(HOST_WORDS_BIGENDIAN)
2725     const ppc_avr_t *x[2] = { a, b };
2726 #else
2727     const ppc_avr_t *x[2] = { b, a };
2728 #endif
2729
2730     VECTOR_FOR_INORDER_I(i, u64) {
2731         VECTOR_FOR_INORDER_I(j, u32) {
2732             uint32_t e = x[i]->u32[j];
2733
2734             result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2735                                  ((e >> 6) & 0x3e0) |
2736                                  ((e >> 3) & 0x1f));
2737         }
2738     }
2739     *r = result;
2740 }
2741
2742 #define VPK(suffix, from, to, cvt, dosat)                               \
2743     void helper_vpk##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2744     {                                                                   \
2745         int i;                                                          \
2746         int sat = 0;                                                    \
2747         ppc_avr_t result;                                               \
2748         ppc_avr_t *a0 = PKBIG ? a : b;                                  \
2749         ppc_avr_t *a1 = PKBIG ? b : a;                                  \
2750                                                                         \
2751         VECTOR_FOR_INORDER_I(i, from) {                                 \
2752             result.to[i] = cvt(a0->from[i], &sat);                      \
2753             result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
2754         }                                                               \
2755         *r = result;                                                    \
2756         if (dosat && sat) {                                             \
2757             env->vscr |= (1 << VSCR_SAT);                               \
2758         }                                                               \
2759     }
2760 #define I(x, y) (x)
2761 VPK(shss, s16, s8, cvtshsb, 1)
2762 VPK(shus, s16, u8, cvtshub, 1)
2763 VPK(swss, s32, s16, cvtswsh, 1)
2764 VPK(swus, s32, u16, cvtswuh, 1)
2765 VPK(uhus, u16, u8, cvtuhub, 1)
2766 VPK(uwus, u32, u16, cvtuwuh, 1)
2767 VPK(uhum, u16, u8, I, 0)
2768 VPK(uwum, u32, u16, I, 0)
2769 #undef I
2770 #undef VPK
2771 #undef PKBIG
2772
2773 void helper_vrefp(ppc_avr_t *r, ppc_avr_t *b)
2774 {
2775     int i;
2776
2777     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2778         HANDLE_NAN1(r->f[i], b->f[i]) {
2779             r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
2780         }
2781     }
2782 }
2783
2784 #define VRFI(suffix, rounding)                                  \
2785     void helper_vrfi##suffix(ppc_avr_t *r, ppc_avr_t *b)        \
2786     {                                                           \
2787         int i;                                                  \
2788         float_status s = env->vec_status;                       \
2789                                                                 \
2790         set_float_rounding_mode(rounding, &s);                  \
2791         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                \
2792             HANDLE_NAN1(r->f[i], b->f[i]) {                     \
2793                 r->f[i] = float32_round_to_int (b->f[i], &s);   \
2794             }                                                   \
2795         }                                                       \
2796     }
2797 VRFI(n, float_round_nearest_even)
2798 VRFI(m, float_round_down)
2799 VRFI(p, float_round_up)
2800 VRFI(z, float_round_to_zero)
2801 #undef VRFI
2802
2803 #define VROTATE(suffix, element)                                        \
2804     void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2805     {                                                                   \
2806         int i;                                                          \
2807                                                                         \
2808         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2809             unsigned int mask = ((1 <<                                  \
2810                                   (3 + (sizeof(a->element[0]) >> 1)))   \
2811                                  - 1);                                  \
2812             unsigned int shift = b->element[i] & mask;                  \
2813             r->element[i] = (a->element[i] << shift) |                  \
2814                 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2815         }                                                               \
2816     }
2817 VROTATE(b, u8)
2818 VROTATE(h, u16)
2819 VROTATE(w, u32)
2820 #undef VROTATE
2821
2822 void helper_vrsqrtefp(ppc_avr_t *r, ppc_avr_t *b)
2823 {
2824     int i;
2825
2826     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2827         HANDLE_NAN1(r->f[i], b->f[i]) {
2828             float32 t = float32_sqrt(b->f[i], &env->vec_status);
2829
2830             r->f[i] = float32_div(float32_one, t, &env->vec_status);
2831         }
2832     }
2833 }
2834
2835 void helper_vsel(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2836 {
2837     r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2838     r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2839 }
2840
2841 void helper_vexptefp(ppc_avr_t *r, ppc_avr_t *b)
2842 {
2843     int i;
2844
2845     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2846         HANDLE_NAN1(r->f[i], b->f[i]) {
2847             r->f[i] = float32_exp2(b->f[i], &env->vec_status);
2848         }
2849     }
2850 }
2851
2852 void helper_vlogefp(ppc_avr_t *r, ppc_avr_t *b)
2853 {
2854     int i;
2855
2856     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2857         HANDLE_NAN1(r->f[i], b->f[i]) {
2858             r->f[i] = float32_log2(b->f[i], &env->vec_status);
2859         }
2860     }
2861 }
2862
2863 #if defined(HOST_WORDS_BIGENDIAN)
2864 #define LEFT 0
2865 #define RIGHT 1
2866 #else
2867 #define LEFT 1
2868 #define RIGHT 0
2869 #endif
2870 /* The specification says that the results are undefined if all of the
2871  * shift counts are not identical.  We check to make sure that they are
2872  * to conform to what real hardware appears to do.  */
2873 #define VSHIFT(suffix, leftp)                                           \
2874     void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2875     {                                                                   \
2876         int shift = b->u8[LO_IDX*15] & 0x7;                             \
2877         int doit = 1;                                                   \
2878         int i;                                                          \
2879                                                                         \
2880         for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
2881             doit = doit && ((b->u8[i] & 0x7) == shift);                 \
2882         }                                                               \
2883         if (doit) {                                                     \
2884             if (shift == 0) {                                           \
2885                 *r = *a;                                                \
2886             } else if (leftp) {                                         \
2887                 uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
2888                                                                         \
2889                 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
2890                 r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
2891             } else {                                                    \
2892                 uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
2893                                                                         \
2894                 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
2895                 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
2896             }                                                           \
2897         }                                                               \
2898     }
2899 VSHIFT(l, LEFT)
2900 VSHIFT(r, RIGHT)
2901 #undef VSHIFT
2902 #undef LEFT
2903 #undef RIGHT
2904
2905 #define VSL(suffix, element)                                            \
2906     void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2907     {                                                                   \
2908         int i;                                                          \
2909                                                                         \
2910         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2911             unsigned int mask = ((1 <<                                  \
2912                                   (3 + (sizeof(a->element[0]) >> 1)))   \
2913                                  - 1);                                  \
2914             unsigned int shift = b->element[i] & mask;                  \
2915                                                                         \
2916             r->element[i] = a->element[i] << shift;                     \
2917         }                                                               \
2918     }
2919 VSL(b, u8)
2920 VSL(h, u16)
2921 VSL(w, u32)
2922 #undef VSL
2923
2924 void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2925 {
2926     int sh = shift & 0xf;
2927     int i;
2928     ppc_avr_t result;
2929
2930 #if defined(HOST_WORDS_BIGENDIAN)
2931     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2932         int index = sh + i;
2933         if (index > 0xf) {
2934             result.u8[i] = b->u8[index - 0x10];
2935         } else {
2936             result.u8[i] = a->u8[index];
2937         }
2938     }
2939 #else
2940     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2941         int index = (16 - sh) + i;
2942         if (index > 0xf) {
2943             result.u8[i] = a->u8[index - 0x10];
2944         } else {
2945             result.u8[i] = b->u8[index];
2946         }
2947     }
2948 #endif
2949     *r = result;
2950 }
2951
2952 void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2953 {
2954     int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2955
2956 #if defined(HOST_WORDS_BIGENDIAN)
2957     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
2958     memset(&r->u8[16-sh], 0, sh);
2959 #else
2960     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
2961     memset(&r->u8[0], 0, sh);
2962 #endif
2963 }
2964
2965 /* Experimental testing shows that hardware masks the immediate.  */
2966 #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2967 #if defined(HOST_WORDS_BIGENDIAN)
2968 #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2969 #else
2970 #define SPLAT_ELEMENT(element)                                  \
2971     (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
2972 #endif
2973 #define VSPLT(suffix, element)                                          \
2974     void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2975     {                                                                   \
2976         uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2977         int i;                                                          \
2978                                                                         \
2979         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2980             r->element[i] = s;                                          \
2981         }                                                               \
2982     }
2983 VSPLT(b, u8)
2984 VSPLT(h, u16)
2985 VSPLT(w, u32)
2986 #undef VSPLT
2987 #undef SPLAT_ELEMENT
2988 #undef _SPLAT_MASKED
2989
2990 #define VSPLTI(suffix, element, splat_type)                     \
2991     void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat)   \
2992     {                                                           \
2993         splat_type x = (int8_t)(splat << 3) >> 3;               \
2994         int i;                                                  \
2995                                                                 \
2996         for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
2997             r->element[i] = x;                                  \
2998         }                                                       \
2999     }
3000 VSPLTI(b, s8, int8_t)
3001 VSPLTI(h, s16, int16_t)
3002 VSPLTI(w, s32, int32_t)
3003 #undef VSPLTI
3004
3005 #define VSR(suffix, element)                                            \
3006     void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
3007     {                                                                   \
3008         int i;                                                          \
3009                                                                         \
3010         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
3011             unsigned int mask = ((1 <<                                  \
3012                                   (3 + (sizeof(a->element[0]) >> 1)))   \
3013                                  - 1);                                  \
3014             unsigned int shift = b->element[i] & mask;                  \
3015                                                                         \
3016             r->element[i] = a->element[i] >> shift;                     \
3017         }                                                               \
3018     }
3019 VSR(ab, s8)
3020 VSR(ah, s16)
3021 VSR(aw, s32)
3022 VSR(b, u8)
3023 VSR(h, u16)
3024 VSR(w, u32)
3025 #undef VSR
3026
3027 void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3028 {
3029     int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
3030
3031 #if defined(HOST_WORDS_BIGENDIAN)
3032     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
3033     memset(&r->u8[0], 0, sh);
3034 #else
3035     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
3036     memset(&r->u8[16 - sh], 0, sh);
3037 #endif
3038 }
3039
3040 void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3041 {
3042     int i;
3043
3044     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
3045         r->u32[i] = a->u32[i] >= b->u32[i];
3046     }
3047 }
3048
3049 void helper_vsumsws(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3050 {
3051     int64_t t;
3052     int i, upper;
3053     ppc_avr_t result;
3054     int sat = 0;
3055
3056 #if defined(HOST_WORDS_BIGENDIAN)
3057     upper = ARRAY_SIZE(r->s32)-1;
3058 #else
3059     upper = 0;
3060 #endif
3061     t = (int64_t)b->s32[upper];
3062     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
3063         t += a->s32[i];
3064         result.s32[i] = 0;
3065     }
3066     result.s32[upper] = cvtsdsw(t, &sat);
3067     *r = result;
3068
3069     if (sat) {
3070         env->vscr |= (1 << VSCR_SAT);
3071     }
3072 }
3073
3074 void helper_vsum2sws(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3075 {
3076     int i, j, upper;
3077     ppc_avr_t result;
3078     int sat = 0;
3079
3080 #if defined(HOST_WORDS_BIGENDIAN)
3081     upper = 1;
3082 #else
3083     upper = 0;
3084 #endif
3085     for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
3086         int64_t t = (int64_t)b->s32[upper + i * 2];
3087
3088         result.u64[i] = 0;
3089         for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
3090             t += a->s32[2 * i + j];
3091         }
3092         result.s32[upper + i * 2] = cvtsdsw(t, &sat);
3093     }
3094
3095     *r = result;
3096     if (sat) {
3097         env->vscr |= (1 << VSCR_SAT);
3098     }
3099 }
3100
3101 void helper_vsum4sbs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3102 {
3103     int i, j;
3104     int sat = 0;
3105
3106     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
3107         int64_t t = (int64_t)b->s32[i];
3108
3109         for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
3110             t += a->s8[4 * i + j];
3111         }
3112         r->s32[i] = cvtsdsw(t, &sat);
3113     }
3114
3115     if (sat) {
3116         env->vscr |= (1 << VSCR_SAT);
3117     }
3118 }
3119
3120 void helper_vsum4shs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3121 {
3122     int sat = 0;
3123     int i;
3124
3125     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
3126         int64_t t = (int64_t)b->s32[i];
3127
3128         t += a->s16[2 * i] + a->s16[2 * i + 1];
3129         r->s32[i] = cvtsdsw(t, &sat);
3130     }
3131
3132     if (sat) {
3133         env->vscr |= (1 << VSCR_SAT);
3134     }
3135 }
3136
3137 void helper_vsum4ubs(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
3138 {
3139     int i, j;
3140     int sat = 0;
3141
3142     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
3143         uint64_t t = (uint64_t)b->u32[i];
3144
3145         for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
3146             t += a->u8[4 * i + j];
3147         }
3148         r->u32[i] = cvtuduw(t, &sat);
3149     }
3150
3151     if (sat) {
3152         env->vscr |= (1 << VSCR_SAT);
3153     }
3154 }
3155
3156 #if defined(HOST_WORDS_BIGENDIAN)
3157 #define UPKHI 1
3158 #define UPKLO 0
3159 #else
3160 #define UPKHI 0
3161 #define UPKLO 1
3162 #endif
3163 #define VUPKPX(suffix, hi)                                              \
3164     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
3165     {                                                                   \
3166         int i;                                                          \
3167         ppc_avr_t result;                                               \
3168                                                                         \
3169         for (i = 0; i < ARRAY_SIZE(r->u32); i++) {                      \
3170             uint16_t e = b->u16[hi ? i : i+4];                          \
3171             uint8_t a = (e >> 15) ? 0xff : 0;                           \
3172             uint8_t r = (e >> 10) & 0x1f;                               \
3173             uint8_t g = (e >> 5) & 0x1f;                                \
3174             uint8_t b = e & 0x1f;                                       \
3175                                                                         \
3176             result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
3177         }                                                               \
3178         *r = result;                                                    \
3179     }
3180 VUPKPX(lpx, UPKLO)
3181 VUPKPX(hpx, UPKHI)
3182 #undef VUPKPX
3183
3184 #define VUPK(suffix, unpacked, packee, hi)                              \
3185     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
3186     {                                                                   \
3187         int i;                                                          \
3188         ppc_avr_t result;                                               \
3189                                                                         \
3190         if (hi) {                                                       \
3191             for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
3192                 result.unpacked[i] = b->packee[i];                      \
3193             }                                                           \
3194         } else {                                                        \
3195             for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
3196                  i++) {                                                 \
3197                 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
3198             }                                                           \
3199         }                                                               \
3200         *r = result;                                                    \
3201     }
3202 VUPK(hsb, s16, s8, UPKHI)
3203 VUPK(hsh, s32, s16, UPKHI)
3204 VUPK(lsb, s16, s8, UPKLO)
3205 VUPK(lsh, s32, s16, UPKLO)
3206 #undef VUPK
3207 #undef UPKHI
3208 #undef UPKLO
3209
3210 #undef DO_HANDLE_NAN
3211 #undef HANDLE_NAN1
3212 #undef HANDLE_NAN2
3213 #undef HANDLE_NAN3
3214 #undef VECTOR_FOR_INORDER_I
3215 #undef HI_IDX
3216 #undef LO_IDX
3217
3218 /*****************************************************************************/
3219 /* SPE extension helpers */
3220 /* Use a table to make this quicker */
3221 static uint8_t hbrev[16] = {
3222     0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
3223     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
3224 };
3225
3226 static inline uint8_t byte_reverse(uint8_t val)
3227 {
3228     return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
3229 }
3230
3231 static inline uint32_t word_reverse(uint32_t val)
3232 {
3233     return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
3234         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
3235 }
3236
3237 #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
3238 target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
3239 {
3240     uint32_t a, b, d, mask;
3241
3242     mask = UINT32_MAX >> (32 - MASKBITS);
3243     a = arg1 & mask;
3244     b = arg2 & mask;
3245     d = word_reverse(1 + word_reverse(a | ~b));
3246     return (arg1 & ~mask) | (d & b);
3247 }
3248
3249 uint32_t helper_cntlsw32(uint32_t val)
3250 {
3251     if (val & 0x80000000) {
3252         return clz32(~val);
3253     } else {
3254         return clz32(val);
3255     }
3256 }
3257
3258 uint32_t helper_cntlzw32(uint32_t val)
3259 {
3260     return clz32(val);
3261 }
3262
3263 /* Single-precision floating-point conversions */
3264 static inline uint32_t efscfsi(uint32_t val)
3265 {
3266     CPU_FloatU u;
3267
3268     u.f = int32_to_float32(val, &env->vec_status);
3269
3270     return u.l;
3271 }
3272
3273 static inline uint32_t efscfui(uint32_t val)
3274 {
3275     CPU_FloatU u;
3276
3277     u.f = uint32_to_float32(val, &env->vec_status);
3278
3279     return u.l;
3280 }
3281
3282 static inline int32_t efsctsi(uint32_t val)
3283 {
3284     CPU_FloatU u;
3285
3286     u.l = val;
3287     /* NaN are not treated the same way IEEE 754 does */
3288     if (unlikely(float32_is_quiet_nan(u.f))) {
3289         return 0;
3290     }
3291
3292     return float32_to_int32(u.f, &env->vec_status);
3293 }
3294
3295 static inline uint32_t efsctui(uint32_t val)
3296 {
3297     CPU_FloatU u;
3298
3299     u.l = val;
3300     /* NaN are not treated the same way IEEE 754 does */
3301     if (unlikely(float32_is_quiet_nan(u.f))) {
3302         return 0;
3303     }
3304
3305     return float32_to_uint32(u.f, &env->vec_status);
3306 }
3307
3308 static inline uint32_t efsctsiz(uint32_t val)
3309 {
3310     CPU_FloatU u;
3311
3312     u.l = val;
3313     /* NaN are not treated the same way IEEE 754 does */
3314     if (unlikely(float32_is_quiet_nan(u.f))) {
3315         return 0;
3316     }
3317
3318     return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3319 }
3320
3321 static inline uint32_t efsctuiz(uint32_t val)
3322 {
3323     CPU_FloatU u;
3324
3325     u.l = val;
3326     /* NaN are not treated the same way IEEE 754 does */
3327     if (unlikely(float32_is_quiet_nan(u.f))) {
3328         return 0;
3329     }
3330
3331     return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3332 }
3333
3334 static inline uint32_t efscfsf(uint32_t val)
3335 {
3336     CPU_FloatU u;
3337     float32 tmp;
3338
3339     u.f = int32_to_float32(val, &env->vec_status);
3340     tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3341     u.f = float32_div(u.f, tmp, &env->vec_status);
3342
3343     return u.l;
3344 }
3345
3346 static inline uint32_t efscfuf(uint32_t val)
3347 {
3348     CPU_FloatU u;
3349     float32 tmp;
3350
3351     u.f = uint32_to_float32(val, &env->vec_status);
3352     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3353     u.f = float32_div(u.f, tmp, &env->vec_status);
3354
3355     return u.l;
3356 }
3357
3358 static inline uint32_t efsctsf(uint32_t val)
3359 {
3360     CPU_FloatU u;
3361     float32 tmp;
3362
3363     u.l = val;
3364     /* NaN are not treated the same way IEEE 754 does */
3365     if (unlikely(float32_is_quiet_nan(u.f))) {
3366         return 0;
3367     }
3368     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3369     u.f = float32_mul(u.f, tmp, &env->vec_status);
3370
3371     return float32_to_int32(u.f, &env->vec_status);
3372 }
3373
3374 static inline uint32_t efsctuf(uint32_t val)
3375 {
3376     CPU_FloatU u;
3377     float32 tmp;
3378
3379     u.l = val;
3380     /* NaN are not treated the same way IEEE 754 does */
3381     if (unlikely(float32_is_quiet_nan(u.f))) {
3382         return 0;
3383     }
3384     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3385     u.f = float32_mul(u.f, tmp, &env->vec_status);
3386
3387     return float32_to_uint32(u.f, &env->vec_status);
3388 }
3389
3390 #define HELPER_SPE_SINGLE_CONV(name)            \
3391     uint32_t helper_e##name(uint32_t val)       \
3392     {                                           \
3393         return e##name(val);                    \
3394     }
3395 /* efscfsi */
3396 HELPER_SPE_SINGLE_CONV(fscfsi);
3397 /* efscfui */
3398 HELPER_SPE_SINGLE_CONV(fscfui);
3399 /* efscfuf */
3400 HELPER_SPE_SINGLE_CONV(fscfuf);
3401 /* efscfsf */
3402 HELPER_SPE_SINGLE_CONV(fscfsf);
3403 /* efsctsi */
3404 HELPER_SPE_SINGLE_CONV(fsctsi);
3405 /* efsctui */
3406 HELPER_SPE_SINGLE_CONV(fsctui);
3407 /* efsctsiz */
3408 HELPER_SPE_SINGLE_CONV(fsctsiz);
3409 /* efsctuiz */
3410 HELPER_SPE_SINGLE_CONV(fsctuiz);
3411 /* efsctsf */
3412 HELPER_SPE_SINGLE_CONV(fsctsf);
3413 /* efsctuf */
3414 HELPER_SPE_SINGLE_CONV(fsctuf);
3415
3416 #define HELPER_SPE_VECTOR_CONV(name)                    \
3417     uint64_t helper_ev##name(uint64_t val)              \
3418     {                                                   \
3419         return ((uint64_t)e##name(val >> 32) << 32) |   \
3420             (uint64_t)e##name(val);                     \
3421     }
3422 /* evfscfsi */
3423 HELPER_SPE_VECTOR_CONV(fscfsi);
3424 /* evfscfui */
3425 HELPER_SPE_VECTOR_CONV(fscfui);
3426 /* evfscfuf */
3427 HELPER_SPE_VECTOR_CONV(fscfuf);
3428 /* evfscfsf */
3429 HELPER_SPE_VECTOR_CONV(fscfsf);
3430 /* evfsctsi */
3431 HELPER_SPE_VECTOR_CONV(fsctsi);
3432 /* evfsctui */
3433 HELPER_SPE_VECTOR_CONV(fsctui);
3434 /* evfsctsiz */
3435 HELPER_SPE_VECTOR_CONV(fsctsiz);
3436 /* evfsctuiz */
3437 HELPER_SPE_VECTOR_CONV(fsctuiz);
3438 /* evfsctsf */
3439 HELPER_SPE_VECTOR_CONV(fsctsf);
3440 /* evfsctuf */
3441 HELPER_SPE_VECTOR_CONV(fsctuf);
3442
3443 /* Single-precision floating-point arithmetic */
3444 static inline uint32_t efsadd(uint32_t op1, uint32_t op2)
3445 {
3446     CPU_FloatU u1, u2;
3447
3448     u1.l = op1;
3449     u2.l = op2;
3450     u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3451     return u1.l;
3452 }
3453
3454 static inline uint32_t efssub(uint32_t op1, uint32_t op2)
3455 {
3456     CPU_FloatU u1, u2;
3457
3458     u1.l = op1;
3459     u2.l = op2;
3460     u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3461     return u1.l;
3462 }
3463
3464 static inline uint32_t efsmul(uint32_t op1, uint32_t op2)
3465 {
3466     CPU_FloatU u1, u2;
3467
3468     u1.l = op1;
3469     u2.l = op2;
3470     u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3471     return u1.l;
3472 }
3473
3474 static inline uint32_t efsdiv(uint32_t op1, uint32_t op2)
3475 {
3476     CPU_FloatU u1, u2;
3477
3478     u1.l = op1;
3479     u2.l = op2;
3480     u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3481     return u1.l;
3482 }
3483
3484 #define HELPER_SPE_SINGLE_ARITH(name)                   \
3485     uint32_t helper_e##name(uint32_t op1, uint32_t op2) \
3486     {                                                   \
3487         return e##name(op1, op2);                       \
3488     }
3489 /* efsadd */
3490 HELPER_SPE_SINGLE_ARITH(fsadd);
3491 /* efssub */
3492 HELPER_SPE_SINGLE_ARITH(fssub);
3493 /* efsmul */
3494 HELPER_SPE_SINGLE_ARITH(fsmul);
3495 /* efsdiv */
3496 HELPER_SPE_SINGLE_ARITH(fsdiv);
3497
3498 #define HELPER_SPE_VECTOR_ARITH(name)                                   \
3499     uint64_t helper_ev##name(uint64_t op1, uint64_t op2)                \
3500     {                                                                   \
3501         return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |        \
3502             (uint64_t)e##name(op1, op2);                                \
3503     }
3504 /* evfsadd */
3505 HELPER_SPE_VECTOR_ARITH(fsadd);
3506 /* evfssub */
3507 HELPER_SPE_VECTOR_ARITH(fssub);
3508 /* evfsmul */
3509 HELPER_SPE_VECTOR_ARITH(fsmul);
3510 /* evfsdiv */
3511 HELPER_SPE_VECTOR_ARITH(fsdiv);
3512
3513 /* Single-precision floating-point comparisons */
3514 static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
3515 {
3516     CPU_FloatU u1, u2;
3517
3518     u1.l = op1;
3519     u2.l = op2;
3520     return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3521 }
3522
3523 static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
3524 {
3525     CPU_FloatU u1, u2;
3526
3527     u1.l = op1;
3528     u2.l = op2;
3529     return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3530 }
3531
3532 static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
3533 {
3534     CPU_FloatU u1, u2;
3535
3536     u1.l = op1;
3537     u2.l = op2;
3538     return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3539 }
3540
3541 static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
3542 {
3543     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
3544     return efscmplt(op1, op2);
3545 }
3546
3547 static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
3548 {
3549     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
3550     return efscmpgt(op1, op2);
3551 }
3552
3553 static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
3554 {
3555     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
3556     return efscmpeq(op1, op2);
3557 }
3558
3559 #define HELPER_SINGLE_SPE_CMP(name)                     \
3560     uint32_t helper_e##name(uint32_t op1, uint32_t op2) \
3561     {                                                   \
3562         return e##name(op1, op2) << 2;                  \
3563     }
3564 /* efststlt */
3565 HELPER_SINGLE_SPE_CMP(fststlt);
3566 /* efststgt */
3567 HELPER_SINGLE_SPE_CMP(fststgt);
3568 /* efststeq */
3569 HELPER_SINGLE_SPE_CMP(fststeq);
3570 /* efscmplt */
3571 HELPER_SINGLE_SPE_CMP(fscmplt);
3572 /* efscmpgt */
3573 HELPER_SINGLE_SPE_CMP(fscmpgt);
3574 /* efscmpeq */
3575 HELPER_SINGLE_SPE_CMP(fscmpeq);
3576
3577 static inline uint32_t evcmp_merge(int t0, int t1)
3578 {
3579     return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3580 }
3581
3582 #define HELPER_VECTOR_SPE_CMP(name)                                     \
3583     uint32_t helper_ev##name(uint64_t op1, uint64_t op2)                \
3584     {                                                                   \
3585         return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2)); \
3586     }
3587 /* evfststlt */
3588 HELPER_VECTOR_SPE_CMP(fststlt);
3589 /* evfststgt */
3590 HELPER_VECTOR_SPE_CMP(fststgt);
3591 /* evfststeq */
3592 HELPER_VECTOR_SPE_CMP(fststeq);
3593 /* evfscmplt */
3594 HELPER_VECTOR_SPE_CMP(fscmplt);
3595 /* evfscmpgt */
3596 HELPER_VECTOR_SPE_CMP(fscmpgt);
3597 /* evfscmpeq */
3598 HELPER_VECTOR_SPE_CMP(fscmpeq);
3599
3600 /* Double-precision floating-point conversion */
3601 uint64_t helper_efdcfsi(uint32_t val)
3602 {
3603     CPU_DoubleU u;
3604
3605     u.d = int32_to_float64(val, &env->vec_status);
3606
3607     return u.ll;
3608 }
3609
3610 uint64_t helper_efdcfsid(uint64_t val)
3611 {
3612     CPU_DoubleU u;
3613
3614     u.d = int64_to_float64(val, &env->vec_status);
3615
3616     return u.ll;
3617 }
3618
3619 uint64_t helper_efdcfui(uint32_t val)
3620 {
3621     CPU_DoubleU u;
3622
3623     u.d = uint32_to_float64(val, &env->vec_status);
3624
3625     return u.ll;
3626 }
3627
3628 uint64_t helper_efdcfuid(uint64_t val)
3629 {
3630     CPU_DoubleU u;
3631
3632     u.d = uint64_to_float64(val, &env->vec_status);
3633
3634     return u.ll;
3635 }
3636
3637 uint32_t helper_efdctsi(uint64_t val)
3638 {
3639     CPU_DoubleU u;
3640
3641     u.ll = val;
3642     /* NaN are not treated the same way IEEE 754 does */
3643     if (unlikely(float64_is_any_nan(u.d))) {
3644         return 0;
3645     }
3646
3647     return float64_to_int32(u.d, &env->vec_status);
3648 }
3649
3650 uint32_t helper_efdctui(uint64_t val)
3651 {
3652     CPU_DoubleU u;
3653
3654     u.ll = val;
3655     /* NaN are not treated the same way IEEE 754 does */
3656     if (unlikely(float64_is_any_nan(u.d))) {
3657         return 0;
3658     }
3659
3660     return float64_to_uint32(u.d, &env->vec_status);
3661 }
3662
3663 uint32_t helper_efdctsiz(uint64_t val)
3664 {
3665     CPU_DoubleU u;
3666
3667     u.ll = val;
3668     /* NaN are not treated the same way IEEE 754 does */
3669     if (unlikely(float64_is_any_nan(u.d))) {
3670         return 0;
3671     }
3672
3673     return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3674 }
3675
3676 uint64_t helper_efdctsidz(uint64_t val)
3677 {
3678     CPU_DoubleU u;
3679
3680     u.ll = val;
3681     /* NaN are not treated the same way IEEE 754 does */
3682     if (unlikely(float64_is_any_nan(u.d))) {
3683         return 0;
3684     }
3685
3686     return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3687 }
3688
3689 uint32_t helper_efdctuiz(uint64_t val)
3690 {
3691     CPU_DoubleU u;
3692
3693     u.ll = val;
3694     /* NaN are not treated the same way IEEE 754 does */
3695     if (unlikely(float64_is_any_nan(u.d))) {
3696         return 0;
3697     }
3698
3699     return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3700 }
3701
3702 uint64_t helper_efdctuidz(uint64_t val)
3703 {
3704     CPU_DoubleU u;
3705
3706     u.ll = val;
3707     /* NaN are not treated the same way IEEE 754 does */
3708     if (unlikely(float64_is_any_nan(u.d))) {
3709         return 0;
3710     }
3711
3712     return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3713 }
3714
3715 uint64_t helper_efdcfsf(uint32_t val)
3716 {
3717     CPU_DoubleU u;
3718     float64 tmp;
3719
3720     u.d = int32_to_float64(val, &env->vec_status);
3721     tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3722     u.d = float64_div(u.d, tmp, &env->vec_status);
3723
3724     return u.ll;
3725 }
3726
3727 uint64_t helper_efdcfuf(uint32_t val)
3728 {
3729     CPU_DoubleU u;
3730     float64 tmp;
3731
3732     u.d = uint32_to_float64(val, &env->vec_status);
3733     tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3734     u.d = float64_div(u.d, tmp, &env->vec_status);
3735
3736     return u.ll;
3737 }
3738
3739 uint32_t helper_efdctsf(uint64_t val)
3740 {
3741     CPU_DoubleU u;
3742     float64 tmp;
3743
3744     u.ll = val;
3745     /* NaN are not treated the same way IEEE 754 does */
3746     if (unlikely(float64_is_any_nan(u.d))) {
3747         return 0;
3748     }
3749     tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3750     u.d = float64_mul(u.d, tmp, &env->vec_status);
3751
3752     return float64_to_int32(u.d, &env->vec_status);
3753 }
3754
3755 uint32_t helper_efdctuf(uint64_t val)
3756 {
3757     CPU_DoubleU u;
3758     float64 tmp;
3759
3760     u.ll = val;
3761     /* NaN are not treated the same way IEEE 754 does */
3762     if (unlikely(float64_is_any_nan(u.d))) {
3763         return 0;
3764     }
3765     tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3766     u.d = float64_mul(u.d, tmp, &env->vec_status);
3767
3768     return float64_to_uint32(u.d, &env->vec_status);
3769 }
3770
3771 uint32_t helper_efscfd(uint64_t val)
3772 {
3773     CPU_DoubleU u1;
3774     CPU_FloatU u2;
3775
3776     u1.ll = val;
3777     u2.f = float64_to_float32(u1.d, &env->vec_status);
3778
3779     return u2.l;
3780 }
3781
3782 uint64_t helper_efdcfs(uint32_t val)
3783 {
3784     CPU_DoubleU u2;
3785     CPU_FloatU u1;
3786
3787     u1.l = val;
3788     u2.d = float32_to_float64(u1.f, &env->vec_status);
3789
3790     return u2.ll;
3791 }
3792
3793 /* Double precision fixed-point arithmetic */
3794 uint64_t helper_efdadd(uint64_t op1, uint64_t op2)
3795 {
3796     CPU_DoubleU u1, u2;
3797
3798     u1.ll = op1;
3799     u2.ll = op2;
3800     u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3801     return u1.ll;
3802 }
3803
3804 uint64_t helper_efdsub(uint64_t op1, uint64_t op2)
3805 {
3806     CPU_DoubleU u1, u2;
3807
3808     u1.ll = op1;
3809     u2.ll = op2;
3810     u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3811     return u1.ll;
3812 }
3813
3814 uint64_t helper_efdmul(uint64_t op1, uint64_t op2)
3815 {
3816     CPU_DoubleU u1, u2;
3817
3818     u1.ll = op1;
3819     u2.ll = op2;
3820     u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3821     return u1.ll;
3822 }
3823
3824 uint64_t helper_efddiv(uint64_t op1, uint64_t op2)
3825 {
3826     CPU_DoubleU u1, u2;
3827
3828     u1.ll = op1;
3829     u2.ll = op2;
3830     u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3831     return u1.ll;
3832 }
3833
3834 /* Double precision floating point helpers */
3835 uint32_t helper_efdtstlt(uint64_t op1, uint64_t op2)
3836 {
3837     CPU_DoubleU u1, u2;
3838
3839     u1.ll = op1;
3840     u2.ll = op2;
3841     return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3842 }
3843
3844 uint32_t helper_efdtstgt(uint64_t op1, uint64_t op2)
3845 {
3846     CPU_DoubleU u1, u2;
3847
3848     u1.ll = op1;
3849     u2.ll = op2;
3850     return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3851 }
3852
3853 uint32_t helper_efdtsteq(uint64_t op1, uint64_t op2)
3854 {
3855     CPU_DoubleU u1, u2;
3856
3857     u1.ll = op1;
3858     u2.ll = op2;
3859     return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3860 }
3861
3862 uint32_t helper_efdcmplt(uint64_t op1, uint64_t op2)
3863 {
3864     /* XXX: TODO: test special values (NaN, infinites, ...) */
3865     return helper_efdtstlt(op1, op2);
3866 }
3867
3868 uint32_t helper_efdcmpgt(uint64_t op1, uint64_t op2)
3869 {
3870     /* XXX: TODO: test special values (NaN, infinites, ...) */
3871     return helper_efdtstgt(op1, op2);
3872 }
3873
3874 uint32_t helper_efdcmpeq(uint64_t op1, uint64_t op2)
3875 {
3876     /* XXX: TODO: test special values (NaN, infinites, ...) */
3877     return helper_efdtsteq(op1, op2);
3878 }
3879
3880 /*****************************************************************************/
3881 /* Softmmu support */
3882 #if !defined(CONFIG_USER_ONLY)
3883
3884 #define MMUSUFFIX _mmu
3885
3886 #define SHIFT 0
3887 #include "softmmu_template.h"
3888
3889 #define SHIFT 1
3890 #include "softmmu_template.h"
3891
3892 #define SHIFT 2
3893 #include "softmmu_template.h"
3894
3895 #define SHIFT 3
3896 #include "softmmu_template.h"
3897
3898 /* try to fill the TLB and return an exception if error. If retaddr is
3899    NULL, it means that the function was called in C code (i.e. not
3900    from generated code or from helper.c) */
3901 /* XXX: fix it to restore all registers */
3902 void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
3903               uintptr_t retaddr)
3904 {
3905     TranslationBlock *tb;
3906     CPUPPCState *saved_env;
3907     int ret;
3908
3909     saved_env = env;
3910     env = env1;
3911     ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
3912     if (unlikely(ret != 0)) {
3913         if (likely(retaddr)) {
3914             /* now we have a real cpu fault */
3915             tb = tb_find_pc(retaddr);
3916             if (likely(tb)) {
3917                 /* the PC is inside the translated code. It means that we have
3918                    a virtual CPU fault */
3919                 cpu_restore_state(tb, env, retaddr);
3920             }
3921         }
3922         helper_raise_exception_err(env->exception_index, env->error_code);
3923     }
3924     env = saved_env;
3925 }
3926
3927 /* Segment registers load and store */
3928 target_ulong helper_load_sr(target_ulong sr_num)
3929 {
3930 #if defined(TARGET_PPC64)
3931     if (env->mmu_model & POWERPC_MMU_64) {
3932         return ppc_load_sr(env, sr_num);
3933     }
3934 #endif
3935     return env->sr[sr_num];
3936 }
3937
3938 void helper_store_sr(target_ulong sr_num, target_ulong val)
3939 {
3940     ppc_store_sr(env, sr_num, val);
3941 }
3942
3943 /* SLB management */
3944 #if defined(TARGET_PPC64)
3945 void helper_store_slb(target_ulong rb, target_ulong rs)
3946 {
3947     if (ppc_store_slb(env, rb, rs) < 0) {
3948         helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
3949     }
3950 }
3951
3952 target_ulong helper_load_slb_esid(target_ulong rb)
3953 {
3954     target_ulong rt;
3955
3956     if (ppc_load_slb_esid(env, rb, &rt) < 0) {
3957         helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
3958     }
3959     return rt;
3960 }
3961
3962 target_ulong helper_load_slb_vsid(target_ulong rb)
3963 {
3964     target_ulong rt;
3965
3966     if (ppc_load_slb_vsid(env, rb, &rt) < 0) {
3967         helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_INVAL);
3968     }
3969     return rt;
3970 }
3971
3972 void helper_slbia(void)
3973 {
3974     ppc_slb_invalidate_all(env);
3975 }
3976
3977 void helper_slbie(target_ulong addr)
3978 {
3979     ppc_slb_invalidate_one(env, addr);
3980 }
3981
3982 #endif /* defined(TARGET_PPC64) */
3983
3984 /* TLB management */
3985 void helper_tlbia(void)
3986 {
3987     ppc_tlb_invalidate_all(env);
3988 }
3989
3990 void helper_tlbie(target_ulong addr)
3991 {
3992     ppc_tlb_invalidate_one(env, addr);
3993 }
3994
3995 /* Software driven TLBs management */
3996 /* PowerPC 602/603 software TLB load instructions helpers */
3997 static void do_6xx_tlb(target_ulong new_EPN, int is_code)
3998 {
3999     target_ulong RPN, CMP, EPN;
4000     int way;
4001
4002     RPN = env->spr[SPR_RPA];
4003     if (is_code) {
4004         CMP = env->spr[SPR_ICMP];
4005         EPN = env->spr[SPR_IMISS];
4006     } else {
4007         CMP = env->spr[SPR_DCMP];
4008         EPN = env->spr[SPR_DMISS];
4009     }
4010     way = (env->spr[SPR_SRR1] >> 17) & 1;
4011     (void)EPN; /* avoid a compiler warning */
4012     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
4013               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
4014               RPN, way);
4015     /* Store this TLB */
4016     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
4017                      way, is_code, CMP, RPN);
4018 }
4019
4020 void helper_6xx_tlbd(target_ulong EPN)
4021 {
4022     do_6xx_tlb(EPN, 0);
4023 }
4024
4025 void helper_6xx_tlbi(target_ulong EPN)
4026 {
4027     do_6xx_tlb(EPN, 1);
4028 }
4029
4030 /* PowerPC 74xx software TLB load instructions helpers */
4031 static void do_74xx_tlb(target_ulong new_EPN, int is_code)
4032 {
4033     target_ulong RPN, CMP, EPN;
4034     int way;
4035
4036     RPN = env->spr[SPR_PTELO];
4037     CMP = env->spr[SPR_PTEHI];
4038     EPN = env->spr[SPR_TLBMISS] & ~0x3;
4039     way = env->spr[SPR_TLBMISS] & 0x3;
4040     (void)EPN; /* avoid a compiler warning */
4041     LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
4042               " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
4043               RPN, way);
4044     /* Store this TLB */
4045     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
4046                      way, is_code, CMP, RPN);
4047 }
4048
4049 void helper_74xx_tlbd(target_ulong EPN)
4050 {
4051     do_74xx_tlb(EPN, 0);
4052 }
4053
4054 void helper_74xx_tlbi(target_ulong EPN)
4055 {
4056     do_74xx_tlb(EPN, 1);
4057 }
4058
4059 static inline target_ulong booke_tlb_to_page_size(int size)
4060 {
4061     return 1024 << (2 * size);
4062 }
4063
4064 static inline int booke_page_size_to_tlb(target_ulong page_size)
4065 {
4066     int size;
4067
4068     switch (page_size) {
4069     case 0x00000400UL:
4070         size = 0x0;
4071         break;
4072     case 0x00001000UL:
4073         size = 0x1;
4074         break;
4075     case 0x00004000UL:
4076         size = 0x2;
4077         break;
4078     case 0x00010000UL:
4079         size = 0x3;
4080         break;
4081     case 0x00040000UL:
4082         size = 0x4;
4083         break;
4084     case 0x00100000UL:
4085         size = 0x5;
4086         break;
4087     case 0x00400000UL:
4088         size = 0x6;
4089         break;
4090     case 0x01000000UL:
4091         size = 0x7;
4092         break;
4093     case 0x04000000UL:
4094         size = 0x8;
4095         break;
4096     case 0x10000000UL:
4097         size = 0x9;
4098         break;
4099     case 0x40000000UL:
4100         size = 0xA;
4101         break;
4102 #if defined(TARGET_PPC64)
4103     case 0x000100000000ULL:
4104         size = 0xB;
4105         break;
4106     case 0x000400000000ULL:
4107         size = 0xC;
4108         break;
4109     case 0x001000000000ULL:
4110         size = 0xD;
4111         break;
4112     case 0x004000000000ULL:
4113         size = 0xE;
4114         break;
4115     case 0x010000000000ULL:
4116         size = 0xF;
4117         break;
4118 #endif
4119     default:
4120         size = -1;
4121         break;
4122     }
4123
4124     return size;
4125 }
4126
4127 /* Helpers for 4xx TLB management */
4128 #define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
4129
4130 #define PPC4XX_TLBHI_V              0x00000040
4131 #define PPC4XX_TLBHI_E              0x00000020
4132 #define PPC4XX_TLBHI_SIZE_MIN       0
4133 #define PPC4XX_TLBHI_SIZE_MAX       7
4134 #define PPC4XX_TLBHI_SIZE_DEFAULT   1
4135 #define PPC4XX_TLBHI_SIZE_SHIFT     7
4136 #define PPC4XX_TLBHI_SIZE_MASK      0x00000007
4137
4138 #define PPC4XX_TLBLO_EX             0x00000200
4139 #define PPC4XX_TLBLO_WR             0x00000100
4140 #define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
4141 #define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
4142
4143 target_ulong helper_4xx_tlbre_hi(target_ulong entry)
4144 {
4145     ppcemb_tlb_t *tlb;
4146     target_ulong ret;
4147     int size;
4148
4149     entry &= PPC4XX_TLB_ENTRY_MASK;
4150     tlb = &env->tlb.tlbe[entry];
4151     ret = tlb->EPN;
4152     if (tlb->prot & PAGE_VALID) {
4153         ret |= PPC4XX_TLBHI_V;
4154     }
4155     size = booke_page_size_to_tlb(tlb->size);
4156     if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
4157         size = PPC4XX_TLBHI_SIZE_DEFAULT;
4158     }
4159     ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
4160     env->spr[SPR_40x_PID] = tlb->PID;
4161     return ret;
4162 }
4163
4164 target_ulong helper_4xx_tlbre_lo(target_ulong entry)
4165 {
4166     ppcemb_tlb_t *tlb;
4167     target_ulong ret;
4168
4169     entry &= PPC4XX_TLB_ENTRY_MASK;
4170     tlb = &env->tlb.tlbe[entry];
4171     ret = tlb->RPN;
4172     if (tlb->prot & PAGE_EXEC) {
4173         ret |= PPC4XX_TLBLO_EX;
4174     }
4175     if (tlb->prot & PAGE_WRITE) {
4176         ret |= PPC4XX_TLBLO_WR;
4177     }
4178     return ret;
4179 }
4180
4181 void helper_4xx_tlbwe_hi(target_ulong entry, target_ulong val)
4182 {
4183     ppcemb_tlb_t *tlb;
4184     target_ulong page, end;
4185
4186     LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
4187               val);
4188     entry &= PPC4XX_TLB_ENTRY_MASK;
4189     tlb = &env->tlb.tlbe[entry];
4190     /* Invalidate previous TLB (if it's valid) */
4191     if (tlb->prot & PAGE_VALID) {
4192         end = tlb->EPN + tlb->size;
4193         LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
4194                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
4195         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
4196             tlb_flush_page(env, page);
4197         }
4198     }
4199     tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
4200                                        & PPC4XX_TLBHI_SIZE_MASK);
4201     /* We cannot handle TLB size < TARGET_PAGE_SIZE.
4202      * If this ever occurs, one should use the ppcemb target instead
4203      * of the ppc or ppc64 one
4204      */
4205     if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
4206         cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
4207                   "are not supported (%d)\n",
4208                   tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
4209     }
4210     tlb->EPN = val & ~(tlb->size - 1);
4211     if (val & PPC4XX_TLBHI_V) {
4212         tlb->prot |= PAGE_VALID;
4213         if (val & PPC4XX_TLBHI_E) {
4214             /* XXX: TO BE FIXED */
4215             cpu_abort(env,
4216                       "Little-endian TLB entries are not supported by now\n");
4217         }
4218     } else {
4219         tlb->prot &= ~PAGE_VALID;
4220     }
4221     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
4222     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
4223               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
4224               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
4225               tlb->prot & PAGE_READ ? 'r' : '-',
4226               tlb->prot & PAGE_WRITE ? 'w' : '-',
4227               tlb->prot & PAGE_EXEC ? 'x' : '-',
4228               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4229     /* Invalidate new TLB (if valid) */
4230     if (tlb->prot & PAGE_VALID) {
4231         end = tlb->EPN + tlb->size;
4232         LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
4233                   TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
4234         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
4235             tlb_flush_page(env, page);
4236         }
4237     }
4238 }
4239
4240 void helper_4xx_tlbwe_lo(target_ulong entry, target_ulong val)
4241 {
4242     ppcemb_tlb_t *tlb;
4243
4244     LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
4245               val);
4246     entry &= PPC4XX_TLB_ENTRY_MASK;
4247     tlb = &env->tlb.tlbe[entry];
4248     tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
4249     tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
4250     tlb->prot = PAGE_READ;
4251     if (val & PPC4XX_TLBLO_EX) {
4252         tlb->prot |= PAGE_EXEC;
4253     }
4254     if (val & PPC4XX_TLBLO_WR) {
4255         tlb->prot |= PAGE_WRITE;
4256     }
4257     LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
4258               " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
4259               (int)entry, tlb->RPN, tlb->EPN, tlb->size,
4260               tlb->prot & PAGE_READ ? 'r' : '-',
4261               tlb->prot & PAGE_WRITE ? 'w' : '-',
4262               tlb->prot & PAGE_EXEC ? 'x' : '-',
4263               tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4264 }
4265
4266 target_ulong helper_4xx_tlbsx(target_ulong address)
4267 {
4268     return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
4269 }
4270
4271 /* PowerPC 440 TLB management */
4272 void helper_440_tlbwe(uint32_t word, target_ulong entry, target_ulong value)
4273 {
4274     ppcemb_tlb_t *tlb;
4275     target_ulong EPN, RPN, size;
4276     int do_flush_tlbs;
4277
4278     LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
4279               __func__, word, (int)entry, value);
4280     do_flush_tlbs = 0;
4281     entry &= 0x3F;
4282     tlb = &env->tlb.tlbe[entry];
4283     switch (word) {
4284     default:
4285         /* Just here to please gcc */
4286     case 0:
4287         EPN = value & 0xFFFFFC00;
4288         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
4289             do_flush_tlbs = 1;
4290         }
4291         tlb->EPN = EPN;
4292         size = booke_tlb_to_page_size((value >> 4) & 0xF);
4293         if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
4294             do_flush_tlbs = 1;
4295         }
4296         tlb->size = size;
4297         tlb->attr &= ~0x1;
4298         tlb->attr |= (value >> 8) & 1;
4299         if (value & 0x200) {
4300             tlb->prot |= PAGE_VALID;
4301         } else {
4302             if (tlb->prot & PAGE_VALID) {
4303                 tlb->prot &= ~PAGE_VALID;
4304                 do_flush_tlbs = 1;
4305             }
4306         }
4307         tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
4308         if (do_flush_tlbs) {
4309             tlb_flush(env, 1);
4310         }
4311         break;
4312     case 1:
4313         RPN = value & 0xFFFFFC0F;
4314         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
4315             tlb_flush(env, 1);
4316         }
4317         tlb->RPN = RPN;
4318         break;
4319     case 2:
4320         tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
4321         tlb->prot = tlb->prot & PAGE_VALID;
4322         if (value & 0x1) {
4323             tlb->prot |= PAGE_READ << 4;
4324         }
4325         if (value & 0x2) {
4326             tlb->prot |= PAGE_WRITE << 4;
4327         }
4328         if (value & 0x4) {
4329             tlb->prot |= PAGE_EXEC << 4;
4330         }
4331         if (value & 0x8) {
4332             tlb->prot |= PAGE_READ;
4333         }
4334         if (value & 0x10) {
4335             tlb->prot |= PAGE_WRITE;
4336         }
4337         if (value & 0x20) {
4338             tlb->prot |= PAGE_EXEC;
4339         }
4340         break;
4341     }
4342 }
4343
4344 target_ulong helper_440_tlbre(uint32_t word, target_ulong entry)
4345 {
4346     ppcemb_tlb_t *tlb;
4347     target_ulong ret;
4348     int size;
4349
4350     entry &= 0x3F;
4351     tlb = &env->tlb.tlbe[entry];
4352     switch (word) {
4353     default:
4354         /* Just here to please gcc */
4355     case 0:
4356         ret = tlb->EPN;
4357         size = booke_page_size_to_tlb(tlb->size);
4358         if (size < 0 || size > 0xF) {
4359             size = 1;
4360         }
4361         ret |= size << 4;
4362         if (tlb->attr & 0x1) {
4363             ret |= 0x100;
4364         }
4365         if (tlb->prot & PAGE_VALID) {
4366             ret |= 0x200;
4367         }
4368         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
4369         env->spr[SPR_440_MMUCR] |= tlb->PID;
4370         break;
4371     case 1:
4372         ret = tlb->RPN;
4373         break;
4374     case 2:
4375         ret = tlb->attr & ~0x1;
4376         if (tlb->prot & (PAGE_READ << 4)) {
4377             ret |= 0x1;
4378         }
4379         if (tlb->prot & (PAGE_WRITE << 4)) {
4380             ret |= 0x2;
4381         }
4382         if (tlb->prot & (PAGE_EXEC << 4)) {
4383             ret |= 0x4;
4384         }
4385         if (tlb->prot & PAGE_READ) {
4386             ret |= 0x8;
4387         }
4388         if (tlb->prot & PAGE_WRITE) {
4389             ret |= 0x10;
4390         }
4391         if (tlb->prot & PAGE_EXEC) {
4392             ret |= 0x20;
4393         }
4394         break;
4395     }
4396     return ret;
4397 }
4398
4399 target_ulong helper_440_tlbsx(target_ulong address)
4400 {
4401     return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
4402 }
4403
4404 /* PowerPC BookE 2.06 TLB management */
4405
4406 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
4407 {
4408     uint32_t tlbncfg = 0;
4409     int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
4410     int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
4411     int tlb;
4412
4413     tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
4414     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
4415
4416     if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
4417         cpu_abort(env, "we don't support HES yet\n");
4418     }
4419
4420     return booke206_get_tlbm(env, tlb, ea, esel);
4421 }
4422
4423 void helper_booke_setpid(uint32_t pidn, target_ulong pid)
4424 {
4425     env->spr[pidn] = pid;
4426     /* changing PIDs mean we're in a different address space now */
4427     tlb_flush(env, 1);
4428 }
4429
4430 void helper_booke206_tlbwe(void)
4431 {
4432     uint32_t tlbncfg, tlbn;
4433     ppcmas_tlb_t *tlb;
4434     uint32_t size_tlb, size_ps;
4435
4436     switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
4437     case MAS0_WQ_ALWAYS:
4438         /* good to go, write that entry */
4439         break;
4440     case MAS0_WQ_COND:
4441         /* XXX check if reserved */
4442         if (0) {
4443             return;
4444         }
4445         break;
4446     case MAS0_WQ_CLR_RSRV:
4447         /* XXX clear entry */
4448         return;
4449     default:
4450         /* no idea what to do */
4451         return;
4452     }
4453
4454     if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
4455         !msr_gs) {
4456         /* XXX we don't support direct LRAT setting yet */
4457         fprintf(stderr, "cpu: don't support LRAT setting yet\n");
4458         return;
4459     }
4460
4461     tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
4462     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
4463
4464     tlb = booke206_cur_tlb(env);
4465
4466     if (!tlb) {
4467         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
4468                                    POWERPC_EXCP_INVAL |
4469                                    POWERPC_EXCP_INVAL_INVAL);
4470     }
4471
4472     /* check that we support the targeted size */
4473     size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
4474     size_ps = booke206_tlbnps(env, tlbn);
4475     if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
4476         !(size_ps & (1 << size_tlb))) {
4477         helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
4478                                    POWERPC_EXCP_INVAL |
4479                                    POWERPC_EXCP_INVAL_INVAL);
4480     }
4481
4482     if (msr_gs) {
4483         cpu_abort(env, "missing HV implementation\n");
4484     }
4485     tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
4486         env->spr[SPR_BOOKE_MAS3];
4487     tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
4488
4489     /* MAV 1.0 only */
4490     if (!(tlbncfg & TLBnCFG_AVAIL)) {
4491         /* force !AVAIL TLB entries to correct page size */
4492         tlb->mas1 &= ~MAS1_TSIZE_MASK;
4493         /* XXX can be configured in MMUCSR0 */
4494         tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
4495     }
4496
4497     /* XXX needs to change when supporting 64-bit e500 */
4498     tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & 0xffffffff;
4499
4500     if (!(tlbncfg & TLBnCFG_IPROT)) {
4501         /* no IPROT supported by TLB */
4502         tlb->mas1 &= ~MAS1_IPROT;
4503     }
4504
4505     if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
4506         tlb_flush_page(env, tlb->mas2 & MAS2_EPN_MASK);
4507     } else {
4508         tlb_flush(env, 1);
4509     }
4510 }
4511
4512 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
4513 {
4514     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
4515     int way = booke206_tlbm_to_way(env, tlb);
4516
4517     env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
4518     env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
4519     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
4520
4521     env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
4522     env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
4523     env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
4524     env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
4525 }
4526
4527 void helper_booke206_tlbre(void)
4528 {
4529     ppcmas_tlb_t *tlb = NULL;
4530
4531     tlb = booke206_cur_tlb(env);
4532     if (!tlb) {
4533         env->spr[SPR_BOOKE_MAS1] = 0;
4534     } else {
4535         booke206_tlb_to_mas(env, tlb);
4536     }
4537 }
4538
4539 void helper_booke206_tlbsx(target_ulong address)
4540 {
4541     ppcmas_tlb_t *tlb = NULL;
4542     int i, j;
4543     target_phys_addr_t raddr;
4544     uint32_t spid, sas;
4545
4546     spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
4547     sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
4548
4549     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
4550         int ways = booke206_tlb_ways(env, i);
4551
4552         for (j = 0; j < ways; j++) {
4553             tlb = booke206_get_tlbm(env, i, address, j);
4554
4555             if (!tlb) {
4556                 continue;
4557             }
4558
4559             if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
4560                 continue;
4561             }
4562
4563             if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
4564                 continue;
4565             }
4566
4567             booke206_tlb_to_mas(env, tlb);
4568             return;
4569         }
4570     }
4571
4572     /* no entry found, fill with defaults */
4573     env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
4574     env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
4575     env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
4576     env->spr[SPR_BOOKE_MAS3] = 0;
4577     env->spr[SPR_BOOKE_MAS7] = 0;
4578
4579     if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
4580         env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
4581     }
4582
4583     env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
4584         << MAS1_TID_SHIFT;
4585
4586     /* next victim logic */
4587     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
4588     env->last_way++;
4589     env->last_way &= booke206_tlb_ways(env, 0) - 1;
4590     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
4591 }
4592
4593 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
4594                                               uint32_t ea)
4595 {
4596     int i;
4597     int ways = booke206_tlb_ways(env, tlbn);
4598     target_ulong mask;
4599
4600     for (i = 0; i < ways; i++) {
4601         ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
4602         if (!tlb) {
4603             continue;
4604         }
4605         mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
4606         if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
4607             !(tlb->mas1 & MAS1_IPROT)) {
4608             tlb->mas1 &= ~MAS1_VALID;
4609         }
4610     }
4611 }
4612
4613 void helper_booke206_tlbivax(target_ulong address)
4614 {
4615     if (address & 0x4) {
4616         /* flush all entries */
4617         if (address & 0x8) {
4618             /* flush all of TLB1 */
4619             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
4620         } else {
4621             /* flush all of TLB0 */
4622             booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
4623         }
4624         return;
4625     }
4626
4627     if (address & 0x8) {
4628         /* flush TLB1 entries */
4629         booke206_invalidate_ea_tlb(env, 1, address);
4630         tlb_flush(env, 1);
4631     } else {
4632         /* flush TLB0 entries */
4633         booke206_invalidate_ea_tlb(env, 0, address);
4634         tlb_flush_page(env, address & MAS2_EPN_MASK);
4635     }
4636 }
4637
4638 void helper_booke206_tlbilx0(target_ulong address)
4639 {
4640     /* XXX missing LPID handling */
4641     booke206_flush_tlb(env, -1, 1);
4642 }
4643
4644 void helper_booke206_tlbilx1(target_ulong address)
4645 {
4646     int i, j;
4647     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
4648     ppcmas_tlb_t *tlb = env->tlb.tlbm;
4649     int tlb_size;
4650
4651     /* XXX missing LPID handling */
4652     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
4653         tlb_size = booke206_tlb_size(env, i);
4654         for (j = 0; j < tlb_size; j++) {
4655             if (!(tlb[j].mas1 & MAS1_IPROT) &&
4656                 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
4657                 tlb[j].mas1 &= ~MAS1_VALID;
4658             }
4659         }
4660         tlb += booke206_tlb_size(env, i);
4661     }
4662     tlb_flush(env, 1);
4663 }
4664
4665 void helper_booke206_tlbilx3(target_ulong address)
4666 {
4667     int i, j;
4668     ppcmas_tlb_t *tlb;
4669     int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
4670     int pid = tid >> MAS6_SPID_SHIFT;
4671     int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
4672     int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
4673     /* XXX check for unsupported isize and raise an invalid opcode then */
4674     int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
4675     /* XXX implement MAV2 handling */
4676     bool mav2 = false;
4677
4678     /* XXX missing LPID handling */
4679     /* flush by pid and ea */
4680     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
4681         int ways = booke206_tlb_ways(env, i);
4682
4683         for (j = 0; j < ways; j++) {
4684             tlb = booke206_get_tlbm(env, i, address, j);
4685             if (!tlb) {
4686                 continue;
4687             }
4688             if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
4689                 (tlb->mas1 & MAS1_IPROT) ||
4690                 ((tlb->mas1 & MAS1_IND) != ind) ||
4691                 ((tlb->mas8 & MAS8_TGS) != sgs)) {
4692                 continue;
4693             }
4694             if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
4695                 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
4696                 continue;
4697             }
4698             /* XXX e500mc doesn't match SAS, but other cores might */
4699             tlb->mas1 &= ~MAS1_VALID;
4700         }
4701     }
4702     tlb_flush(env, 1);
4703 }
4704
4705 void helper_booke206_tlbflush(uint32_t type)
4706 {
4707     int flags = 0;
4708
4709     if (type & 2) {
4710         flags |= BOOKE206_FLUSH_TLB1;
4711     }
4712
4713     if (type & 4) {
4714         flags |= BOOKE206_FLUSH_TLB0;
4715     }
4716
4717     booke206_flush_tlb(env, flags, 1);
4718 }
4719
4720 /* Embedded.Processor Control */
4721 static int dbell2irq(target_ulong rb)
4722 {
4723     int msg = rb & DBELL_TYPE_MASK;
4724     int irq = -1;
4725
4726     switch (msg) {
4727     case DBELL_TYPE_DBELL:
4728         irq = PPC_INTERRUPT_DOORBELL;
4729         break;
4730     case DBELL_TYPE_DBELL_CRIT:
4731         irq = PPC_INTERRUPT_CDOORBELL;
4732         break;
4733     case DBELL_TYPE_G_DBELL:
4734     case DBELL_TYPE_G_DBELL_CRIT:
4735     case DBELL_TYPE_G_DBELL_MC:
4736         /* XXX implement */
4737     default:
4738         break;
4739     }
4740
4741     return irq;
4742 }
4743
4744 void helper_msgclr(target_ulong rb)
4745 {
4746     int irq = dbell2irq(rb);
4747
4748     if (irq < 0) {
4749         return;
4750     }
4751
4752     env->pending_interrupts &= ~(1 << irq);
4753 }
4754
4755 void helper_msgsnd(target_ulong rb)
4756 {
4757     int irq = dbell2irq(rb);
4758     int pir = rb & DBELL_PIRTAG_MASK;
4759     CPUPPCState *cenv;
4760
4761     if (irq < 0) {
4762         return;
4763     }
4764
4765     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
4766         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
4767             cenv->pending_interrupts |= 1 << irq;
4768             cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
4769         }
4770     }
4771 }
4772
4773 #endif /* !CONFIG_USER_ONLY */
This page took 0.277056 seconds and 4 git commands to generate.