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