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