Fix format specified for watchpoint address.
[qemu/mini2440.git] / target-ppc / op_helper.c
bloba65da36b7b346c7b62c827457087d6ac3ddd21f9
1 /*
2 * PowerPC emulation helpers for qemu.
3 *
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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
20 #include "exec.h"
22 #include "op_helper.h"
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
36 //#define DEBUG_OP
37 //#define DEBUG_EXCEPTIONS
38 //#define DEBUG_SOFTWARE_TLB
39 //#define FLUSH_ALL_TLBS
41 /*****************************************************************************/
42 /* Exceptions processing helpers */
43 void cpu_loop_exit (void)
45 longjmp(env->jmp_env, 1);
48 void do_raise_exception_err (uint32_t exception, int error_code)
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;
61 env->exception_index = exception;
62 env->error_code = error_code;
63 cpu_loop_exit();
66 void do_raise_exception (uint32_t exception)
68 do_raise_exception_err(exception, 0);
71 /*****************************************************************************/
72 /* Registers load and stores */
73 void do_load_cr (void)
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);
85 void do_store_cr (uint32_t mask)
87 int i, sh;
89 for (i = 0, sh = 7; i < 8; i++, sh --) {
90 if (mask & (1 << sh))
91 env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
95 void do_load_xer (void)
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);
104 void do_store_xer (void)
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;
113 void do_load_fpscr (void)
115 /* The 32 MSB of the target fpr are undefined.
116 * They'll be zero...
118 union {
119 float64 d;
120 struct {
121 uint32_t u[2];
122 } s;
123 } u;
124 int i;
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;
140 void do_store_fpscr (uint32_t mask)
143 * We use only the 32 LSB of the incoming fpr
145 union {
146 double d;
147 struct {
148 uint32_t u[2];
149 } s;
150 } u;
151 int i, rnd_type;
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;
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;
181 set_float_rounding_mode(rnd_type, &env->fp_status);
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)
189 *plow += a;
190 /* carry test */
191 if (*plow < a)
192 (*phigh)++;
193 *phigh += b;
196 static void neg128 (uint64_t *plow, uint64_t *phigh)
198 *plow = ~ *plow;
199 *phigh = ~ *phigh;
200 add128(plow, phigh, 1, 0);
203 static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
205 uint32_t a0, a1, b0, b1;
206 uint64_t v;
208 a0 = a;
209 a1 = a >> 32;
211 b0 = b;
212 b1 = b >> 32;
214 v = (uint64_t)a0 * (uint64_t)b0;
215 *plow = v;
216 *phigh = 0;
218 v = (uint64_t)a0 * (uint64_t)b1;
219 add128(plow, phigh, v << 32, v >> 32);
221 v = (uint64_t)a1 * (uint64_t)b0;
222 add128(plow, phigh, v << 32, v >> 32);
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
232 void do_mul64 (uint64_t *plow, uint64_t *phigh)
234 mul64(plow, phigh, T0, T1);
237 static void imul64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
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);
252 void do_imul64 (uint64_t *plow, uint64_t *phigh)
254 imul64(plow, phigh, T0, T1);
256 #endif
258 void do_adde (void)
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;
270 #if defined(TARGET_PPC64)
271 void do_adde_64 (void)
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;
282 #endif
284 void do_addmeo (void)
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;
295 if (likely(T1 != 0))
296 xer_ca = 1;
299 #if defined(TARGET_PPC64)
300 void do_addmeo_64 (void)
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;
311 if (likely(T1 != 0))
312 xer_ca = 1;
314 #endif
316 void do_divwo (void)
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);
329 #if defined(TARGET_PPC64)
330 void do_divdo (void)
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);
342 #endif
344 void do_divwuo (void)
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;
356 #if defined(TARGET_PPC64)
357 void do_divduo (void)
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;
368 #endif
370 void do_mullwo (void)
372 int64_t res = (int64_t)T0 * (int64_t)T1;
374 if (likely((int32_t)res == res)) {
375 xer_ov = 0;
376 } else {
377 xer_ov = 1;
378 xer_so = 1;
380 T0 = (int32_t)res;
383 #if defined(TARGET_PPC64)
384 void do_mulldo (void)
386 int64_t th;
387 uint64_t tl;
389 do_imul64(&tl, &th);
390 if (likely(th == 0)) {
391 xer_ov = 0;
392 } else {
393 xer_ov = 1;
394 xer_so = 1;
396 T0 = (int64_t)tl;
398 #endif
400 void do_nego (void)
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;
411 #if defined(TARGET_PPC64)
412 void do_nego_64 (void)
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;
422 #endif
424 void do_subfe (void)
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;
435 #if defined(TARGET_PPC64)
436 void do_subfe_64 (void)
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;
446 #endif
448 void do_subfmeo (void)
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;
459 if (likely((uint32_t)T1 != UINT32_MAX))
460 xer_ca = 1;
463 #if defined(TARGET_PPC64)
464 void do_subfmeo_64 (void)
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;
475 if (likely((uint64_t)T1 != UINT64_MAX))
476 xer_ca = 1;
478 #endif
480 void do_subfzeo (void)
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;
491 if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
492 xer_ca = 0;
493 } else {
494 xer_ca = 1;
498 #if defined(TARGET_PPC64)
499 void do_subfzeo_64 (void)
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;
510 if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
511 xer_ca = 0;
512 } else {
513 xer_ca = 1;
516 #endif
518 /* shift right arithmetic helper */
519 void do_sraw (void)
521 int32_t ret;
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;
531 } else {
532 ret = T0;
533 xer_ca = 0;
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;
543 T0 = ret;
546 #if defined(TARGET_PPC64)
547 void do_srad (void)
549 int64_t ret;
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;
559 } else {
560 ret = T0;
561 xer_ca = 0;
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;
571 T0 = ret;
573 #endif
575 static inline int popcnt (uint32_t val)
577 int i;
579 for (i = 0; val != 0;)
580 val = val ^ (val - 1);
582 return i;
585 void do_popcntb (void)
587 uint32_t ret;
588 int i;
590 ret = 0;
591 for (i = 0; i < 32; i += 8)
592 ret |= popcnt((T0 >> i) & 0xFF) << i;
593 T0 = ret;
596 #if defined(TARGET_PPC64)
597 void do_popcntb_64 (void)
599 uint64_t ret;
600 int i;
602 ret = 0;
603 for (i = 0; i < 64; i += 8)
604 ret |= popcnt((T0 >> i) & 0xFF) << i;
605 T0 = ret;
607 #endif
609 /*****************************************************************************/
610 /* Floating point operations helpers */
611 void do_fctiw (void)
613 union {
614 double d;
615 uint64_t i;
616 } p;
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)
623 p.i |= 0xFFF80000ULL << 32;
624 #endif
625 FT0 = p.d;
628 void do_fctiwz (void)
630 union {
631 double d;
632 uint64_t i;
633 } p;
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)
640 p.i |= 0xFFF80000ULL << 32;
641 #endif
642 FT0 = p.d;
645 #if defined(TARGET_PPC64)
646 void do_fcfid (void)
648 union {
649 double d;
650 uint64_t i;
651 } p;
653 p.d = FT0;
654 FT0 = int64_to_float64(p.i, &env->fp_status);
657 void do_fctid (void)
659 union {
660 double d;
661 uint64_t i;
662 } p;
664 p.i = float64_to_int64(FT0, &env->fp_status);
665 FT0 = p.d;
668 void do_fctidz (void)
670 union {
671 double d;
672 uint64_t i;
673 } p;
675 p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
676 FT0 = p.d;
679 #endif
681 #if USE_PRECISE_EMULATION
682 void do_fmadd (void)
684 #ifdef FLOAT128
685 float128 ft0_128, ft1_128;
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
699 void do_fmsub (void)
701 #ifdef FLOAT128
702 float128 ft0_128, ft1_128;
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
715 #endif /* USE_PRECISE_EMULATION */
717 void do_fnmadd (void)
719 #if USE_PRECISE_EMULATION
720 #ifdef FLOAT128
721 float128 ft0_128, ft1_128;
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);
741 void do_fnmsub (void)
743 #if USE_PRECISE_EMULATION
744 #ifdef FLOAT128
745 float128 ft0_128, ft1_128;
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);
765 void do_fsqrt (void)
767 FT0 = float64_sqrt(FT0, &env->fp_status);
770 void do_fres (void)
772 union {
773 double d;
774 uint64_t i;
775 } p;
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;
797 FT0 = p.d;
801 void do_frsqrte (void)
803 union {
804 double d;
805 uint64_t i;
806 } p;
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;
825 FT0 = p.d;
829 void do_fsel (void)
831 if (FT0 >= 0)
832 FT0 = FT1;
833 else
834 FT0 = FT2;
837 void do_fcmpu (void)
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;
847 } else {
848 T0 = 0x01UL;
849 env->fpscr[4] |= 0x1;
850 env->fpscr[6] |= 0x1;
852 env->fpscr[3] = T0;
855 void do_fcmpo (void)
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;
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;
878 env->fpscr[3] = T0;
881 #if !defined (CONFIG_USER_ONLY)
882 void do_rfi (void)
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));
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;
902 #if defined(TARGET_PPC64)
903 void do_rfid (void)
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));
912 #if defined (DEBUG_OP)
913 dump_rfi();
914 #endif
915 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
917 #endif
918 #endif
920 void do_tw (int flags)
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);
931 #if defined(TARGET_PPC64)
932 void do_td (int flags)
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);
941 #endif
943 /*****************************************************************************/
944 /* PowerPC 601 specific instructions (POWER bridge) */
945 void do_POWER_abso (void)
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;
957 void do_POWER_clcs (void)
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;
984 void do_POWER_div (void)
986 uint64_t tmp;
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;
998 void do_POWER_divo (void)
1000 int64_t tmp;
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;
1017 T0 = tmp;
1021 void do_POWER_divs (void)
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;
1032 void do_POWER_divso (void)
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;
1046 void do_POWER_dozo (void)
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;
1058 } else {
1059 T0 = 0;
1060 xer_ov = 0;
1064 void do_POWER_maskg (void)
1066 uint32_t ret;
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;
1076 T0 = ret;
1079 void do_POWER_mulo (void)
1081 uint64_t tmp;
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;
1094 #if !defined (CONFIG_USER_ONLY)
1095 void do_POWER_rac (void)
1097 #if 0
1098 mmu_ctx_t ctx;
1100 /* We don't have to generate many instances of this instruction,
1101 * as rac is supervisor only.
1103 if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
1104 T0 = ctx.raddr;
1105 #endif
1108 void do_POWER_rfsvc (void)
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;
1119 /* PowerPC 601 BAT management helper */
1120 void do_store_601_batu (int nr)
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];
1126 #endif
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)
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
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;
1160 /*****************************************************************************/
1161 /* Embedded PowerPC specific helpers */
1162 void do_405_check_ov (void)
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;
1173 void do_405_check_sat (void)
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;
1186 #if !defined(CONFIG_USER_ONLY)
1187 void do_40x_rfci (void)
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;
1197 void do_rfci (void)
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
1205 env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
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;
1214 void do_rfdi (void)
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
1222 env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
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;
1231 void do_rfmci (void)
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
1239 env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
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;
1248 void do_load_dcr (void)
1250 target_ulong val;
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;
1263 void do_store_dcr (void)
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);
1274 void do_load_403_pb (int num)
1276 T0 = env->pb[num];
1279 void do_store_403_pb (int num)
1281 if (likely(env->pb[num] != T0)) {
1282 env->pb[num] = T0;
1283 /* Should be optimized */
1284 tlb_flush(env, 1);
1287 #endif
1289 /* 440 specific */
1290 void do_440_dlmzb (void)
1292 target_ulong mask;
1293 int i;
1295 i = 1;
1296 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1297 if ((T0 & mask) == 0)
1298 goto done;
1299 i++;
1301 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1302 if ((T1 & mask) == 0)
1303 break;
1304 i++;
1306 done:
1307 T0 = i;
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,
1318 static inline uint8_t byte_reverse (uint8_t val)
1320 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1323 static inline uint32_t word_reverse (uint32_t val)
1325 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1326 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1329 #define MASKBITS 16 // Random value - to be fixed
1330 void do_brinc (void)
1332 uint32_t a, b, d, mask;
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);
1341 #define DO_SPE_OP2(name) \
1342 void do_ev##name (void) \
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); \
1348 #define DO_SPE_OP1(name) \
1349 void do_ev##name (void) \
1351 T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) | \
1352 (uint64_t)_do_e##name(T0_64); \
1355 /* Fixed-point vector arithmetic */
1356 static inline uint32_t _do_eabs (uint32_t val)
1358 if (val != 0x80000000)
1359 val &= ~0x80000000;
1361 return val;
1364 static inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1366 return op1 + op2;
1369 static inline int _do_ecntlsw (uint32_t val)
1371 if (val & 0x80000000)
1372 return _do_cntlzw(~val);
1373 else
1374 return _do_cntlzw(val);
1377 static inline int _do_ecntlzw (uint32_t val)
1379 return _do_cntlzw(val);
1382 static inline uint32_t _do_eneg (uint32_t val)
1384 if (val != 0x80000000)
1385 val ^= 0x80000000;
1387 return val;
1390 static inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1392 return rotl32(op1, op2);
1395 static inline uint32_t _do_erndw (uint32_t val)
1397 return (val + 0x000080000000) & 0xFFFF0000;
1400 static inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1402 /* No error here: 6 bits are used */
1403 return op1 << (op2 & 0x3F);
1406 static inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1408 /* No error here: 6 bits are used */
1409 return op1 >> (op2 & 0x3F);
1412 static inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1414 /* No error here: 6 bits are used */
1415 return op1 >> (op2 & 0x3F);
1418 static inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1420 return op2 - op1;
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);
1446 /* evsel is a little bit more complicated... */
1447 static inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1449 if (n)
1450 return op1;
1451 else
1452 return op2;
1455 void do_evsel (void)
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);
1461 /* Fixed-point vector comparisons */
1462 #define DO_SPE_CMP(name) \
1463 void do_ev##name (void) \
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)); \
1470 static inline uint32_t _do_evcmp_merge (int t0, int t1)
1472 return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1474 static inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1476 return op1 == op2 ? 1 : 0;
1479 static inline int _do_ecmpgts (int32_t op1, int32_t op2)
1481 return op1 > op2 ? 1 : 0;
1484 static inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
1486 return op1 > op2 ? 1 : 0;
1489 static inline int _do_ecmplts (int32_t op1, int32_t op2)
1491 return op1 < op2 ? 1 : 0;
1494 static inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
1496 return op1 < op2 ? 1 : 0;
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);
1510 /* Single precision floating-point conversions from/to integer */
1511 static inline uint32_t _do_efscfsi (int32_t val)
1513 union {
1514 uint32_t u;
1515 float32 f;
1516 } u;
1518 u.f = int32_to_float32(val, &env->spe_status);
1520 return u.u;
1523 static inline uint32_t _do_efscfui (uint32_t val)
1525 union {
1526 uint32_t u;
1527 float32 f;
1528 } u;
1530 u.f = uint32_to_float32(val, &env->spe_status);
1532 return u.u;
1535 static inline int32_t _do_efsctsi (uint32_t val)
1537 union {
1538 int32_t u;
1539 float32 f;
1540 } u;
1542 u.u = val;
1543 /* NaN are not treated the same way IEEE 754 does */
1544 if (unlikely(isnan(u.f)))
1545 return 0;
1547 return float32_to_int32(u.f, &env->spe_status);
1550 static inline uint32_t _do_efsctui (uint32_t val)
1552 union {
1553 int32_t u;
1554 float32 f;
1555 } u;
1557 u.u = val;
1558 /* NaN are not treated the same way IEEE 754 does */
1559 if (unlikely(isnan(u.f)))
1560 return 0;
1562 return float32_to_uint32(u.f, &env->spe_status);
1565 static inline int32_t _do_efsctsiz (uint32_t val)
1567 union {
1568 int32_t u;
1569 float32 f;
1570 } u;
1572 u.u = val;
1573 /* NaN are not treated the same way IEEE 754 does */
1574 if (unlikely(isnan(u.f)))
1575 return 0;
1577 return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1580 static inline uint32_t _do_efsctuiz (uint32_t val)
1582 union {
1583 int32_t u;
1584 float32 f;
1585 } u;
1587 u.u = val;
1588 /* NaN are not treated the same way IEEE 754 does */
1589 if (unlikely(isnan(u.f)))
1590 return 0;
1592 return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1595 void do_efscfsi (void)
1597 T0_64 = _do_efscfsi(T0_64);
1600 void do_efscfui (void)
1602 T0_64 = _do_efscfui(T0_64);
1605 void do_efsctsi (void)
1607 T0_64 = _do_efsctsi(T0_64);
1610 void do_efsctui (void)
1612 T0_64 = _do_efsctui(T0_64);
1615 void do_efsctsiz (void)
1617 T0_64 = _do_efsctsiz(T0_64);
1620 void do_efsctuiz (void)
1622 T0_64 = _do_efsctuiz(T0_64);
1625 /* Single precision floating-point conversion to/from fractional */
1626 static inline uint32_t _do_efscfsf (uint32_t val)
1628 union {
1629 uint32_t u;
1630 float32 f;
1631 } u;
1632 float32 tmp;
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);
1638 return u.u;
1641 static inline uint32_t _do_efscfuf (uint32_t val)
1643 union {
1644 uint32_t u;
1645 float32 f;
1646 } u;
1647 float32 tmp;
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);
1653 return u.u;
1656 static inline int32_t _do_efsctsf (uint32_t val)
1658 union {
1659 int32_t u;
1660 float32 f;
1661 } u;
1662 float32 tmp;
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);
1671 return float32_to_int32(u.f, &env->spe_status);
1674 static inline uint32_t _do_efsctuf (uint32_t val)
1676 union {
1677 int32_t u;
1678 float32 f;
1679 } u;
1680 float32 tmp;
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);
1689 return float32_to_uint32(u.f, &env->spe_status);
1692 static inline int32_t _do_efsctsfz (uint32_t val)
1694 union {
1695 int32_t u;
1696 float32 f;
1697 } u;
1698 float32 tmp;
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);
1707 return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1710 static inline uint32_t _do_efsctufz (uint32_t val)
1712 union {
1713 int32_t u;
1714 float32 f;
1715 } u;
1716 float32 tmp;
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);
1725 return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1728 void do_efscfsf (void)
1730 T0_64 = _do_efscfsf(T0_64);
1733 void do_efscfuf (void)
1735 T0_64 = _do_efscfuf(T0_64);
1738 void do_efsctsf (void)
1740 T0_64 = _do_efsctsf(T0_64);
1743 void do_efsctuf (void)
1745 T0_64 = _do_efsctuf(T0_64);
1748 void do_efsctsfz (void)
1750 T0_64 = _do_efsctsfz(T0_64);
1753 void do_efsctufz (void)
1755 T0_64 = _do_efsctufz(T0_64);
1758 /* Double precision floating point helpers */
1759 static inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1761 /* XXX: TODO: test special values (NaN, infinites, ...) */
1762 return _do_efdtstlt(op1, op2);
1765 static inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
1767 /* XXX: TODO: test special values (NaN, infinites, ...) */
1768 return _do_efdtstgt(op1, op2);
1771 static inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
1773 /* XXX: TODO: test special values (NaN, infinites, ...) */
1774 return _do_efdtsteq(op1, op2);
1777 void do_efdcmplt (void)
1779 T0 = _do_efdcmplt(T0_64, T1_64);
1782 void do_efdcmpgt (void)
1784 T0 = _do_efdcmpgt(T0_64, T1_64);
1787 void do_efdcmpeq (void)
1789 T0 = _do_efdcmpeq(T0_64, T1_64);
1792 /* Double precision floating-point conversion to/from integer */
1793 static inline uint64_t _do_efdcfsi (int64_t val)
1795 union {
1796 uint64_t u;
1797 float64 f;
1798 } u;
1800 u.f = int64_to_float64(val, &env->spe_status);
1802 return u.u;
1805 static inline uint64_t _do_efdcfui (uint64_t val)
1807 union {
1808 uint64_t u;
1809 float64 f;
1810 } u;
1812 u.f = uint64_to_float64(val, &env->spe_status);
1814 return u.u;
1817 static inline int64_t _do_efdctsi (uint64_t val)
1819 union {
1820 int64_t u;
1821 float64 f;
1822 } u;
1824 u.u = val;
1825 /* NaN are not treated the same way IEEE 754 does */
1826 if (unlikely(isnan(u.f)))
1827 return 0;
1829 return float64_to_int64(u.f, &env->spe_status);
1832 static inline uint64_t _do_efdctui (uint64_t val)
1834 union {
1835 int64_t u;
1836 float64 f;
1837 } u;
1839 u.u = val;
1840 /* NaN are not treated the same way IEEE 754 does */
1841 if (unlikely(isnan(u.f)))
1842 return 0;
1844 return float64_to_uint64(u.f, &env->spe_status);
1847 static inline int64_t _do_efdctsiz (uint64_t val)
1849 union {
1850 int64_t u;
1851 float64 f;
1852 } u;
1854 u.u = val;
1855 /* NaN are not treated the same way IEEE 754 does */
1856 if (unlikely(isnan(u.f)))
1857 return 0;
1859 return float64_to_int64_round_to_zero(u.f, &env->spe_status);
1862 static inline uint64_t _do_efdctuiz (uint64_t val)
1864 union {
1865 int64_t u;
1866 float64 f;
1867 } u;
1869 u.u = val;
1870 /* NaN are not treated the same way IEEE 754 does */
1871 if (unlikely(isnan(u.f)))
1872 return 0;
1874 return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
1877 void do_efdcfsi (void)
1879 T0_64 = _do_efdcfsi(T0_64);
1882 void do_efdcfui (void)
1884 T0_64 = _do_efdcfui(T0_64);
1887 void do_efdctsi (void)
1889 T0_64 = _do_efdctsi(T0_64);
1892 void do_efdctui (void)
1894 T0_64 = _do_efdctui(T0_64);
1897 void do_efdctsiz (void)
1899 T0_64 = _do_efdctsiz(T0_64);
1902 void do_efdctuiz (void)
1904 T0_64 = _do_efdctuiz(T0_64);
1907 /* Double precision floating-point conversion to/from fractional */
1908 static inline uint64_t _do_efdcfsf (int64_t val)
1910 union {
1911 uint64_t u;
1912 float64 f;
1913 } u;
1914 float64 tmp;
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);
1920 return u.u;
1923 static inline uint64_t _do_efdcfuf (uint64_t val)
1925 union {
1926 uint64_t u;
1927 float64 f;
1928 } u;
1929 float64 tmp;
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);
1935 return u.u;
1938 static inline int64_t _do_efdctsf (uint64_t val)
1940 union {
1941 int64_t u;
1942 float64 f;
1943 } u;
1944 float64 tmp;
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);
1953 return float64_to_int32(u.f, &env->spe_status);
1956 static inline uint64_t _do_efdctuf (uint64_t val)
1958 union {
1959 int64_t u;
1960 float64 f;
1961 } u;
1962 float64 tmp;
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);
1971 return float64_to_uint32(u.f, &env->spe_status);
1974 static inline int64_t _do_efdctsfz (uint64_t val)
1976 union {
1977 int64_t u;
1978 float64 f;
1979 } u;
1980 float64 tmp;
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);
1989 return float64_to_int32_round_to_zero(u.f, &env->spe_status);
1992 static inline uint64_t _do_efdctufz (uint64_t val)
1994 union {
1995 int64_t u;
1996 float64 f;
1997 } u;
1998 float64 tmp;
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);
2007 return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
2010 void do_efdcfsf (void)
2012 T0_64 = _do_efdcfsf(T0_64);
2015 void do_efdcfuf (void)
2017 T0_64 = _do_efdcfuf(T0_64);
2020 void do_efdctsf (void)
2022 T0_64 = _do_efdctsf(T0_64);
2025 void do_efdctuf (void)
2027 T0_64 = _do_efdctuf(T0_64);
2030 void do_efdctsfz (void)
2032 T0_64 = _do_efdctsfz(T0_64);
2035 void do_efdctufz (void)
2037 T0_64 = _do_efdctufz(T0_64);
2040 /* Floating point conversion between single and double precision */
2041 static inline uint32_t _do_efscfd (uint64_t val)
2043 union {
2044 uint64_t u;
2045 float64 f;
2046 } u1;
2047 union {
2048 uint32_t u;
2049 float32 f;
2050 } u2;
2052 u1.u = val;
2053 u2.f = float64_to_float32(u1.f, &env->spe_status);
2055 return u2.u;
2058 static inline uint64_t _do_efdcfs (uint32_t val)
2060 union {
2061 uint64_t u;
2062 float64 f;
2063 } u2;
2064 union {
2065 uint32_t u;
2066 float32 f;
2067 } u1;
2069 u1.u = val;
2070 u2.f = float32_to_float64(u1.f, &env->spe_status);
2072 return u2.u;
2075 void do_efscfd (void)
2077 T0_64 = _do_efscfd(T0_64);
2080 void do_efdcfs (void)
2082 T0_64 = _do_efdcfs(T0_64);
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);
2101 /* Single-precision floating-point comparisons */
2102 static inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2104 /* XXX: TODO: test special values (NaN, infinites, ...) */
2105 return _do_efststlt(op1, op2);
2108 static inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2110 /* XXX: TODO: test special values (NaN, infinites, ...) */
2111 return _do_efststgt(op1, op2);
2114 static inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2116 /* XXX: TODO: test special values (NaN, infinites, ...) */
2117 return _do_efststeq(op1, op2);
2120 void do_efscmplt (void)
2122 T0 = _do_efscmplt(T0_64, T1_64);
2125 void do_efscmpgt (void)
2127 T0 = _do_efscmpgt(T0_64, T1_64);
2130 void do_efscmpeq (void)
2132 T0 = _do_efscmpeq(T0_64, T1_64);
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);
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) */
2172 /*****************************************************************************/
2173 /* Softmmu support */
2174 #if !defined (CONFIG_USER_ONLY)
2176 #define MMUSUFFIX _mmu
2177 #define GETPC() (__builtin_return_address(0))
2179 #define SHIFT 0
2180 #include "softmmu_template.h"
2182 #define SHIFT 1
2183 #include "softmmu_template.h"
2185 #define SHIFT 2
2186 #include "softmmu_template.h"
2188 #define SHIFT 3
2189 #include "softmmu_template.h"
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)
2197 TranslationBlock *tb;
2198 CPUState *saved_env;
2199 target_phys_addr_t pc;
2200 int ret;
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);
2218 do_raise_exception_err(env->exception_index, env->error_code);
2220 env = saved_env;
2223 /* TLB invalidation helpers */
2224 void do_tlbia (void)
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);
2238 void do_tlbie (void)
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
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));
2276 #else
2277 do_tlbia();
2278 #endif
2281 #if defined(TARGET_PPC64)
2282 void do_tlbie_64 (void)
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
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
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
2326 #else
2327 do_tlbia();
2328 #endif
2330 #endif
2332 #if defined(TARGET_PPC64)
2333 void do_slbia (void)
2335 /* XXX: TODO */
2336 tlb_flush(env, 1);
2339 void do_slbie (void)
2341 /* XXX: TODO */
2342 tlb_flush(env, 1);
2344 #endif
2346 /* Software driven TLBs management */
2347 /* PowerPC 602/603 software TLB load instructions helpers */
2348 void do_load_6xx_tlb (int is_code)
2350 target_ulong RPN, CMP, EPN;
2351 int way;
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];
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);
2368 #endif
2369 /* Store this TLB */
2370 ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2371 way, is_code, CMP, RPN);
2374 static target_ulong booke_tlb_to_page_size (int size)
2376 return 1024 << (2 * size);
2379 static int booke_page_size_to_tlb (target_ulong page_size)
2381 int size;
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;
2439 return size;
2442 /* Helpers for 4xx TLB management */
2443 void do_4xx_tlbia (void)
2445 ppcemb_tlb_t *tlb;
2446 int i;
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;
2459 tlb_flush(env, 1);
2462 void do_4xx_tlbre_lo (void)
2464 ppcemb_tlb_t *tlb;
2465 int size;
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;
2479 void do_4xx_tlbre_hi (void)
2481 ppcemb_tlb_t *tlb;
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;
2492 static int tlb_4xx_search (target_ulong virtual)
2494 ppcemb_tlb_t *tlb;
2495 target_ulong base, mask;
2496 int i, ret;
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;
2517 return ret;
2520 void do_4xx_tlbsx (void)
2522 T0 = tlb_4xx_search(T0);
2525 void do_4xx_tlbsx_ (void)
2527 int tmp = xer_ov;
2529 T0 = tlb_4xx_search(T0);
2530 if (T0 != -1)
2531 tmp |= 0x02;
2532 env->crf[0] = tmp;
2535 void do_4xx_tlbwe_lo (void)
2537 ppcemb_tlb_t *tlb;
2538 target_ulong page, end;
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);
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);
2564 void do_4xx_tlbwe_hi (void)
2566 ppcemb_tlb_t *tlb;
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;
2577 #endif /* !CONFIG_USER_ONLY */