]> Git Repo - qemu.git/blob - target-ppc/op_helper.c
target-ppc: convert dcbz instruction to TCG
[qemu.git] / target-ppc / op_helper.c
1 /*
2  *  PowerPC emulation helpers for qemu.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "exec.h"
21 #include "host-utils.h"
22 #include "helper.h"
23
24 #include "helper_regs.h"
25 #include "op_helper.h"
26
27 #define MEMSUFFIX _raw
28 #include "op_helper.h"
29 #include "op_helper_mem.h"
30 #if !defined(CONFIG_USER_ONLY)
31 #define MEMSUFFIX _user
32 #include "op_helper.h"
33 #include "op_helper_mem.h"
34 #define MEMSUFFIX _kernel
35 #include "op_helper.h"
36 #include "op_helper_mem.h"
37 #define MEMSUFFIX _hypv
38 #include "op_helper.h"
39 #include "op_helper_mem.h"
40 #endif
41
42 //#define DEBUG_OP
43 //#define DEBUG_EXCEPTIONS
44 //#define DEBUG_SOFTWARE_TLB
45
46 /*****************************************************************************/
47 /* Exceptions processing helpers */
48
49 void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
50 {
51     raise_exception_err(env, exception, error_code);
52 }
53
54 void helper_raise_debug (void)
55 {
56     raise_exception(env, EXCP_DEBUG);
57 }
58
59 /*****************************************************************************/
60 /* Registers load and stores */
61 target_ulong helper_load_cr (void)
62 {
63     return (env->crf[0] << 28) |
64            (env->crf[1] << 24) |
65            (env->crf[2] << 20) |
66            (env->crf[3] << 16) |
67            (env->crf[4] << 12) |
68            (env->crf[5] << 8) |
69            (env->crf[6] << 4) |
70            (env->crf[7] << 0);
71 }
72
73 void helper_store_cr (target_ulong val, uint32_t mask)
74 {
75     int i, sh;
76
77     for (i = 0, sh = 7; i < 8; i++, sh--) {
78         if (mask & (1 << sh))
79             env->crf[i] = (val >> (sh * 4)) & 0xFUL;
80     }
81 }
82
83 #if defined(TARGET_PPC64)
84 void do_store_pri (int prio)
85 {
86     env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
87     env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
88 }
89 #endif
90
91 target_ulong ppc_load_dump_spr (int sprn)
92 {
93     if (loglevel != 0) {
94         fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
95                 sprn, sprn, env->spr[sprn]);
96     }
97
98     return env->spr[sprn];
99 }
100
101 void ppc_store_dump_spr (int sprn, target_ulong val)
102 {
103     if (loglevel != 0) {
104         fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
105                 sprn, sprn, env->spr[sprn], val);
106     }
107     env->spr[sprn] = val;
108 }
109
110 /*****************************************************************************/
111 /* Memory load and stores */
112
113 static always_inline target_ulong get_addr(target_ulong addr)
114 {
115 #if defined(TARGET_PPC64)
116         if (msr_sf)
117             return addr;
118         else
119 #endif
120             return (uint32_t)addr;
121 }
122
123 void helper_lmw (target_ulong addr, uint32_t reg)
124 {
125 #ifdef CONFIG_USER_ONLY
126 #define ldfun ldl_raw
127 #else
128     int (*ldfun)(target_ulong);
129
130     switch (env->mmu_idx) {
131     default:
132     case 0: ldfun = ldl_user;
133         break;
134     case 1: ldfun = ldl_kernel;
135         break;
136     case 2: ldfun = ldl_hypv;
137         break;
138     }
139 #endif
140     for (; reg < 32; reg++, addr += 4) {
141         if (msr_le)
142             env->gpr[reg] = bswap32(ldfun(get_addr(addr)));
143         else
144             env->gpr[reg] = ldfun(get_addr(addr));
145     }
146 }
147
148 void helper_stmw (target_ulong addr, uint32_t reg)
149 {
150 #ifdef CONFIG_USER_ONLY
151 #define stfun stl_raw
152 #else
153     void (*stfun)(target_ulong, int);
154
155     switch (env->mmu_idx) {
156     default:
157     case 0: stfun = stl_user;
158         break;
159     case 1: stfun = stl_kernel;
160         break;
161     case 2: stfun = stl_hypv;
162         break;
163     }
164 #endif
165     for (; reg < 32; reg++, addr += 4) {
166         if (msr_le)
167             stfun(get_addr(addr), bswap32((uint32_t)env->gpr[reg]));
168         else
169             stfun(get_addr(addr), (uint32_t)env->gpr[reg]);
170     }
171 }
172
173 static void do_dcbz(target_ulong addr, int dcache_line_size)
174 {
175     target_long mask = get_addr(~(dcache_line_size - 1));
176     int i;
177 #ifdef CONFIG_USER_ONLY
178 #define stfun stl_raw
179 #else
180     void (*stfun)(target_ulong, int);
181
182     switch (env->mmu_idx) {
183     default:
184     case 0: stfun = stl_user;
185         break;
186     case 1: stfun = stl_kernel;
187         break;
188     case 2: stfun = stl_hypv;
189         break;
190     }
191 #endif
192     addr &= mask;
193     for (i = 0 ; i < dcache_line_size ; i += 4) {
194         stfun(addr + i , 0);
195     }
196     if ((env->reserve & mask) == addr)
197         env->reserve = (target_ulong)-1ULL;
198 }
199
200 void helper_dcbz(target_ulong addr)
201 {
202     do_dcbz(addr, env->dcache_line_size);
203 }
204
205 void helper_dcbz_970(target_ulong addr)
206 {
207     if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
208         do_dcbz(addr, 32);
209     else
210         do_dcbz(addr, env->dcache_line_size);
211 }
212
213 /*****************************************************************************/
214 /* Fixed point operations helpers */
215 #if defined(TARGET_PPC64)
216
217 /* multiply high word */
218 uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
219 {
220     uint64_t tl, th;
221
222     muls64(&tl, &th, arg1, arg2);
223     return th;
224 }
225
226 /* multiply high word unsigned */
227 uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
228 {
229     uint64_t tl, th;
230
231     mulu64(&tl, &th, arg1, arg2);
232     return th;
233 }
234
235 uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
236 {
237     int64_t th;
238     uint64_t tl;
239
240     muls64(&tl, (uint64_t *)&th, arg1, arg2);
241     /* If th != 0 && th != -1, then we had an overflow */
242     if (likely((uint64_t)(th + 1) <= 1)) {
243         env->xer &= ~(1 << XER_OV);
244     } else {
245         env->xer |= (1 << XER_OV) | (1 << XER_SO);
246     }
247     return (int64_t)tl;
248 }
249 #endif
250
251 target_ulong helper_cntlzw (target_ulong t)
252 {
253     return clz32(t);
254 }
255
256 #if defined(TARGET_PPC64)
257 target_ulong helper_cntlzd (target_ulong t)
258 {
259     return clz64(t);
260 }
261 #endif
262
263 /* shift right arithmetic helper */
264 target_ulong helper_sraw (target_ulong value, target_ulong shift)
265 {
266     int32_t ret;
267
268     if (likely(!(shift & 0x20))) {
269         if (likely((uint32_t)shift != 0)) {
270             shift &= 0x1f;
271             ret = (int32_t)value >> shift;
272             if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
273                 env->xer &= ~(1 << XER_CA);
274             } else {
275                 env->xer |= (1 << XER_CA);
276             }
277         } else {
278             ret = (int32_t)value;
279             env->xer &= ~(1 << XER_CA);
280         }
281     } else {
282         ret = (int32_t)value >> 31;
283         if (ret) {
284             env->xer |= (1 << XER_CA);
285         } else {
286             env->xer &= ~(1 << XER_CA);
287         }
288     }
289     return (target_long)ret;
290 }
291
292 #if defined(TARGET_PPC64)
293 target_ulong helper_srad (target_ulong value, target_ulong shift)
294 {
295     int64_t ret;
296
297     if (likely(!(shift & 0x40))) {
298         if (likely((uint64_t)shift != 0)) {
299             shift &= 0x3f;
300             ret = (int64_t)value >> shift;
301             if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
302                 env->xer &= ~(1 << XER_CA);
303             } else {
304                 env->xer |= (1 << XER_CA);
305             }
306         } else {
307             ret = (int64_t)value;
308             env->xer &= ~(1 << XER_CA);
309         }
310     } else {
311         ret = (int64_t)value >> 63;
312         if (ret) {
313             env->xer |= (1 << XER_CA);
314         } else {
315             env->xer &= ~(1 << XER_CA);
316         }
317     }
318     return ret;
319 }
320 #endif
321
322 target_ulong helper_popcntb (target_ulong val)
323 {
324     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
325     val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
326     val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
327     return val;
328 }
329
330 #if defined(TARGET_PPC64)
331 target_ulong helper_popcntb_64 (target_ulong val)
332 {
333     val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
334     val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
335     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
336     return val;
337 }
338 #endif
339
340 /*****************************************************************************/
341 /* Floating point operations helpers */
342 uint64_t helper_float32_to_float64(uint32_t arg)
343 {
344     CPU_FloatU f;
345     CPU_DoubleU d;
346     f.l = arg;
347     d.d = float32_to_float64(f.f, &env->fp_status);
348     return d.ll;
349 }
350
351 uint32_t helper_float64_to_float32(uint64_t arg)
352 {
353     CPU_FloatU f;
354     CPU_DoubleU d;
355     d.ll = arg;
356     f.f = float64_to_float32(d.d, &env->fp_status);
357     return f.l;
358 }
359
360 static always_inline int fpisneg (float64 d)
361 {
362     CPU_DoubleU u;
363
364     u.d = d;
365
366     return u.ll >> 63 != 0;
367 }
368
369 static always_inline int isden (float64 d)
370 {
371     CPU_DoubleU u;
372
373     u.d = d;
374
375     return ((u.ll >> 52) & 0x7FF) == 0;
376 }
377
378 static always_inline int iszero (float64 d)
379 {
380     CPU_DoubleU u;
381
382     u.d = d;
383
384     return (u.ll & ~0x8000000000000000ULL) == 0;
385 }
386
387 static always_inline int isinfinity (float64 d)
388 {
389     CPU_DoubleU u;
390
391     u.d = d;
392
393     return ((u.ll >> 52) & 0x7FF) == 0x7FF &&
394         (u.ll & 0x000FFFFFFFFFFFFFULL) == 0;
395 }
396
397 #ifdef CONFIG_SOFTFLOAT
398 static always_inline int isfinite (float64 d)
399 {
400     CPU_DoubleU u;
401
402     u.d = d;
403
404     return (((u.ll >> 52) & 0x7FF) != 0x7FF);
405 }
406
407 static always_inline int isnormal (float64 d)
408 {
409     CPU_DoubleU u;
410
411     u.d = d;
412
413     uint32_t exp = (u.ll >> 52) & 0x7FF;
414     return ((0 < exp) && (exp < 0x7FF));
415 }
416 #endif
417
418 uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
419 {
420     CPU_DoubleU farg;
421     int isneg;
422     int ret;
423     farg.ll = arg;
424     isneg = fpisneg(farg.d);
425     if (unlikely(float64_is_nan(farg.d))) {
426         if (float64_is_signaling_nan(farg.d)) {
427             /* Signaling NaN: flags are undefined */
428             ret = 0x00;
429         } else {
430             /* Quiet NaN */
431             ret = 0x11;
432         }
433     } else if (unlikely(isinfinity(farg.d))) {
434         /* +/- infinity */
435         if (isneg)
436             ret = 0x09;
437         else
438             ret = 0x05;
439     } else {
440         if (iszero(farg.d)) {
441             /* +/- zero */
442             if (isneg)
443                 ret = 0x12;
444             else
445                 ret = 0x02;
446         } else {
447             if (isden(farg.d)) {
448                 /* Denormalized numbers */
449                 ret = 0x10;
450             } else {
451                 /* Normalized numbers */
452                 ret = 0x00;
453             }
454             if (isneg) {
455                 ret |= 0x08;
456             } else {
457                 ret |= 0x04;
458             }
459         }
460     }
461     if (set_fprf) {
462         /* We update FPSCR_FPRF */
463         env->fpscr &= ~(0x1F << FPSCR_FPRF);
464         env->fpscr |= ret << FPSCR_FPRF;
465     }
466     /* We just need fpcc to update Rc1 */
467     return ret & 0xF;
468 }
469
470 /* Floating-point invalid operations exception */
471 static always_inline uint64_t fload_invalid_op_excp (int op)
472 {
473     uint64_t ret = 0;
474     int ve;
475
476     ve = fpscr_ve;
477     if (op & POWERPC_EXCP_FP_VXSNAN) {
478         /* Operation on signaling NaN */
479         env->fpscr |= 1 << FPSCR_VXSNAN;
480     }
481     if (op & POWERPC_EXCP_FP_VXSOFT) {
482         /* Software-defined condition */
483         env->fpscr |= 1 << FPSCR_VXSOFT;
484     }
485     switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
486     case POWERPC_EXCP_FP_VXISI:
487         /* Magnitude subtraction of infinities */
488         env->fpscr |= 1 << FPSCR_VXISI;
489         goto update_arith;
490     case POWERPC_EXCP_FP_VXIDI:
491         /* Division of infinity by infinity */
492         env->fpscr |= 1 << FPSCR_VXIDI;
493         goto update_arith;
494     case POWERPC_EXCP_FP_VXZDZ:
495         /* Division of zero by zero */
496         env->fpscr |= 1 << FPSCR_VXZDZ;
497         goto update_arith;
498     case POWERPC_EXCP_FP_VXIMZ:
499         /* Multiplication of zero by infinity */
500         env->fpscr |= 1 << FPSCR_VXIMZ;
501         goto update_arith;
502     case POWERPC_EXCP_FP_VXVC:
503         /* Ordered comparison of NaN */
504         env->fpscr |= 1 << FPSCR_VXVC;
505         env->fpscr &= ~(0xF << FPSCR_FPCC);
506         env->fpscr |= 0x11 << FPSCR_FPCC;
507         /* We must update the target FPR before raising the exception */
508         if (ve != 0) {
509             env->exception_index = POWERPC_EXCP_PROGRAM;
510             env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
511             /* Update the floating-point enabled exception summary */
512             env->fpscr |= 1 << FPSCR_FEX;
513             /* Exception is differed */
514             ve = 0;
515         }
516         break;
517     case POWERPC_EXCP_FP_VXSQRT:
518         /* Square root of a negative number */
519         env->fpscr |= 1 << FPSCR_VXSQRT;
520     update_arith:
521         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
522         if (ve == 0) {
523             /* Set the result to quiet NaN */
524             ret = UINT64_MAX;
525             env->fpscr &= ~(0xF << FPSCR_FPCC);
526             env->fpscr |= 0x11 << FPSCR_FPCC;
527         }
528         break;
529     case POWERPC_EXCP_FP_VXCVI:
530         /* Invalid conversion */
531         env->fpscr |= 1 << FPSCR_VXCVI;
532         env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
533         if (ve == 0) {
534             /* Set the result to quiet NaN */
535             ret = UINT64_MAX;
536             env->fpscr &= ~(0xF << FPSCR_FPCC);
537             env->fpscr |= 0x11 << FPSCR_FPCC;
538         }
539         break;
540     }
541     /* Update the floating-point invalid operation summary */
542     env->fpscr |= 1 << FPSCR_VX;
543     /* Update the floating-point exception summary */
544     env->fpscr |= 1 << FPSCR_FX;
545     if (ve != 0) {
546         /* Update the floating-point enabled exception summary */
547         env->fpscr |= 1 << FPSCR_FEX;
548         if (msr_fe0 != 0 || msr_fe1 != 0)
549             raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
550     }
551     return ret;
552 }
553
554 static always_inline uint64_t float_zero_divide_excp (uint64_t arg1, uint64_t arg2)
555 {
556     env->fpscr |= 1 << FPSCR_ZX;
557     env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
558     /* Update the floating-point exception summary */
559     env->fpscr |= 1 << FPSCR_FX;
560     if (fpscr_ze != 0) {
561         /* Update the floating-point enabled exception summary */
562         env->fpscr |= 1 << FPSCR_FEX;
563         if (msr_fe0 != 0 || msr_fe1 != 0) {
564             raise_exception_err(env, POWERPC_EXCP_PROGRAM,
565                                 POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
566         }
567     } else {
568         /* Set the result to infinity */
569         arg1 = ((arg1 ^ arg2) & 0x8000000000000000ULL);
570         arg1 |= 0x7FFULL << 52;
571     }
572     return arg1;
573 }
574
575 static always_inline void float_overflow_excp (void)
576 {
577     env->fpscr |= 1 << FPSCR_OX;
578     /* Update the floating-point exception summary */
579     env->fpscr |= 1 << FPSCR_FX;
580     if (fpscr_oe != 0) {
581         /* XXX: should adjust the result */
582         /* Update the floating-point enabled exception summary */
583         env->fpscr |= 1 << FPSCR_FEX;
584         /* We must update the target FPR before raising the exception */
585         env->exception_index = POWERPC_EXCP_PROGRAM;
586         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
587     } else {
588         env->fpscr |= 1 << FPSCR_XX;
589         env->fpscr |= 1 << FPSCR_FI;
590     }
591 }
592
593 static always_inline void float_underflow_excp (void)
594 {
595     env->fpscr |= 1 << FPSCR_UX;
596     /* Update the floating-point exception summary */
597     env->fpscr |= 1 << FPSCR_FX;
598     if (fpscr_ue != 0) {
599         /* XXX: should adjust the result */
600         /* Update the floating-point enabled exception summary */
601         env->fpscr |= 1 << FPSCR_FEX;
602         /* We must update the target FPR before raising the exception */
603         env->exception_index = POWERPC_EXCP_PROGRAM;
604         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
605     }
606 }
607
608 static always_inline void float_inexact_excp (void)
609 {
610     env->fpscr |= 1 << FPSCR_XX;
611     /* Update the floating-point exception summary */
612     env->fpscr |= 1 << FPSCR_FX;
613     if (fpscr_xe != 0) {
614         /* Update the floating-point enabled exception summary */
615         env->fpscr |= 1 << FPSCR_FEX;
616         /* We must update the target FPR before raising the exception */
617         env->exception_index = POWERPC_EXCP_PROGRAM;
618         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
619     }
620 }
621
622 static always_inline void fpscr_set_rounding_mode (void)
623 {
624     int rnd_type;
625
626     /* Set rounding mode */
627     switch (fpscr_rn) {
628     case 0:
629         /* Best approximation (round to nearest) */
630         rnd_type = float_round_nearest_even;
631         break;
632     case 1:
633         /* Smaller magnitude (round toward zero) */
634         rnd_type = float_round_to_zero;
635         break;
636     case 2:
637         /* Round toward +infinite */
638         rnd_type = float_round_up;
639         break;
640     default:
641     case 3:
642         /* Round toward -infinite */
643         rnd_type = float_round_down;
644         break;
645     }
646     set_float_rounding_mode(rnd_type, &env->fp_status);
647 }
648
649 void helper_fpscr_setbit (uint32_t bit)
650 {
651     int prev;
652
653     prev = (env->fpscr >> bit) & 1;
654     env->fpscr |= 1 << bit;
655     if (prev == 0) {
656         switch (bit) {
657         case FPSCR_VX:
658             env->fpscr |= 1 << FPSCR_FX;
659             if (fpscr_ve)
660                 goto raise_ve;
661         case FPSCR_OX:
662             env->fpscr |= 1 << FPSCR_FX;
663             if (fpscr_oe)
664                 goto raise_oe;
665             break;
666         case FPSCR_UX:
667             env->fpscr |= 1 << FPSCR_FX;
668             if (fpscr_ue)
669                 goto raise_ue;
670             break;
671         case FPSCR_ZX:
672             env->fpscr |= 1 << FPSCR_FX;
673             if (fpscr_ze)
674                 goto raise_ze;
675             break;
676         case FPSCR_XX:
677             env->fpscr |= 1 << FPSCR_FX;
678             if (fpscr_xe)
679                 goto raise_xe;
680             break;
681         case FPSCR_VXSNAN:
682         case FPSCR_VXISI:
683         case FPSCR_VXIDI:
684         case FPSCR_VXZDZ:
685         case FPSCR_VXIMZ:
686         case FPSCR_VXVC:
687         case FPSCR_VXSOFT:
688         case FPSCR_VXSQRT:
689         case FPSCR_VXCVI:
690             env->fpscr |= 1 << FPSCR_VX;
691             env->fpscr |= 1 << FPSCR_FX;
692             if (fpscr_ve != 0)
693                 goto raise_ve;
694             break;
695         case FPSCR_VE:
696             if (fpscr_vx != 0) {
697             raise_ve:
698                 env->error_code = POWERPC_EXCP_FP;
699                 if (fpscr_vxsnan)
700                     env->error_code |= POWERPC_EXCP_FP_VXSNAN;
701                 if (fpscr_vxisi)
702                     env->error_code |= POWERPC_EXCP_FP_VXISI;
703                 if (fpscr_vxidi)
704                     env->error_code |= POWERPC_EXCP_FP_VXIDI;
705                 if (fpscr_vxzdz)
706                     env->error_code |= POWERPC_EXCP_FP_VXZDZ;
707                 if (fpscr_vximz)
708                     env->error_code |= POWERPC_EXCP_FP_VXIMZ;
709                 if (fpscr_vxvc)
710                     env->error_code |= POWERPC_EXCP_FP_VXVC;
711                 if (fpscr_vxsoft)
712                     env->error_code |= POWERPC_EXCP_FP_VXSOFT;
713                 if (fpscr_vxsqrt)
714                     env->error_code |= POWERPC_EXCP_FP_VXSQRT;
715                 if (fpscr_vxcvi)
716                     env->error_code |= POWERPC_EXCP_FP_VXCVI;
717                 goto raise_excp;
718             }
719             break;
720         case FPSCR_OE:
721             if (fpscr_ox != 0) {
722             raise_oe:
723                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
724                 goto raise_excp;
725             }
726             break;
727         case FPSCR_UE:
728             if (fpscr_ux != 0) {
729             raise_ue:
730                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
731                 goto raise_excp;
732             }
733             break;
734         case FPSCR_ZE:
735             if (fpscr_zx != 0) {
736             raise_ze:
737                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
738                 goto raise_excp;
739             }
740             break;
741         case FPSCR_XE:
742             if (fpscr_xx != 0) {
743             raise_xe:
744                 env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
745                 goto raise_excp;
746             }
747             break;
748         case FPSCR_RN1:
749         case FPSCR_RN:
750             fpscr_set_rounding_mode();
751             break;
752         default:
753             break;
754         raise_excp:
755             /* Update the floating-point enabled exception summary */
756             env->fpscr |= 1 << FPSCR_FEX;
757                 /* We have to update Rc1 before raising the exception */
758             env->exception_index = POWERPC_EXCP_PROGRAM;
759             break;
760         }
761     }
762 }
763
764 void helper_store_fpscr (uint64_t arg, uint32_t mask)
765 {
766     /*
767      * We use only the 32 LSB of the incoming fpr
768      */
769     uint32_t prev, new;
770     int i;
771
772     prev = env->fpscr;
773     new = (uint32_t)arg;
774     new &= ~0x90000000;
775     new |= prev & 0x90000000;
776     for (i = 0; i < 7; i++) {
777         if (mask & (1 << i)) {
778             env->fpscr &= ~(0xF << (4 * i));
779             env->fpscr |= new & (0xF << (4 * i));
780         }
781     }
782     /* Update VX and FEX */
783     if (fpscr_ix != 0)
784         env->fpscr |= 1 << FPSCR_VX;
785     else
786         env->fpscr &= ~(1 << FPSCR_VX);
787     if ((fpscr_ex & fpscr_eex) != 0) {
788         env->fpscr |= 1 << FPSCR_FEX;
789         env->exception_index = POWERPC_EXCP_PROGRAM;
790         /* XXX: we should compute it properly */
791         env->error_code = POWERPC_EXCP_FP;
792     }
793     else
794         env->fpscr &= ~(1 << FPSCR_FEX);
795     fpscr_set_rounding_mode();
796 }
797
798 void helper_float_check_status (void)
799 {
800 #ifdef CONFIG_SOFTFLOAT
801     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
802         (env->error_code & POWERPC_EXCP_FP)) {
803         /* Differred floating-point exception after target FPR update */
804         if (msr_fe0 != 0 || msr_fe1 != 0)
805             raise_exception_err(env, env->exception_index, env->error_code);
806     } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
807         float_overflow_excp();
808     } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
809         float_underflow_excp();
810     } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
811         float_inexact_excp();
812     }
813 #else
814     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
815         (env->error_code & POWERPC_EXCP_FP)) {
816         /* Differred floating-point exception after target FPR update */
817         if (msr_fe0 != 0 || msr_fe1 != 0)
818             raise_exception_err(env, env->exception_index, env->error_code);
819     }
820     RETURN();
821 #endif
822 }
823
824 #ifdef CONFIG_SOFTFLOAT
825 void helper_reset_fpstatus (void)
826 {
827     env->fp_status.float_exception_flags = 0;
828 }
829 #endif
830
831 /* fadd - fadd. */
832 uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
833 {
834     CPU_DoubleU farg1, farg2;
835
836     farg1.ll = arg1;
837     farg2.ll = arg2;
838 #if USE_PRECISE_EMULATION
839     if (unlikely(float64_is_signaling_nan(farg1.d) ||
840                  float64_is_signaling_nan(farg2.d))) {
841         /* sNaN addition */
842         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
843     } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) ||
844                       fpisneg(farg1.d) == fpisneg(farg2.d))) {
845         farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
846     } else {
847         /* Magnitude subtraction of infinities */
848         farg1.ll == fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
849     }
850 #else
851     farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
852 #endif
853     return farg1.ll;
854 }
855
856 /* fsub - fsub. */
857 uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
858 {
859     CPU_DoubleU farg1, farg2;
860
861     farg1.ll = arg1;
862     farg2.ll = arg2;
863 #if USE_PRECISE_EMULATION
864 {
865     if (unlikely(float64_is_signaling_nan(farg1.d) ||
866                  float64_is_signaling_nan(farg2.d))) {
867         /* sNaN subtraction */
868         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
869     } else if (likely(isfinite(farg1.d) || isfinite(farg2.d) ||
870                       fpisneg(farg1.d) != fpisneg(farg2.d))) {
871         farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
872     } else {
873         /* Magnitude subtraction of infinities */
874         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
875     }
876 }
877 #else
878     farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
879 #endif
880     return farg1.ll;
881 }
882
883 /* fmul - fmul. */
884 uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
885 {
886     CPU_DoubleU farg1, farg2;
887
888     farg1.ll = arg1;
889     farg2.ll = arg2;
890 #if USE_PRECISE_EMULATION
891     if (unlikely(float64_is_signaling_nan(farg1.d) ||
892                  float64_is_signaling_nan(farg2.d))) {
893         /* sNaN multiplication */
894         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
895     } else if (unlikely((isinfinity(farg1.d) && iszero(farg2.d)) ||
896                         (iszero(farg1.d) && isinfinity(farg2.d)))) {
897         /* Multiplication of zero by infinity */
898         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
899     } else {
900         farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
901     }
902 }
903 #else
904     farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
905 #endif
906     return farg1.ll;
907 }
908
909 /* fdiv - fdiv. */
910 uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
911 {
912     CPU_DoubleU farg1, farg2;
913
914     farg1.ll = arg1;
915     farg2.ll = arg2;
916 #if USE_PRECISE_EMULATION
917     if (unlikely(float64_is_signaling_nan(farg1.d) ||
918                  float64_is_signaling_nan(farg2.d))) {
919         /* sNaN division */
920         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
921     } else if (unlikely(isinfinity(farg1.d) && isinfinity(farg2.d))) {
922         /* Division of infinity by infinity */
923         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
924     } else if (unlikely(iszero(farg2.d))) {
925         if (iszero(farg1.d)) {
926             /* Division of zero by zero */
927             farg1.ll fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
928         } else {
929             /* Division by zero */
930             farg1.ll = float_zero_divide_excp(farg1.d, farg2.d);
931         }
932     } else {
933         farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
934     }
935 #else
936     farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
937 #endif
938     return farg1.ll;
939 }
940
941 /* fabs */
942 uint64_t helper_fabs (uint64_t arg)
943 {
944     CPU_DoubleU farg;
945
946     farg.ll = arg;
947     farg.d = float64_abs(farg.d);
948     return farg.ll;
949 }
950
951 /* fnabs */
952 uint64_t helper_fnabs (uint64_t arg)
953 {
954     CPU_DoubleU farg;
955
956     farg.ll = arg;
957     farg.d = float64_abs(farg.d);
958     farg.d = float64_chs(farg.d);
959     return farg.ll;
960 }
961
962 /* fneg */
963 uint64_t helper_fneg (uint64_t arg)
964 {
965     CPU_DoubleU farg;
966
967     farg.ll = arg;
968     farg.d = float64_chs(farg.d);
969     return farg.ll;
970 }
971
972 /* fctiw - fctiw. */
973 uint64_t helper_fctiw (uint64_t arg)
974 {
975     CPU_DoubleU farg;
976     farg.ll = arg;
977
978     if (unlikely(float64_is_signaling_nan(farg.d))) {
979         /* sNaN conversion */
980         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
981     } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
982         /* qNan / infinity conversion */
983         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
984     } else {
985         farg.ll = float64_to_int32(farg.d, &env->fp_status);
986 #if USE_PRECISE_EMULATION
987         /* XXX: higher bits are not supposed to be significant.
988          *     to make tests easier, return the same as a real PowerPC 750
989          */
990         farg.ll |= 0xFFF80000ULL << 32;
991 #endif
992     }
993     return farg.ll;
994 }
995
996 /* fctiwz - fctiwz. */
997 uint64_t helper_fctiwz (uint64_t arg)
998 {
999     CPU_DoubleU farg;
1000     farg.ll = arg;
1001
1002     if (unlikely(float64_is_signaling_nan(farg.d))) {
1003         /* sNaN conversion */
1004         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1005     } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
1006         /* qNan / infinity conversion */
1007         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1008     } else {
1009         farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1010 #if USE_PRECISE_EMULATION
1011         /* XXX: higher bits are not supposed to be significant.
1012          *     to make tests easier, return the same as a real PowerPC 750
1013          */
1014         farg.ll |= 0xFFF80000ULL << 32;
1015 #endif
1016     }
1017     return farg.ll;
1018 }
1019
1020 #if defined(TARGET_PPC64)
1021 /* fcfid - fcfid. */
1022 uint64_t helper_fcfid (uint64_t arg)
1023 {
1024     CPU_DoubleU farg;
1025     farg.d = int64_to_float64(arg, &env->fp_status);
1026     return farg.ll;
1027 }
1028
1029 /* fctid - fctid. */
1030 uint64_t helper_fctid (uint64_t arg)
1031 {
1032     CPU_DoubleU farg;
1033     farg.ll = arg;
1034
1035     if (unlikely(float64_is_signaling_nan(farg.d))) {
1036         /* sNaN conversion */
1037         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1038     } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
1039         /* qNan / infinity conversion */
1040         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1041     } else {
1042         farg.ll = float64_to_int64(farg.d, &env->fp_status);
1043     }
1044     return farg.ll;
1045 }
1046
1047 /* fctidz - fctidz. */
1048 uint64_t helper_fctidz (uint64_t arg)
1049 {
1050     CPU_DoubleU farg;
1051     farg.ll = arg;
1052
1053     if (unlikely(float64_is_signaling_nan(farg.d))) {
1054         /* sNaN conversion */
1055         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1056     } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
1057         /* qNan / infinity conversion */
1058         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1059     } else {
1060         farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1061     }
1062     return farg.ll;
1063 }
1064
1065 #endif
1066
1067 static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
1068 {
1069     CPU_DoubleU farg;
1070     farg.ll = arg;
1071
1072     if (unlikely(float64_is_signaling_nan(farg.d))) {
1073         /* sNaN round */
1074         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1075     } else if (unlikely(float64_is_nan(farg.d) || isinfinity(farg.d))) {
1076         /* qNan / infinity round */
1077         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1078     } else {
1079         set_float_rounding_mode(rounding_mode, &env->fp_status);
1080         farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1081         /* Restore rounding mode from FPSCR */
1082         fpscr_set_rounding_mode();
1083     }
1084     return farg.ll;
1085 }
1086
1087 uint64_t helper_frin (uint64_t arg)
1088 {
1089     return do_fri(arg, float_round_nearest_even);
1090 }
1091
1092 uint64_t helper_friz (uint64_t arg)
1093 {
1094     return do_fri(arg, float_round_to_zero);
1095 }
1096
1097 uint64_t helper_frip (uint64_t arg)
1098 {
1099     return do_fri(arg, float_round_up);
1100 }
1101
1102 uint64_t helper_frim (uint64_t arg)
1103 {
1104     return do_fri(arg, float_round_down);
1105 }
1106
1107 /* fmadd - fmadd. */
1108 uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1109 {
1110     CPU_DoubleU farg1, farg2, farg3;
1111
1112     farg1.ll = arg1;
1113     farg2.ll = arg2;
1114     farg3.ll = arg3;
1115 #if USE_PRECISE_EMULATION
1116     if (unlikely(float64_is_signaling_nan(farg1.d) ||
1117                  float64_is_signaling_nan(farg2.d) ||
1118                  float64_is_signaling_nan(farg3.d))) {
1119         /* sNaN operation */
1120         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1121     } else {
1122 #ifdef FLOAT128
1123         /* This is the way the PowerPC specification defines it */
1124         float128 ft0_128, ft1_128;
1125
1126         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1127         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1128         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1129         ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1130         ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1131         farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1132 #else
1133         /* This is OK on x86 hosts */
1134         farg1.d = (farg1.d * farg2.d) + farg3.d;
1135 #endif
1136     }
1137 #else
1138     farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1139     farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1140 #endif
1141     return farg1.ll;
1142 }
1143
1144 /* fmsub - fmsub. */
1145 uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1146 {
1147     CPU_DoubleU farg1, farg2, farg3;
1148
1149     farg1.ll = arg1;
1150     farg2.ll = arg2;
1151     farg3.ll = arg3;
1152 #if USE_PRECISE_EMULATION
1153     if (unlikely(float64_is_signaling_nan(farg1.d) ||
1154                  float64_is_signaling_nan(farg2.d) ||
1155                  float64_is_signaling_nan(farg3.d))) {
1156         /* sNaN operation */
1157         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1158     } else {
1159 #ifdef FLOAT128
1160         /* This is the way the PowerPC specification defines it */
1161         float128 ft0_128, ft1_128;
1162
1163         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1164         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1165         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1166         ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1167         ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1168         farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1169 #else
1170         /* This is OK on x86 hosts */
1171         farg1.d = (farg1.d * farg2.d) - farg3.d;
1172 #endif
1173     }
1174 #else
1175     farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1176     farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1177 #endif
1178     return farg1.ll;
1179 }
1180
1181 /* fnmadd - fnmadd. */
1182 uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1183 {
1184     CPU_DoubleU farg1, farg2, farg3;
1185
1186     farg1.ll = arg1;
1187     farg2.ll = arg2;
1188     farg3.ll = arg3;
1189
1190     if (unlikely(float64_is_signaling_nan(farg1.d) ||
1191                  float64_is_signaling_nan(farg2.d) ||
1192                  float64_is_signaling_nan(farg3.d))) {
1193         /* sNaN operation */
1194         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1195     } else {
1196 #if USE_PRECISE_EMULATION
1197 #ifdef FLOAT128
1198         /* This is the way the PowerPC specification defines it */
1199         float128 ft0_128, ft1_128;
1200
1201         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1202         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1203         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1204         ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1205         ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1206         farg1.d= float128_to_float64(ft0_128, &env->fp_status);
1207 #else
1208         /* This is OK on x86 hosts */
1209         farg1.d = (farg1.d * farg2.d) + farg3.d;
1210 #endif
1211 #else
1212         farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1213         farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1214 #endif
1215         if (likely(!isnan(farg1.d)))
1216             farg1.d = float64_chs(farg1.d);
1217     }
1218     return farg1.ll;
1219 }
1220
1221 /* fnmsub - fnmsub. */
1222 uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1223 {
1224     CPU_DoubleU farg1, farg2, farg3;
1225
1226     farg1.ll = arg1;
1227     farg2.ll = arg2;
1228     farg3.ll = arg3;
1229
1230     if (unlikely(float64_is_signaling_nan(farg1.d) ||
1231                  float64_is_signaling_nan(farg2.d) ||
1232                  float64_is_signaling_nan(farg3.d))) {
1233         /* sNaN operation */
1234         farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1235     } else {
1236 #if USE_PRECISE_EMULATION
1237 #ifdef FLOAT128
1238         /* This is the way the PowerPC specification defines it */
1239         float128 ft0_128, ft1_128;
1240
1241         ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1242         ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1243         ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1244         ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1245         ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1246         farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1247 #else
1248         /* This is OK on x86 hosts */
1249         farg1.d = (farg1.d * farg2.d) - farg3.d;
1250 #endif
1251 #else
1252         farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1253         farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1254 #endif
1255         if (likely(!isnan(farg1.d)))
1256             farg1.d = float64_chs(farg1.d);
1257     }
1258     return farg1.ll;
1259 }
1260
1261 /* frsp - frsp. */
1262 uint64_t helper_frsp (uint64_t arg)
1263 {
1264     CPU_DoubleU farg;
1265     farg.ll = arg;
1266
1267 #if USE_PRECISE_EMULATION
1268     if (unlikely(float64_is_signaling_nan(farg.d))) {
1269         /* sNaN square root */
1270        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1271     } else {
1272        fard.d = float64_to_float32(farg.d, &env->fp_status);
1273     }
1274 #else
1275     farg.d = float64_to_float32(farg.d, &env->fp_status);
1276 #endif
1277     return farg.ll;
1278 }
1279
1280 /* fsqrt - fsqrt. */
1281 uint64_t helper_fsqrt (uint64_t arg)
1282 {
1283     CPU_DoubleU farg;
1284     farg.ll = arg;
1285
1286     if (unlikely(float64_is_signaling_nan(farg.d))) {
1287         /* sNaN square root */
1288         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1289     } else if (unlikely(fpisneg(farg.d) && !iszero(farg.d))) {
1290         /* Square root of a negative nonzero number */
1291         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1292     } else {
1293         farg.d = float64_sqrt(farg.d, &env->fp_status);
1294     }
1295     return farg.ll;
1296 }
1297
1298 /* fre - fre. */
1299 uint64_t helper_fre (uint64_t arg)
1300 {
1301     CPU_DoubleU farg;
1302     farg.ll = arg;
1303
1304     if (unlikely(float64_is_signaling_nan(farg.d))) {
1305         /* sNaN reciprocal */
1306         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1307     } else if (unlikely(iszero(farg.d))) {
1308         /* Zero reciprocal */
1309         farg.ll = float_zero_divide_excp(1.0, farg.d);
1310     } else if (likely(isnormal(farg.d))) {
1311         farg.d = float64_div(1.0, farg.d, &env->fp_status);
1312     } else {
1313         if (farg.ll == 0x8000000000000000ULL) {
1314             farg.ll = 0xFFF0000000000000ULL;
1315         } else if (farg.ll == 0x0000000000000000ULL) {
1316             farg.ll = 0x7FF0000000000000ULL;
1317         } else if (isnan(farg.d)) {
1318             farg.ll = 0x7FF8000000000000ULL;
1319         } else if (fpisneg(farg.d)) {
1320             farg.ll = 0x8000000000000000ULL;
1321         } else {
1322             farg.ll = 0x0000000000000000ULL;
1323         }
1324     }
1325     return farg.d;
1326 }
1327
1328 /* fres - fres. */
1329 uint64_t helper_fres (uint64_t arg)
1330 {
1331     CPU_DoubleU farg;
1332     farg.ll = arg;
1333
1334     if (unlikely(float64_is_signaling_nan(farg.d))) {
1335         /* sNaN reciprocal */
1336         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1337     } else if (unlikely(iszero(farg.d))) {
1338         /* Zero reciprocal */
1339         farg.ll = float_zero_divide_excp(1.0, farg.d);
1340     } else if (likely(isnormal(farg.d))) {
1341 #if USE_PRECISE_EMULATION
1342         farg.d = float64_div(1.0, farg.d, &env->fp_status);
1343         farg.d = float64_to_float32(farg.d, &env->fp_status);
1344 #else
1345         farg.d = float32_div(1.0, farg.d, &env->fp_status);
1346 #endif
1347     } else {
1348         if (farg.ll == 0x8000000000000000ULL) {
1349             farg.ll = 0xFFF0000000000000ULL;
1350         } else if (farg.ll == 0x0000000000000000ULL) {
1351             farg.ll = 0x7FF0000000000000ULL;
1352         } else if (isnan(farg.d)) {
1353             farg.ll = 0x7FF8000000000000ULL;
1354         } else if (fpisneg(farg.d)) {
1355             farg.ll = 0x8000000000000000ULL;
1356         } else {
1357             farg.ll = 0x0000000000000000ULL;
1358         }
1359     }
1360     return farg.ll;
1361 }
1362
1363 /* frsqrte  - frsqrte. */
1364 uint64_t helper_frsqrte (uint64_t arg)
1365 {
1366     CPU_DoubleU farg;
1367     farg.ll = arg;
1368
1369     if (unlikely(float64_is_signaling_nan(farg.d))) {
1370         /* sNaN reciprocal square root */
1371         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1372     } else if (unlikely(fpisneg(farg.d) && !iszero(farg.d))) {
1373         /* Reciprocal square root of a negative nonzero number */
1374         farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1375     } else if (likely(isnormal(farg.d))) {
1376         farg.d = float64_sqrt(farg.d, &env->fp_status);
1377         farg.d = float32_div(1.0, farg.d, &env->fp_status);
1378     } else {
1379         if (farg.ll == 0x8000000000000000ULL) {
1380             farg.ll = 0xFFF0000000000000ULL;
1381         } else if (farg.ll == 0x0000000000000000ULL) {
1382             farg.ll = 0x7FF0000000000000ULL;
1383         } else if (isnan(farg.d)) {
1384             farg.ll |= 0x000FFFFFFFFFFFFFULL;
1385         } else if (fpisneg(farg.d)) {
1386             farg.ll = 0x7FF8000000000000ULL;
1387         } else {
1388             farg.ll = 0x0000000000000000ULL;
1389         }
1390     }
1391     return farg.ll;
1392 }
1393
1394 /* fsel - fsel. */
1395 uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1396 {
1397     CPU_DoubleU farg1, farg2, farg3;
1398
1399     farg1.ll = arg1;
1400     farg2.ll = arg2;
1401     farg3.ll = arg3;
1402
1403     if (!fpisneg(farg1.d) || iszero(farg1.d))
1404         return farg2.ll;
1405     else
1406         return farg2.ll;
1407 }
1408
1409 uint32_t helper_fcmpu (uint64_t arg1, uint64_t arg2)
1410 {
1411     CPU_DoubleU farg1, farg2;
1412     uint32_t ret = 0;
1413     farg1.ll = arg1;
1414     farg2.ll = arg2;
1415
1416     if (unlikely(float64_is_signaling_nan(farg1.d) ||
1417                  float64_is_signaling_nan(farg2.d))) {
1418         /* sNaN comparison */
1419         fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1420     } else {
1421         if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1422             ret = 0x08UL;
1423         } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1424             ret = 0x04UL;
1425         } else {
1426             ret = 0x02UL;
1427         }
1428     }
1429     env->fpscr &= ~(0x0F << FPSCR_FPRF);
1430     env->fpscr |= ret << FPSCR_FPRF;
1431     return ret;
1432 }
1433
1434 uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
1435 {
1436     CPU_DoubleU farg1, farg2;
1437     uint32_t ret = 0;
1438     farg1.ll = arg1;
1439     farg2.ll = arg2;
1440
1441     if (unlikely(float64_is_nan(farg1.d) ||
1442                  float64_is_nan(farg2.d))) {
1443         if (float64_is_signaling_nan(farg1.d) ||
1444             float64_is_signaling_nan(farg2.d)) {
1445             /* sNaN comparison */
1446             fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1447                                   POWERPC_EXCP_FP_VXVC);
1448         } else {
1449             /* qNaN comparison */
1450             fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1451         }
1452     } else {
1453         if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1454             ret = 0x08UL;
1455         } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1456             ret = 0x04UL;
1457         } else {
1458             ret = 0x02UL;
1459         }
1460     }
1461     env->fpscr &= ~(0x0F << FPSCR_FPRF);
1462     env->fpscr |= ret << FPSCR_FPRF;
1463     return ret;
1464 }
1465
1466 #if !defined (CONFIG_USER_ONLY)
1467 void cpu_dump_rfi (target_ulong RA, target_ulong msr);
1468
1469 void do_store_msr (void)
1470 {
1471     T0 = hreg_store_msr(env, T0, 0);
1472     if (T0 != 0) {
1473         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1474         raise_exception(env, T0);
1475     }
1476 }
1477
1478 static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
1479                                     target_ulong msrm, int keep_msrh)
1480 {
1481 #if defined(TARGET_PPC64)
1482     if (msr & (1ULL << MSR_SF)) {
1483         nip = (uint64_t)nip;
1484         msr &= (uint64_t)msrm;
1485     } else {
1486         nip = (uint32_t)nip;
1487         msr = (uint32_t)(msr & msrm);
1488         if (keep_msrh)
1489             msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1490     }
1491 #else
1492     nip = (uint32_t)nip;
1493     msr &= (uint32_t)msrm;
1494 #endif
1495     /* XXX: beware: this is false if VLE is supported */
1496     env->nip = nip & ~((target_ulong)0x00000003);
1497     hreg_store_msr(env, msr, 1);
1498 #if defined (DEBUG_OP)
1499     cpu_dump_rfi(env->nip, env->msr);
1500 #endif
1501     /* No need to raise an exception here,
1502      * as rfi is always the last insn of a TB
1503      */
1504     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1505 }
1506
1507 void do_rfi (void)
1508 {
1509     __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1510              ~((target_ulong)0xFFFF0000), 1);
1511 }
1512
1513 #if defined(TARGET_PPC64)
1514 void do_rfid (void)
1515 {
1516     __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1517              ~((target_ulong)0xFFFF0000), 0);
1518 }
1519
1520 void do_hrfid (void)
1521 {
1522     __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1523              ~((target_ulong)0xFFFF0000), 0);
1524 }
1525 #endif
1526 #endif
1527
1528 void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
1529 {
1530     if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1531                   ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1532                   ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1533                   ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1534                   ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1535         raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1536     }
1537 }
1538
1539 #if defined(TARGET_PPC64)
1540 void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1541 {
1542     if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1543                   ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1544                   ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1545                   ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1546                   ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
1547         raise_exception_err(env, POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1548 }
1549 #endif
1550
1551 /*****************************************************************************/
1552 /* PowerPC 601 specific instructions (POWER bridge) */
1553 void do_POWER_abso (void)
1554 {
1555     if ((int32_t)T0 == INT32_MIN) {
1556         T0 = INT32_MAX;
1557         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1558     } else if ((int32_t)T0 < 0) {
1559         T0 = -T0;
1560         env->xer &= ~(1 << XER_OV);
1561     } else {
1562         env->xer &= ~(1 << XER_OV);
1563     }
1564 }
1565
1566 void do_POWER_clcs (void)
1567 {
1568     switch (T0) {
1569     case 0x0CUL:
1570         /* Instruction cache line size */
1571         T0 = env->icache_line_size;
1572         break;
1573     case 0x0DUL:
1574         /* Data cache line size */
1575         T0 = env->dcache_line_size;
1576         break;
1577     case 0x0EUL:
1578         /* Minimum cache line size */
1579         T0 = env->icache_line_size < env->dcache_line_size ?
1580             env->icache_line_size : env->dcache_line_size;
1581         break;
1582     case 0x0FUL:
1583         /* Maximum cache line size */
1584         T0 = env->icache_line_size > env->dcache_line_size ?
1585             env->icache_line_size : env->dcache_line_size;
1586         break;
1587     default:
1588         /* Undefined */
1589         break;
1590     }
1591 }
1592
1593 void do_POWER_div (void)
1594 {
1595     uint64_t tmp;
1596
1597     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1598         (int32_t)T1 == 0) {
1599         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1600         env->spr[SPR_MQ] = 0;
1601     } else {
1602         tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1603         env->spr[SPR_MQ] = tmp % T1;
1604         T0 = tmp / (int32_t)T1;
1605     }
1606 }
1607
1608 void do_POWER_divo (void)
1609 {
1610     int64_t tmp;
1611
1612     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1613         (int32_t)T1 == 0) {
1614         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1615         env->spr[SPR_MQ] = 0;
1616         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1617     } else {
1618         tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1619         env->spr[SPR_MQ] = tmp % T1;
1620         tmp /= (int32_t)T1;
1621         if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1622             env->xer |= (1 << XER_OV) | (1 << XER_SO);
1623         } else {
1624             env->xer &= ~(1 << XER_OV);
1625         }
1626         T0 = tmp;
1627     }
1628 }
1629
1630 void do_POWER_divs (void)
1631 {
1632     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1633         (int32_t)T1 == 0) {
1634         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1635         env->spr[SPR_MQ] = 0;
1636     } else {
1637         env->spr[SPR_MQ] = T0 % T1;
1638         T0 = (int32_t)T0 / (int32_t)T1;
1639     }
1640 }
1641
1642 void do_POWER_divso (void)
1643 {
1644     if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1645         (int32_t)T1 == 0) {
1646         T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1647         env->spr[SPR_MQ] = 0;
1648         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1649     } else {
1650         T0 = (int32_t)T0 / (int32_t)T1;
1651         env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1652         env->xer &= ~(1 << XER_OV);
1653     }
1654 }
1655
1656 void do_POWER_dozo (void)
1657 {
1658     if ((int32_t)T1 > (int32_t)T0) {
1659         T2 = T0;
1660         T0 = T1 - T0;
1661         if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1662             ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1663             env->xer |= (1 << XER_OV) | (1 << XER_SO);
1664         } else {
1665             env->xer &= ~(1 << XER_OV);
1666         }
1667     } else {
1668         T0 = 0;
1669         env->xer &= ~(1 << XER_OV);
1670     }
1671 }
1672
1673 void do_POWER_maskg (void)
1674 {
1675     uint32_t ret;
1676
1677     if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1678         ret = UINT32_MAX;
1679     } else {
1680         ret = (UINT32_MAX >> ((uint32_t)T0)) ^
1681             ((UINT32_MAX >> ((uint32_t)T1)) >> 1);
1682         if ((uint32_t)T0 > (uint32_t)T1)
1683             ret = ~ret;
1684     }
1685     T0 = ret;
1686 }
1687
1688 void do_POWER_mulo (void)
1689 {
1690     uint64_t tmp;
1691
1692     tmp = (uint64_t)T0 * (uint64_t)T1;
1693     env->spr[SPR_MQ] = tmp >> 32;
1694     T0 = tmp;
1695     if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1696         env->xer |= (1 << XER_OV) | (1 << XER_SO);
1697     } else {
1698         env->xer &= ~(1 << XER_OV);
1699     }
1700 }
1701
1702 #if !defined (CONFIG_USER_ONLY)
1703 void do_POWER_rac (void)
1704 {
1705     mmu_ctx_t ctx;
1706     int nb_BATs;
1707
1708     /* We don't have to generate many instances of this instruction,
1709      * as rac is supervisor only.
1710      */
1711     /* XXX: FIX THIS: Pretend we have no BAT */
1712     nb_BATs = env->nb_BATs;
1713     env->nb_BATs = 0;
1714     if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
1715         T0 = ctx.raddr;
1716     env->nb_BATs = nb_BATs;
1717 }
1718
1719 void do_POWER_rfsvc (void)
1720 {
1721     __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1722 }
1723
1724 void do_store_hid0_601 (void)
1725 {
1726     uint32_t hid0;
1727
1728     hid0 = env->spr[SPR_HID0];
1729     if ((T0 ^ hid0) & 0x00000008) {
1730         /* Change current endianness */
1731         env->hflags &= ~(1 << MSR_LE);
1732         env->hflags_nmsr &= ~(1 << MSR_LE);
1733         env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
1734         env->hflags |= env->hflags_nmsr;
1735         if (loglevel != 0) {
1736             fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
1737                     __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
1738         }
1739     }
1740     env->spr[SPR_HID0] = T0;
1741 }
1742 #endif
1743
1744 /*****************************************************************************/
1745 /* 602 specific instructions */
1746 /* mfrom is the most crazy instruction ever seen, imho ! */
1747 /* Real implementation uses a ROM table. Do the same */
1748 #define USE_MFROM_ROM_TABLE
1749 target_ulong helper_602_mfrom (target_ulong arg)
1750 {
1751     if (likely(arg < 602)) {
1752 #if defined(USE_MFROM_ROM_TABLE)
1753 #include "mfrom_table.c"
1754         return mfrom_ROM_table[T0];
1755 #else
1756         double d;
1757         /* Extremly decomposed:
1758          *                      -arg / 256
1759          * return 256 * log10(10           + 1.0) + 0.5
1760          */
1761         d = arg;
1762         d = float64_div(d, 256, &env->fp_status);
1763         d = float64_chs(d);
1764         d = exp10(d); // XXX: use float emulation function
1765         d = float64_add(d, 1.0, &env->fp_status);
1766         d = log10(d); // XXX: use float emulation function
1767         d = float64_mul(d, 256, &env->fp_status);
1768         d = float64_add(d, 0.5, &env->fp_status);
1769         return float64_round_to_int(d, &env->fp_status);
1770 #endif
1771     } else {
1772         return 0;
1773     }
1774 }
1775
1776 /*****************************************************************************/
1777 /* Embedded PowerPC specific helpers */
1778
1779 /* XXX: to be improved to check access rights when in user-mode */
1780 void do_load_dcr (void)
1781 {
1782     target_ulong val;
1783
1784     if (unlikely(env->dcr_env == NULL)) {
1785         if (loglevel != 0) {
1786             fprintf(logfile, "No DCR environment\n");
1787         }
1788         raise_exception_err(env, POWERPC_EXCP_PROGRAM,
1789                             POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1790     } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1791         if (loglevel != 0) {
1792             fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1793         }
1794         raise_exception_err(env, POWERPC_EXCP_PROGRAM,
1795                             POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1796     } else {
1797         T0 = val;
1798     }
1799 }
1800
1801 void do_store_dcr (void)
1802 {
1803     if (unlikely(env->dcr_env == NULL)) {
1804         if (loglevel != 0) {
1805             fprintf(logfile, "No DCR environment\n");
1806         }
1807         raise_exception_err(env, POWERPC_EXCP_PROGRAM,
1808                             POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1809     } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1810         if (loglevel != 0) {
1811             fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1812         }
1813         raise_exception_err(env, POWERPC_EXCP_PROGRAM,
1814                             POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1815     }
1816 }
1817
1818 #if !defined(CONFIG_USER_ONLY)
1819 void do_40x_rfci (void)
1820 {
1821     __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1822              ~((target_ulong)0xFFFF0000), 0);
1823 }
1824
1825 void do_rfci (void)
1826 {
1827     __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1828              ~((target_ulong)0x3FFF0000), 0);
1829 }
1830
1831 void do_rfdi (void)
1832 {
1833     __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1834              ~((target_ulong)0x3FFF0000), 0);
1835 }
1836
1837 void do_rfmci (void)
1838 {
1839     __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1840              ~((target_ulong)0x3FFF0000), 0);
1841 }
1842
1843 void do_load_403_pb (int num)
1844 {
1845     T0 = env->pb[num];
1846 }
1847
1848 void do_store_403_pb (int num)
1849 {
1850     if (likely(env->pb[num] != T0)) {
1851         env->pb[num] = T0;
1852         /* Should be optimized */
1853         tlb_flush(env, 1);
1854     }
1855 }
1856 #endif
1857
1858 /* 440 specific */
1859 void do_440_dlmzb (void)
1860 {
1861     target_ulong mask;
1862     int i;
1863
1864     i = 1;
1865     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1866         if ((T0 & mask) == 0)
1867             goto done;
1868         i++;
1869     }
1870     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1871         if ((T1 & mask) == 0)
1872             break;
1873         i++;
1874     }
1875  done:
1876     T0 = i;
1877 }
1878
1879 /*****************************************************************************/
1880 /* SPE extension helpers */
1881 /* Use a table to make this quicker */
1882 static uint8_t hbrev[16] = {
1883     0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1884     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1885 };
1886
1887 static always_inline uint8_t byte_reverse (uint8_t val)
1888 {
1889     return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1890 }
1891
1892 static always_inline uint32_t word_reverse (uint32_t val)
1893 {
1894     return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1895         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1896 }
1897
1898 #define MASKBITS 16 // Random value - to be fixed (implementation dependant)
1899 target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
1900 {
1901     uint32_t a, b, d, mask;
1902
1903     mask = UINT32_MAX >> (32 - MASKBITS);
1904     a = arg1 & mask;
1905     b = arg2 & mask;
1906     d = word_reverse(1 + word_reverse(a | ~b));
1907     return (arg1 & ~mask) | (d & b);
1908 }
1909
1910 uint32_t helper_cntlsw32 (uint32_t val)
1911 {
1912     if (val & 0x80000000)
1913         return clz32(~val);
1914     else
1915         return clz32(val);
1916 }
1917
1918 uint32_t helper_cntlzw32 (uint32_t val)
1919 {
1920     return clz32(val);
1921 }
1922
1923 /* Single-precision floating-point conversions */
1924 static always_inline uint32_t efscfsi (uint32_t val)
1925 {
1926     CPU_FloatU u;
1927
1928     u.f = int32_to_float32(val, &env->spe_status);
1929
1930     return u.l;
1931 }
1932
1933 static always_inline uint32_t efscfui (uint32_t val)
1934 {
1935     CPU_FloatU u;
1936
1937     u.f = uint32_to_float32(val, &env->spe_status);
1938
1939     return u.l;
1940 }
1941
1942 static always_inline int32_t efsctsi (uint32_t val)
1943 {
1944     CPU_FloatU u;
1945
1946     u.l = val;
1947     /* NaN are not treated the same way IEEE 754 does */
1948     if (unlikely(isnan(u.f)))
1949         return 0;
1950
1951     return float32_to_int32(u.f, &env->spe_status);
1952 }
1953
1954 static always_inline uint32_t efsctui (uint32_t val)
1955 {
1956     CPU_FloatU u;
1957
1958     u.l = val;
1959     /* NaN are not treated the same way IEEE 754 does */
1960     if (unlikely(isnan(u.f)))
1961         return 0;
1962
1963     return float32_to_uint32(u.f, &env->spe_status);
1964 }
1965
1966 static always_inline uint32_t efsctsiz (uint32_t val)
1967 {
1968     CPU_FloatU u;
1969
1970     u.l = val;
1971     /* NaN are not treated the same way IEEE 754 does */
1972     if (unlikely(isnan(u.f)))
1973         return 0;
1974
1975     return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1976 }
1977
1978 static always_inline uint32_t efsctuiz (uint32_t val)
1979 {
1980     CPU_FloatU u;
1981
1982     u.l = val;
1983     /* NaN are not treated the same way IEEE 754 does */
1984     if (unlikely(isnan(u.f)))
1985         return 0;
1986
1987     return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1988 }
1989
1990 static always_inline uint32_t efscfsf (uint32_t val)
1991 {
1992     CPU_FloatU u;
1993     float32 tmp;
1994
1995     u.f = int32_to_float32(val, &env->spe_status);
1996     tmp = int64_to_float32(1ULL << 32, &env->spe_status);
1997     u.f = float32_div(u.f, tmp, &env->spe_status);
1998
1999     return u.l;
2000 }
2001
2002 static always_inline uint32_t efscfuf (uint32_t val)
2003 {
2004     CPU_FloatU u;
2005     float32 tmp;
2006
2007     u.f = uint32_to_float32(val, &env->spe_status);
2008     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2009     u.f = float32_div(u.f, tmp, &env->spe_status);
2010
2011     return u.l;
2012 }
2013
2014 static always_inline uint32_t efsctsf (uint32_t val)
2015 {
2016     CPU_FloatU u;
2017     float32 tmp;
2018
2019     u.l = val;
2020     /* NaN are not treated the same way IEEE 754 does */
2021     if (unlikely(isnan(u.f)))
2022         return 0;
2023     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2024     u.f = float32_mul(u.f, tmp, &env->spe_status);
2025
2026     return float32_to_int32(u.f, &env->spe_status);
2027 }
2028
2029 static always_inline uint32_t efsctuf (uint32_t val)
2030 {
2031     CPU_FloatU u;
2032     float32 tmp;
2033
2034     u.l = val;
2035     /* NaN are not treated the same way IEEE 754 does */
2036     if (unlikely(isnan(u.f)))
2037         return 0;
2038     tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2039     u.f = float32_mul(u.f, tmp, &env->spe_status);
2040
2041     return float32_to_uint32(u.f, &env->spe_status);
2042 }
2043
2044 #define HELPER_SPE_SINGLE_CONV(name)                                          \
2045 uint32_t helper_e##name (uint32_t val)                                        \
2046 {                                                                             \
2047     return e##name(val);                                                      \
2048 }
2049 /* efscfsi */
2050 HELPER_SPE_SINGLE_CONV(fscfsi);
2051 /* efscfui */
2052 HELPER_SPE_SINGLE_CONV(fscfui);
2053 /* efscfuf */
2054 HELPER_SPE_SINGLE_CONV(fscfuf);
2055 /* efscfsf */
2056 HELPER_SPE_SINGLE_CONV(fscfsf);
2057 /* efsctsi */
2058 HELPER_SPE_SINGLE_CONV(fsctsi);
2059 /* efsctui */
2060 HELPER_SPE_SINGLE_CONV(fsctui);
2061 /* efsctsiz */
2062 HELPER_SPE_SINGLE_CONV(fsctsiz);
2063 /* efsctuiz */
2064 HELPER_SPE_SINGLE_CONV(fsctuiz);
2065 /* efsctsf */
2066 HELPER_SPE_SINGLE_CONV(fsctsf);
2067 /* efsctuf */
2068 HELPER_SPE_SINGLE_CONV(fsctuf);
2069
2070 #define HELPER_SPE_VECTOR_CONV(name)                                          \
2071 uint64_t helper_ev##name (uint64_t val)                                       \
2072 {                                                                             \
2073     return ((uint64_t)e##name(val >> 32) << 32) |                             \
2074             (uint64_t)e##name(val);                                           \
2075 }
2076 /* evfscfsi */
2077 HELPER_SPE_VECTOR_CONV(fscfsi);
2078 /* evfscfui */
2079 HELPER_SPE_VECTOR_CONV(fscfui);
2080 /* evfscfuf */
2081 HELPER_SPE_VECTOR_CONV(fscfuf);
2082 /* evfscfsf */
2083 HELPER_SPE_VECTOR_CONV(fscfsf);
2084 /* evfsctsi */
2085 HELPER_SPE_VECTOR_CONV(fsctsi);
2086 /* evfsctui */
2087 HELPER_SPE_VECTOR_CONV(fsctui);
2088 /* evfsctsiz */
2089 HELPER_SPE_VECTOR_CONV(fsctsiz);
2090 /* evfsctuiz */
2091 HELPER_SPE_VECTOR_CONV(fsctuiz);
2092 /* evfsctsf */
2093 HELPER_SPE_VECTOR_CONV(fsctsf);
2094 /* evfsctuf */
2095 HELPER_SPE_VECTOR_CONV(fsctuf);
2096
2097 /* Single-precision floating-point arithmetic */
2098 static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
2099 {
2100     CPU_FloatU u1, u2;
2101     u1.l = op1;
2102     u2.l = op2;
2103     u1.f = float32_add(u1.f, u2.f, &env->spe_status);
2104     return u1.l;
2105 }
2106
2107 static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
2108 {
2109     CPU_FloatU u1, u2;
2110     u1.l = op1;
2111     u2.l = op2;
2112     u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
2113     return u1.l;
2114 }
2115
2116 static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
2117 {
2118     CPU_FloatU u1, u2;
2119     u1.l = op1;
2120     u2.l = op2;
2121     u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
2122     return u1.l;
2123 }
2124
2125 static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
2126 {
2127     CPU_FloatU u1, u2;
2128     u1.l = op1;
2129     u2.l = op2;
2130     u1.f = float32_div(u1.f, u2.f, &env->spe_status);
2131     return u1.l;
2132 }
2133
2134 #define HELPER_SPE_SINGLE_ARITH(name)                                         \
2135 uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2136 {                                                                             \
2137     return e##name(op1, op2);                                                 \
2138 }
2139 /* efsadd */
2140 HELPER_SPE_SINGLE_ARITH(fsadd);
2141 /* efssub */
2142 HELPER_SPE_SINGLE_ARITH(fssub);
2143 /* efsmul */
2144 HELPER_SPE_SINGLE_ARITH(fsmul);
2145 /* efsdiv */
2146 HELPER_SPE_SINGLE_ARITH(fsdiv);
2147
2148 #define HELPER_SPE_VECTOR_ARITH(name)                                         \
2149 uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2150 {                                                                             \
2151     return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
2152             (uint64_t)e##name(op1, op2);                                      \
2153 }
2154 /* evfsadd */
2155 HELPER_SPE_VECTOR_ARITH(fsadd);
2156 /* evfssub */
2157 HELPER_SPE_VECTOR_ARITH(fssub);
2158 /* evfsmul */
2159 HELPER_SPE_VECTOR_ARITH(fsmul);
2160 /* evfsdiv */
2161 HELPER_SPE_VECTOR_ARITH(fsdiv);
2162
2163 /* Single-precision floating-point comparisons */
2164 static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
2165 {
2166     CPU_FloatU u1, u2;
2167     u1.l = op1;
2168     u2.l = op2;
2169     return float32_lt(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2170 }
2171
2172 static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
2173 {
2174     CPU_FloatU u1, u2;
2175     u1.l = op1;
2176     u2.l = op2;
2177     return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 4;
2178 }
2179
2180 static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
2181 {
2182     CPU_FloatU u1, u2;
2183     u1.l = op1;
2184     u2.l = op2;
2185     return float32_eq(u1.f, u2.f, &env->spe_status) ? 4 : 0;
2186 }
2187
2188 static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
2189 {
2190     /* XXX: TODO: test special values (NaN, infinites, ...) */
2191     return efststlt(op1, op2);
2192 }
2193
2194 static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
2195 {
2196     /* XXX: TODO: test special values (NaN, infinites, ...) */
2197     return efststgt(op1, op2);
2198 }
2199
2200 static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
2201 {
2202     /* XXX: TODO: test special values (NaN, infinites, ...) */
2203     return efststeq(op1, op2);
2204 }
2205
2206 #define HELPER_SINGLE_SPE_CMP(name)                                           \
2207 uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
2208 {                                                                             \
2209     return e##name(op1, op2) << 2;                                            \
2210 }
2211 /* efststlt */
2212 HELPER_SINGLE_SPE_CMP(fststlt);
2213 /* efststgt */
2214 HELPER_SINGLE_SPE_CMP(fststgt);
2215 /* efststeq */
2216 HELPER_SINGLE_SPE_CMP(fststeq);
2217 /* efscmplt */
2218 HELPER_SINGLE_SPE_CMP(fscmplt);
2219 /* efscmpgt */
2220 HELPER_SINGLE_SPE_CMP(fscmpgt);
2221 /* efscmpeq */
2222 HELPER_SINGLE_SPE_CMP(fscmpeq);
2223
2224 static always_inline uint32_t evcmp_merge (int t0, int t1)
2225 {
2226     return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
2227 }
2228
2229 #define HELPER_VECTOR_SPE_CMP(name)                                           \
2230 uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
2231 {                                                                             \
2232     return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
2233 }
2234 /* evfststlt */
2235 HELPER_VECTOR_SPE_CMP(fststlt);
2236 /* evfststgt */
2237 HELPER_VECTOR_SPE_CMP(fststgt);
2238 /* evfststeq */
2239 HELPER_VECTOR_SPE_CMP(fststeq);
2240 /* evfscmplt */
2241 HELPER_VECTOR_SPE_CMP(fscmplt);
2242 /* evfscmpgt */
2243 HELPER_VECTOR_SPE_CMP(fscmpgt);
2244 /* evfscmpeq */
2245 HELPER_VECTOR_SPE_CMP(fscmpeq);
2246
2247 /* Double-precision floating-point conversion */
2248 uint64_t helper_efdcfsi (uint32_t val)
2249 {
2250     CPU_DoubleU u;
2251
2252     u.d = int32_to_float64(val, &env->spe_status);
2253
2254     return u.ll;
2255 }
2256
2257 uint64_t helper_efdcfsid (uint64_t val)
2258 {
2259     CPU_DoubleU u;
2260
2261     u.d = int64_to_float64(val, &env->spe_status);
2262
2263     return u.ll;
2264 }
2265
2266 uint64_t helper_efdcfui (uint32_t val)
2267 {
2268     CPU_DoubleU u;
2269
2270     u.d = uint32_to_float64(val, &env->spe_status);
2271
2272     return u.ll;
2273 }
2274
2275 uint64_t helper_efdcfuid (uint64_t val)
2276 {
2277     CPU_DoubleU u;
2278
2279     u.d = uint64_to_float64(val, &env->spe_status);
2280
2281     return u.ll;
2282 }
2283
2284 uint32_t helper_efdctsi (uint64_t val)
2285 {
2286     CPU_DoubleU u;
2287
2288     u.ll = val;
2289     /* NaN are not treated the same way IEEE 754 does */
2290     if (unlikely(isnan(u.d)))
2291         return 0;
2292
2293     return float64_to_int32(u.d, &env->spe_status);
2294 }
2295
2296 uint32_t helper_efdctui (uint64_t val)
2297 {
2298     CPU_DoubleU u;
2299
2300     u.ll = val;
2301     /* NaN are not treated the same way IEEE 754 does */
2302     if (unlikely(isnan(u.d)))
2303         return 0;
2304
2305     return float64_to_uint32(u.d, &env->spe_status);
2306 }
2307
2308 uint32_t helper_efdctsiz (uint64_t val)
2309 {
2310     CPU_DoubleU u;
2311
2312     u.ll = val;
2313     /* NaN are not treated the same way IEEE 754 does */
2314     if (unlikely(isnan(u.d)))
2315         return 0;
2316
2317     return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2318 }
2319
2320 uint64_t helper_efdctsidz (uint64_t val)
2321 {
2322     CPU_DoubleU u;
2323
2324     u.ll = val;
2325     /* NaN are not treated the same way IEEE 754 does */
2326     if (unlikely(isnan(u.d)))
2327         return 0;
2328
2329     return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2330 }
2331
2332 uint32_t helper_efdctuiz (uint64_t val)
2333 {
2334     CPU_DoubleU u;
2335
2336     u.ll = val;
2337     /* NaN are not treated the same way IEEE 754 does */
2338     if (unlikely(isnan(u.d)))
2339         return 0;
2340
2341     return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2342 }
2343
2344 uint64_t helper_efdctuidz (uint64_t val)
2345 {
2346     CPU_DoubleU u;
2347
2348     u.ll = val;
2349     /* NaN are not treated the same way IEEE 754 does */
2350     if (unlikely(isnan(u.d)))
2351         return 0;
2352
2353     return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2354 }
2355
2356 uint64_t helper_efdcfsf (uint32_t val)
2357 {
2358     CPU_DoubleU u;
2359     float64 tmp;
2360
2361     u.d = int32_to_float64(val, &env->spe_status);
2362     tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2363     u.d = float64_div(u.d, tmp, &env->spe_status);
2364
2365     return u.ll;
2366 }
2367
2368 uint64_t helper_efdcfuf (uint32_t val)
2369 {
2370     CPU_DoubleU u;
2371     float64 tmp;
2372
2373     u.d = uint32_to_float64(val, &env->spe_status);
2374     tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2375     u.d = float64_div(u.d, tmp, &env->spe_status);
2376
2377     return u.ll;
2378 }
2379
2380 uint32_t helper_efdctsf (uint64_t val)
2381 {
2382     CPU_DoubleU u;
2383     float64 tmp;
2384
2385     u.ll = val;
2386     /* NaN are not treated the same way IEEE 754 does */
2387     if (unlikely(isnan(u.d)))
2388         return 0;
2389     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2390     u.d = float64_mul(u.d, tmp, &env->spe_status);
2391
2392     return float64_to_int32(u.d, &env->spe_status);
2393 }
2394
2395 uint32_t helper_efdctuf (uint64_t val)
2396 {
2397     CPU_DoubleU u;
2398     float64 tmp;
2399
2400     u.ll = val;
2401     /* NaN are not treated the same way IEEE 754 does */
2402     if (unlikely(isnan(u.d)))
2403         return 0;
2404     tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2405     u.d = float64_mul(u.d, tmp, &env->spe_status);
2406
2407     return float64_to_uint32(u.d, &env->spe_status);
2408 }
2409
2410 uint32_t helper_efscfd (uint64_t val)
2411 {
2412     CPU_DoubleU u1;
2413     CPU_FloatU u2;
2414
2415     u1.ll = val;
2416     u2.f = float64_to_float32(u1.d, &env->spe_status);
2417
2418     return u2.l;
2419 }
2420
2421 uint64_t helper_efdcfs (uint32_t val)
2422 {
2423     CPU_DoubleU u2;
2424     CPU_FloatU u1;
2425
2426     u1.l = val;
2427     u2.d = float32_to_float64(u1.f, &env->spe_status);
2428
2429     return u2.ll;
2430 }
2431
2432 /* Double precision fixed-point arithmetic */
2433 uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
2434 {
2435     CPU_DoubleU u1, u2;
2436     u1.ll = op1;
2437     u2.ll = op2;
2438     u1.d = float64_add(u1.d, u2.d, &env->spe_status);
2439     return u1.ll;
2440 }
2441
2442 uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
2443 {
2444     CPU_DoubleU u1, u2;
2445     u1.ll = op1;
2446     u2.ll = op2;
2447     u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
2448     return u1.ll;
2449 }
2450
2451 uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
2452 {
2453     CPU_DoubleU u1, u2;
2454     u1.ll = op1;
2455     u2.ll = op2;
2456     u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
2457     return u1.ll;
2458 }
2459
2460 uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
2461 {
2462     CPU_DoubleU u1, u2;
2463     u1.ll = op1;
2464     u2.ll = op2;
2465     u1.d = float64_div(u1.d, u2.d, &env->spe_status);
2466     return u1.ll;
2467 }
2468
2469 /* Double precision floating point helpers */
2470 uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
2471 {
2472     CPU_DoubleU u1, u2;
2473     u1.ll = op1;
2474     u2.ll = op2;
2475     return float64_lt(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2476 }
2477
2478 uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
2479 {
2480     CPU_DoubleU u1, u2;
2481     u1.ll = op1;
2482     u2.ll = op2;
2483     return float64_le(u1.d, u2.d, &env->spe_status) ? 0 : 4;
2484 }
2485
2486 uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
2487 {
2488     CPU_DoubleU u1, u2;
2489     u1.ll = op1;
2490     u2.ll = op2;
2491     return float64_eq(u1.d, u2.d, &env->spe_status) ? 4 : 0;
2492 }
2493
2494 uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
2495 {
2496     /* XXX: TODO: test special values (NaN, infinites, ...) */
2497     return helper_efdtstlt(op1, op2);
2498 }
2499
2500 uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
2501 {
2502     /* XXX: TODO: test special values (NaN, infinites, ...) */
2503     return helper_efdtstgt(op1, op2);
2504 }
2505
2506 uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
2507 {
2508     /* XXX: TODO: test special values (NaN, infinites, ...) */
2509     return helper_efdtsteq(op1, op2);
2510 }
2511
2512 /*****************************************************************************/
2513 /* Softmmu support */
2514 #if !defined (CONFIG_USER_ONLY)
2515
2516 #define MMUSUFFIX _mmu
2517
2518 #define SHIFT 0
2519 #include "softmmu_template.h"
2520
2521 #define SHIFT 1
2522 #include "softmmu_template.h"
2523
2524 #define SHIFT 2
2525 #include "softmmu_template.h"
2526
2527 #define SHIFT 3
2528 #include "softmmu_template.h"
2529
2530 /* try to fill the TLB and return an exception if error. If retaddr is
2531    NULL, it means that the function was called in C code (i.e. not
2532    from generated code or from helper.c) */
2533 /* XXX: fix it to restore all registers */
2534 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2535 {
2536     TranslationBlock *tb;
2537     CPUState *saved_env;
2538     unsigned long pc;
2539     int ret;
2540
2541     /* XXX: hack to restore env in all cases, even if not called from
2542        generated code */
2543     saved_env = env;
2544     env = cpu_single_env;
2545     ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2546     if (unlikely(ret != 0)) {
2547         if (likely(retaddr)) {
2548             /* now we have a real cpu fault */
2549             pc = (unsigned long)retaddr;
2550             tb = tb_find_pc(pc);
2551             if (likely(tb)) {
2552                 /* the PC is inside the translated code. It means that we have
2553                    a virtual CPU fault */
2554                 cpu_restore_state(tb, env, pc, NULL);
2555             }
2556         }
2557         raise_exception_err(env, env->exception_index, env->error_code);
2558     }
2559     env = saved_env;
2560 }
2561
2562 /* Software driven TLBs management */
2563 /* PowerPC 602/603 software TLB load instructions helpers */
2564 static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code)
2565 {
2566     target_ulong RPN, CMP, EPN;
2567     int way;
2568
2569     RPN = env->spr[SPR_RPA];
2570     if (is_code) {
2571         CMP = env->spr[SPR_ICMP];
2572         EPN = env->spr[SPR_IMISS];
2573     } else {
2574         CMP = env->spr[SPR_DCMP];
2575         EPN = env->spr[SPR_DMISS];
2576     }
2577     way = (env->spr[SPR_SRR1] >> 17) & 1;
2578 #if defined (DEBUG_SOFTWARE_TLB)
2579     if (loglevel != 0) {
2580         fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2581                 " PTE1 " ADDRX " way %d\n",
2582                 __func__, T0, EPN, CMP, RPN, way);
2583     }
2584 #endif
2585     /* Store this TLB */
2586     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2587                      way, is_code, CMP, RPN);
2588 }
2589
2590 void helper_load_6xx_tlbd (target_ulong EPN)
2591 {
2592     helper_load_6xx_tlb(EPN, 0);
2593 }
2594
2595 void helper_load_6xx_tlbi (target_ulong EPN)
2596 {
2597     helper_load_6xx_tlb(EPN, 1);
2598 }
2599
2600 /* PowerPC 74xx software TLB load instructions helpers */
2601 static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code)
2602 {
2603     target_ulong RPN, CMP, EPN;
2604     int way;
2605
2606     RPN = env->spr[SPR_PTELO];
2607     CMP = env->spr[SPR_PTEHI];
2608     EPN = env->spr[SPR_TLBMISS] & ~0x3;
2609     way = env->spr[SPR_TLBMISS] & 0x3;
2610 #if defined (DEBUG_SOFTWARE_TLB)
2611     if (loglevel != 0) {
2612         fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2613                 " PTE1 " ADDRX " way %d\n",
2614                 __func__, T0, EPN, CMP, RPN, way);
2615     }
2616 #endif
2617     /* Store this TLB */
2618     ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2619                      way, is_code, CMP, RPN);
2620 }
2621
2622 void helper_load_74xx_tlbd (target_ulong EPN)
2623 {
2624     helper_load_74xx_tlb(EPN, 0);
2625 }
2626
2627 void helper_load_74xx_tlbi (target_ulong EPN)
2628 {
2629     helper_load_74xx_tlb(EPN, 1);
2630 }
2631
2632 static always_inline target_ulong booke_tlb_to_page_size (int size)
2633 {
2634     return 1024 << (2 * size);
2635 }
2636
2637 static always_inline int booke_page_size_to_tlb (target_ulong page_size)
2638 {
2639     int size;
2640
2641     switch (page_size) {
2642     case 0x00000400UL:
2643         size = 0x0;
2644         break;
2645     case 0x00001000UL:
2646         size = 0x1;
2647         break;
2648     case 0x00004000UL:
2649         size = 0x2;
2650         break;
2651     case 0x00010000UL:
2652         size = 0x3;
2653         break;
2654     case 0x00040000UL:
2655         size = 0x4;
2656         break;
2657     case 0x00100000UL:
2658         size = 0x5;
2659         break;
2660     case 0x00400000UL:
2661         size = 0x6;
2662         break;
2663     case 0x01000000UL:
2664         size = 0x7;
2665         break;
2666     case 0x04000000UL:
2667         size = 0x8;
2668         break;
2669     case 0x10000000UL:
2670         size = 0x9;
2671         break;
2672     case 0x40000000UL:
2673         size = 0xA;
2674         break;
2675 #if defined (TARGET_PPC64)
2676     case 0x000100000000ULL:
2677         size = 0xB;
2678         break;
2679     case 0x000400000000ULL:
2680         size = 0xC;
2681         break;
2682     case 0x001000000000ULL:
2683         size = 0xD;
2684         break;
2685     case 0x004000000000ULL:
2686         size = 0xE;
2687         break;
2688     case 0x010000000000ULL:
2689         size = 0xF;
2690         break;
2691 #endif
2692     default:
2693         size = -1;
2694         break;
2695     }
2696
2697     return size;
2698 }
2699
2700 /* Helpers for 4xx TLB management */
2701 void do_4xx_tlbre_lo (void)
2702 {
2703     ppcemb_tlb_t *tlb;
2704     int size;
2705
2706     T0 &= 0x3F;
2707     tlb = &env->tlb[T0].tlbe;
2708     T0 = tlb->EPN;
2709     if (tlb->prot & PAGE_VALID)
2710         T0 |= 0x400;
2711     size = booke_page_size_to_tlb(tlb->size);
2712     if (size < 0 || size > 0x7)
2713         size = 1;
2714     T0 |= size << 7;
2715     env->spr[SPR_40x_PID] = tlb->PID;
2716 }
2717
2718 void do_4xx_tlbre_hi (void)
2719 {
2720     ppcemb_tlb_t *tlb;
2721
2722     T0 &= 0x3F;
2723     tlb = &env->tlb[T0].tlbe;
2724     T0 = tlb->RPN;
2725     if (tlb->prot & PAGE_EXEC)
2726         T0 |= 0x200;
2727     if (tlb->prot & PAGE_WRITE)
2728         T0 |= 0x100;
2729 }
2730
2731 void do_4xx_tlbwe_hi (void)
2732 {
2733     ppcemb_tlb_t *tlb;
2734     target_ulong page, end;
2735
2736 #if defined (DEBUG_SOFTWARE_TLB)
2737     if (loglevel != 0) {
2738         fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2739     }
2740 #endif
2741     T0 &= 0x3F;
2742     tlb = &env->tlb[T0].tlbe;
2743     /* Invalidate previous TLB (if it's valid) */
2744     if (tlb->prot & PAGE_VALID) {
2745         end = tlb->EPN + tlb->size;
2746 #if defined (DEBUG_SOFTWARE_TLB)
2747         if (loglevel != 0) {
2748             fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2749                     " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2750         }
2751 #endif
2752         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2753             tlb_flush_page(env, page);
2754     }
2755     tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2756     /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2757      * If this ever occurs, one should use the ppcemb target instead
2758      * of the ppc or ppc64 one
2759      */
2760     if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2761         cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2762                   "are not supported (%d)\n",
2763                   tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
2764     }
2765     tlb->EPN = T1 & ~(tlb->size - 1);
2766     if (T1 & 0x40)
2767         tlb->prot |= PAGE_VALID;
2768     else
2769         tlb->prot &= ~PAGE_VALID;
2770     if (T1 & 0x20) {
2771         /* XXX: TO BE FIXED */
2772         cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2773     }
2774     tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2775     tlb->attr = T1 & 0xFF;
2776 #if defined (DEBUG_SOFTWARE_TLB)
2777     if (loglevel != 0) {
2778         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2779                 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2780                 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2781                 tlb->prot & PAGE_READ ? 'r' : '-',
2782                 tlb->prot & PAGE_WRITE ? 'w' : '-',
2783                 tlb->prot & PAGE_EXEC ? 'x' : '-',
2784                 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2785     }
2786 #endif
2787     /* Invalidate new TLB (if valid) */
2788     if (tlb->prot & PAGE_VALID) {
2789         end = tlb->EPN + tlb->size;
2790 #if defined (DEBUG_SOFTWARE_TLB)
2791         if (loglevel != 0) {
2792             fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2793                     " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2794         }
2795 #endif
2796         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2797             tlb_flush_page(env, page);
2798     }
2799 }
2800
2801 void do_4xx_tlbwe_lo (void)
2802 {
2803     ppcemb_tlb_t *tlb;
2804
2805 #if defined (DEBUG_SOFTWARE_TLB)
2806     if (loglevel != 0) {
2807         fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2808     }
2809 #endif
2810     T0 &= 0x3F;
2811     tlb = &env->tlb[T0].tlbe;
2812     tlb->RPN = T1 & 0xFFFFFC00;
2813     tlb->prot = PAGE_READ;
2814     if (T1 & 0x200)
2815         tlb->prot |= PAGE_EXEC;
2816     if (T1 & 0x100)
2817         tlb->prot |= PAGE_WRITE;
2818 #if defined (DEBUG_SOFTWARE_TLB)
2819     if (loglevel != 0) {
2820         fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2821                 " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2822                 (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2823                 tlb->prot & PAGE_READ ? 'r' : '-',
2824                 tlb->prot & PAGE_WRITE ? 'w' : '-',
2825                 tlb->prot & PAGE_EXEC ? 'x' : '-',
2826                 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2827     }
2828 #endif
2829 }
2830
2831 /* PowerPC 440 TLB management */
2832 void do_440_tlbwe (int word)
2833 {
2834     ppcemb_tlb_t *tlb;
2835     target_ulong EPN, RPN, size;
2836     int do_flush_tlbs;
2837
2838 #if defined (DEBUG_SOFTWARE_TLB)
2839     if (loglevel != 0) {
2840         fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
2841                 __func__, word, T0, T1);
2842     }
2843 #endif
2844     do_flush_tlbs = 0;
2845     T0 &= 0x3F;
2846     tlb = &env->tlb[T0].tlbe;
2847     switch (word) {
2848     default:
2849         /* Just here to please gcc */
2850     case 0:
2851         EPN = T1 & 0xFFFFFC00;
2852         if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2853             do_flush_tlbs = 1;
2854         tlb->EPN = EPN;
2855         size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2856         if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2857             do_flush_tlbs = 1;
2858         tlb->size = size;
2859         tlb->attr &= ~0x1;
2860         tlb->attr |= (T1 >> 8) & 1;
2861         if (T1 & 0x200) {
2862             tlb->prot |= PAGE_VALID;
2863         } else {
2864             if (tlb->prot & PAGE_VALID) {
2865                 tlb->prot &= ~PAGE_VALID;
2866                 do_flush_tlbs = 1;
2867             }
2868         }
2869         tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2870         if (do_flush_tlbs)
2871             tlb_flush(env, 1);
2872         break;
2873     case 1:
2874         RPN = T1 & 0xFFFFFC0F;
2875         if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2876             tlb_flush(env, 1);
2877         tlb->RPN = RPN;
2878         break;
2879     case 2:
2880         tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2881         tlb->prot = tlb->prot & PAGE_VALID;
2882         if (T1 & 0x1)
2883             tlb->prot |= PAGE_READ << 4;
2884         if (T1 & 0x2)
2885             tlb->prot |= PAGE_WRITE << 4;
2886         if (T1 & 0x4)
2887             tlb->prot |= PAGE_EXEC << 4;
2888         if (T1 & 0x8)
2889             tlb->prot |= PAGE_READ;
2890         if (T1 & 0x10)
2891             tlb->prot |= PAGE_WRITE;
2892         if (T1 & 0x20)
2893             tlb->prot |= PAGE_EXEC;
2894         break;
2895     }
2896 }
2897
2898 void do_440_tlbre (int word)
2899 {
2900     ppcemb_tlb_t *tlb;
2901     int size;
2902
2903     T0 &= 0x3F;
2904     tlb = &env->tlb[T0].tlbe;
2905     switch (word) {
2906     default:
2907         /* Just here to please gcc */
2908     case 0:
2909         T0 = tlb->EPN;
2910         size = booke_page_size_to_tlb(tlb->size);
2911         if (size < 0 || size > 0xF)
2912             size = 1;
2913         T0 |= size << 4;
2914         if (tlb->attr & 0x1)
2915             T0 |= 0x100;
2916         if (tlb->prot & PAGE_VALID)
2917             T0 |= 0x200;
2918         env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2919         env->spr[SPR_440_MMUCR] |= tlb->PID;
2920         break;
2921     case 1:
2922         T0 = tlb->RPN;
2923         break;
2924     case 2:
2925         T0 = tlb->attr & ~0x1;
2926         if (tlb->prot & (PAGE_READ << 4))
2927             T0 |= 0x1;
2928         if (tlb->prot & (PAGE_WRITE << 4))
2929             T0 |= 0x2;
2930         if (tlb->prot & (PAGE_EXEC << 4))
2931             T0 |= 0x4;
2932         if (tlb->prot & PAGE_READ)
2933             T0 |= 0x8;
2934         if (tlb->prot & PAGE_WRITE)
2935             T0 |= 0x10;
2936         if (tlb->prot & PAGE_EXEC)
2937             T0 |= 0x20;
2938         break;
2939     }
2940 }
2941 #endif /* !CONFIG_USER_ONLY */
This page took 0.180838 seconds and 4 git commands to generate.