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