Commit fdabc366bd922d3029b42864ecf268103d8ca8e6

Authored by bellard
1 parent 2157fa06

correct split between helper.c and op_helper.c - moved some uops to op_helper.c (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1504 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -32,6 +32,15 @@
32 32  
33 33 #define TARGET_HAS_ICE 1
34 34  
  35 +/* XXX: this should be tunable: PowerPC 601 & 64 bits PowerPC
  36 + * have different cache line sizes
  37 + */
  38 +#define ICACHE_LINE_SIZE 32
  39 +#define DCACHE_LINE_SIZE 32
  40 +
  41 +/* XXX: put this in a common place */
  42 +#define likely(x) __builtin_expect(!!(x), 1)
  43 +
35 44 /*****************************************************************************/
36 45 /* PVR definitions for most known PowerPC */
37 46 enum {
... ...
target-ppc/exec.h
... ... @@ -20,8 +20,12 @@
20 20 #if !defined (__PPC_H__)
21 21 #define __PPC_H__
22 22  
  23 +#include "config.h"
  24 +
23 25 #include "dyngen-exec.h"
24 26  
  27 +#define TARGET_LONG_BITS 32
  28 +
25 29 register struct CPUPPCState *env asm(AREG0);
26 30 register uint32_t T0 asm(AREG1);
27 31 register uint32_t T1 asm(AREG2);
... ...
target-ppc/helper.c
... ... @@ -17,11 +17,21 @@
17 17 * License along with this library; if not, write to the Free Software
18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 */
20   -#include "exec.h"
  20 +#include <stdarg.h>
  21 +#include <stdlib.h>
  22 +#include <stdio.h>
  23 +#include <string.h>
  24 +#include <inttypes.h>
  25 +#include <signal.h>
  26 +#include <assert.h>
  27 +
  28 +#include "cpu.h"
  29 +#include "exec-all.h"
21 30  
22 31 //#define DEBUG_MMU
23 32 //#define DEBUG_BATS
24 33 //#define DEBUG_EXCEPTIONS
  34 +//#define FLUSH_ALL_TLBS
25 35  
26 36 /*****************************************************************************/
27 37 /* PowerPC MMU emulation */
... ... @@ -394,92 +404,6 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
394 404 }
395 405 #endif
396 406  
397   -#if !defined(CONFIG_USER_ONLY)
398   -
399   -#define MMUSUFFIX _mmu
400   -#define GETPC() (__builtin_return_address(0))
401   -
402   -#define SHIFT 0
403   -#include "softmmu_template.h"
404   -
405   -#define SHIFT 1
406   -#include "softmmu_template.h"
407   -
408   -#define SHIFT 2
409   -#include "softmmu_template.h"
410   -
411   -#define SHIFT 3
412   -#include "softmmu_template.h"
413   -
414   -/* try to fill the TLB and return an exception if error. If retaddr is
415   - NULL, it means that the function was called in C code (i.e. not
416   - from generated code or from helper.c) */
417   -/* XXX: fix it to restore all registers */
418   -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
419   -{
420   - TranslationBlock *tb;
421   - CPUState *saved_env;
422   - unsigned long pc;
423   - int ret;
424   -
425   - /* XXX: hack to restore env in all cases, even if not called from
426   - generated code */
427   - saved_env = env;
428   - env = cpu_single_env;
429   -#if 0
430   - {
431   - unsigned long tlb_addrr, tlb_addrw;
432   - int index;
433   - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
434   - tlb_addrr = env->tlb_read[is_user][index].address;
435   - tlb_addrw = env->tlb_write[is_user][index].address;
436   - if (loglevel) {
437   - fprintf(logfile,
438   - "%s 1 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx "
439   - "(0x%08lx 0x%08lx)\n", __func__, env,
440   - &env->tlb_read[is_user][index], index, addr,
441   - tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK,
442   - tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK));
443   - }
444   - }
445   -#endif
446   - ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
447   - if (ret) {
448   - if (retaddr) {
449   - /* now we have a real cpu fault */
450   - pc = (unsigned long)retaddr;
451   - tb = tb_find_pc(pc);
452   - if (tb) {
453   - /* the PC is inside the translated code. It means that we have
454   - a virtual CPU fault */
455   - cpu_restore_state(tb, env, pc, NULL);
456   - }
457   - }
458   - do_raise_exception_err(env->exception_index, env->error_code);
459   - }
460   -#if 0
461   - {
462   - unsigned long tlb_addrr, tlb_addrw;
463   - int index;
464   - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
465   - tlb_addrr = env->tlb_read[is_user][index].address;
466   - tlb_addrw = env->tlb_write[is_user][index].address;
467   - printf("%s 2 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx "
468   - "(0x%08lx 0x%08lx)\n", __func__, env,
469   - &env->tlb_read[is_user][index], index, addr,
470   - tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK,
471   - tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK));
472   - }
473   -#endif
474   - env = saved_env;
475   -}
476   -
477   -void cpu_ppc_init_mmu(CPUState *env)
478   -{
479   - /* Nothing to do: all translation are disabled */
480   -}
481   -#endif
482   -
483 407 /* Perform address translation */
484 408 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
485 409 int is_user, int is_softmmu)
... ... @@ -576,13 +500,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
576 500 error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
577 501 break;
578 502 }
  503 + break;
579 504 case -5:
580 505 /* No match in segment table */
581 506 exception = EXCP_DSEG;
582 507 error_code = 0;
583 508 break;
584 509 }
585   - if (rw)
  510 + if (exception == EXCP_DSI && rw == 1)
586 511 error_code |= 0x02000000;
587 512 /* Store fault address */
588 513 env->spr[SPR_DAR] = address;
... ... @@ -1491,6 +1416,7 @@ void do_interrupt (CPUState *env)
1491 1416 /* Jump to handler */
1492 1417 env->nip = excp;
1493 1418 env->exception_index = EXCP_NONE;
  1419 +#if 0
1494 1420 /* ensure that no TB jump will be modified as
1495 1421 the program flow was changed */
1496 1422 #ifdef __sparc__
... ... @@ -1498,6 +1424,7 @@ void do_interrupt (CPUState *env)
1498 1424 #else
1499 1425 T0 = 0;
1500 1426 #endif
  1427 +#endif
1501 1428 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1502 1429 }
1503 1430 #endif /* !CONFIG_USER_ONLY */
... ...
target-ppc/op.c
... ... @@ -548,16 +548,10 @@ PPC_OP(add)
548 548 RETURN();
549 549 }
550 550  
551   -PPC_OP(addo)
  551 +void do_addo (void);
  552 +void op_addo (void)
552 553 {
553   - T2 = T0;
554   - T0 += T1;
555   - if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
556   - xer_so = 1;
557   - xer_ov = 1;
558   - } else {
559   - xer_ov = 0;
560   - }
  554 + do_addo();
561 555 RETURN();
562 556 }
563 557  
... ... @@ -574,53 +568,24 @@ PPC_OP(addc)
574 568 RETURN();
575 569 }
576 570  
577   -PPC_OP(addco)
  571 +void do_addco (void);
  572 +void op_addco (void)
578 573 {
579   - T2 = T0;
580   - T0 += T1;
581   - if (T0 < T2) {
582   - xer_ca = 1;
583   - } else {
584   - xer_ca = 0;
585   - }
586   - if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
587   - xer_so = 1;
588   - xer_ov = 1;
589   - } else {
590   - xer_ov = 0;
591   - }
  574 + do_addco();
592 575 RETURN();
593 576 }
594 577  
595 578 /* add extended */
596   -/* candidate for helper (too long) */
597   -PPC_OP(adde)
  579 +void do_adde (void);
  580 +void op_adde (void)
598 581 {
599   - T2 = T0;
600   - T0 += T1 + xer_ca;
601   - if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
602   - xer_ca = 1;
603   - } else {
604   - xer_ca = 0;
605   - }
606   - RETURN();
  582 + do_adde();
607 583 }
608 584  
  585 +void do_addeo (void);
609 586 PPC_OP(addeo)
610 587 {
611   - T2 = T0;
612   - T0 += T1 + xer_ca;
613   - if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
614   - xer_ca = 1;
615   - } else {
616   - xer_ca = 0;
617   - }
618   - if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
619   - xer_so = 1;
620   - xer_ov = 1;
621   - } else {
622   - xer_ov = 0;
623   - }
  588 + do_addeo();
624 589 RETURN();
625 590 }
626 591  
... ... @@ -654,18 +619,10 @@ PPC_OP(addme)
654 619 RETURN();
655 620 }
656 621  
657   -PPC_OP(addmeo)
  622 +void do_addmeo (void);
  623 +void op_addmeo (void)
658 624 {
659   - T1 = T0;
660   - T0 += xer_ca + (-1);
661   - if (T1 & (T1 ^ T0) & (1 << 31)) {
662   - xer_so = 1;
663   - xer_ov = 1;
664   - } else {
665   - xer_ov = 0;
666   - }
667   - if (T1 != 0)
668   - xer_ca = 1;
  625 + do_addmeo();
669 626 RETURN();
670 627 }
671 628  
... ... @@ -682,26 +639,14 @@ PPC_OP(addze)
682 639 RETURN();
683 640 }
684 641  
685   -PPC_OP(addzeo)
  642 +void do_addzeo (void);
  643 +void op_addzeo (void)
686 644 {
687   - T1 = T0;
688   - T0 += xer_ca;
689   - if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
690   - xer_so = 1;
691   - xer_ov = 1;
692   - } else {
693   - xer_ov = 0;
694   - }
695   - if (T0 < T1) {
696   - xer_ca = 1;
697   - } else {
698   - xer_ca = 0;
699   - }
  645 + do_addzeo();
700 646 RETURN();
701 647 }
702 648  
703 649 /* divide word */
704   -/* candidate for helper (too long) */
705 650 PPC_OP(divw)
706 651 {
707 652 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
... ... @@ -712,16 +657,10 @@ PPC_OP(divw)
712 657 RETURN();
713 658 }
714 659  
715   -PPC_OP(divwo)
  660 +void do_divwo (void);
  661 +void op_divwo (void)
716 662 {
717   - if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
718   - xer_so = 1;
719   - xer_ov = 1;
720   - T0 = (-1) * (T0 >> 31);
721   - } else {
722   - xer_ov = 0;
723   - T0 = (Ts0 / Ts1);
724   - }
  663 + do_divwo();
725 664 RETURN();
726 665 }
727 666  
... ... @@ -736,16 +675,10 @@ PPC_OP(divwu)
736 675 RETURN();
737 676 }
738 677  
739   -PPC_OP(divwuo)
  678 +void do_divwuo (void);
  679 +void op_divwuo (void)
740 680 {
741   - if (T1 == 0) {
742   - xer_so = 1;
743   - xer_ov = 1;
744   - T0 = 0;
745   - } else {
746   - xer_ov = 0;
747   - T0 /= T1;
748   - }
  681 + do_divwuo();
749 682 RETURN();
750 683 }
751 684  
... ... @@ -777,17 +710,10 @@ PPC_OP(mullw)
777 710 RETURN();
778 711 }
779 712  
780   -PPC_OP(mullwo)
  713 +void do_mullwo (void);
  714 +void op_mullwo (void)
781 715 {
782   - int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
783   -
784   - if ((int32_t)res != res) {
785   - xer_ov = 1;
786   - xer_so = 1;
787   - } else {
788   - xer_ov = 0;
789   - }
790   - T0 = (int32_t)res;
  716 + do_mullwo();
791 717 RETURN();
792 718 }
793 719  
... ... @@ -800,15 +726,10 @@ PPC_OP(neg)
800 726 RETURN();
801 727 }
802 728  
803   -PPC_OP(nego)
  729 +void do_nego (void);
  730 +void op_nego (void)
804 731 {
805   - if (T0 == 0x80000000) {
806   - xer_ov = 1;
807   - xer_so = 1;
808   - } else {
809   - xer_ov = 0;
810   - T0 = -Ts0;
811   - }
  732 + do_nego();
812 733 RETURN();
813 734 }
814 735  
... ... @@ -819,16 +740,10 @@ PPC_OP(subf)
819 740 RETURN();
820 741 }
821 742  
822   -PPC_OP(subfo)
  743 +void do_subfo (void);
  744 +void op_subfo (void)
823 745 {
824   - T2 = T0;
825   - T0 = T1 - T0;
826   - if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
827   - xer_so = 1;
828   - xer_ov = 1;
829   - } else {
830   - xer_ov = 0;
831   - }
  746 + do_subfo();
832 747 RETURN();
833 748 }
834 749  
... ... @@ -844,52 +759,25 @@ PPC_OP(subfc)
844 759 RETURN();
845 760 }
846 761  
847   -PPC_OP(subfco)
  762 +void do_subfco (void);
  763 +void op_subfco (void)
848 764 {
849   - T2 = T0;
850   - T0 = T1 - T0;
851   - if (T0 <= T1) {
852   - xer_ca = 1;
853   - } else {
854   - xer_ca = 0;
855   - }
856   - if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
857   - xer_so = 1;
858   - xer_ov = 1;
859   - } else {
860   - xer_ov = 0;
861   - }
  765 + do_subfco();
862 766 RETURN();
863 767 }
864 768  
865 769 /* substract from extended */
866   -/* candidate for helper (too long) */
867   -PPC_OP(subfe)
  770 +void do_subfe (void);
  771 +void op_subfe (void)
868 772 {
869   - T0 = T1 + ~T0 + xer_ca;
870   - if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
871   - xer_ca = 1;
872   - } else {
873   - xer_ca = 0;
874   - }
  773 + do_subfe();
875 774 RETURN();
876 775 }
877 776  
  777 +void do_subfeo (void);
878 778 PPC_OP(subfeo)
879 779 {
880   - T2 = T0;
881   - T0 = T1 + ~T0 + xer_ca;
882   - if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
883   - xer_so = 1;
884   - xer_ov = 1;
885   - } else {
886   - xer_ov = 0;
887   - }
888   - if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
889   - xer_ca = 1;
890   - } else {
891   - xer_ca = 0;
892   - }
  780 + do_subfeo();
893 781 RETURN();
894 782 }
895 783  
... ... @@ -915,18 +803,10 @@ PPC_OP(subfme)
915 803 RETURN();
916 804 }
917 805  
918   -PPC_OP(subfmeo)
  806 +void do_subfmeo (void);
  807 +void op_subfmeo (void)
919 808 {
920   - T1 = T0;
921   - T0 = ~T0 + xer_ca - 1;
922   - if (~T1 & (~T1 ^ T0) & (1 << 31)) {
923   - xer_so = 1;
924   - xer_ov = 1;
925   - } else {
926   - xer_ov = 0;
927   - }
928   - if (T1 != -1)
929   - xer_ca = 1;
  809 + do_subfmeo();
930 810 RETURN();
931 811 }
932 812  
... ... @@ -943,21 +823,10 @@ PPC_OP(subfze)
943 823 RETURN();
944 824 }
945 825  
946   -PPC_OP(subfzeo)
  826 +void do_subfzeo (void);
  827 +void op_subfzeo (void)
947 828 {
948   - T1 = T0;
949   - T0 = ~T0 + xer_ca;
950   - if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
951   - xer_ov = 1;
952   - xer_so = 1;
953   - } else {
954   - xer_ov = 0;
955   - }
956   - if (T0 < ~T1) {
957   - xer_ca = 1;
958   - } else {
959   - xer_ca = 0;
960   - }
  829 + do_subfzeo();
961 830 RETURN();
962 831 }
963 832  
... ... @@ -1174,7 +1043,7 @@ PPC_OP(slw)
1174 1043 }
1175 1044  
1176 1045 /* shift right algebraic word */
1177   -PPC_OP(sraw)
  1046 +void op_sraw (void)
1178 1047 {
1179 1048 do_sraw();
1180 1049 RETURN();
... ... @@ -1227,10 +1096,9 @@ PPC_OP(fmul)
1227 1096 }
1228 1097  
1229 1098 /* fdiv - fdiv. */
1230   -void do_fdiv (void);
1231 1099 PPC_OP(fdiv)
1232 1100 {
1233   - do_fdiv();
  1101 + FT0 = float64_div(FT0, FT1, &env->fp_status);
1234 1102 RETURN();
1235 1103 }
1236 1104  
... ... @@ -1331,25 +1199,24 @@ PPC_OP(fcmpo)
1331 1199  
1332 1200 /*** Floating-point move ***/
1333 1201 /* fabs */
1334   -void do_fabs (void);
1335 1202 PPC_OP(fabs)
1336 1203 {
1337   - do_fabs();
  1204 + FT0 = float64_abs(FT0);
1338 1205 RETURN();
1339 1206 }
1340 1207  
1341 1208 /* fnabs */
1342   -void do_fnabs (void);
1343 1209 PPC_OP(fnabs)
1344 1210 {
1345   - do_fnabs();
  1211 + FT0 = float64_abs(FT0);
  1212 + FT0 = float64_chs(FT0);
1346 1213 RETURN();
1347 1214 }
1348 1215  
1349 1216 /* fneg */
1350 1217 PPC_OP(fneg)
1351 1218 {
1352   - FT0 = -FT0;
  1219 + FT0 = float64_chs(FT0);
1353 1220 RETURN();
1354 1221 }
1355 1222  
... ... @@ -1367,40 +1234,30 @@ PPC_OP(fneg)
1367 1234 /* Special op to check and maybe clear reservation */
1368 1235 PPC_OP(check_reservation)
1369 1236 {
1370   - do_check_reservation();
  1237 + if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
  1238 + env->reserve = -1;
1371 1239 RETURN();
1372 1240 }
1373 1241  
1374 1242 /* Return from interrupt */
1375   -PPC_OP(rfi)
  1243 +void do_rfi (void);
  1244 +void op_rfi (void)
1376 1245 {
1377   - env->nip = env->spr[SPR_SRR0] & ~0x00000003;
1378   - T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
1379   - do_store_msr(env, T0);
1380   - env->interrupt_request |= CPU_INTERRUPT_EXITTB;
  1246 + do_rfi();
1381 1247 RETURN();
1382 1248 }
1383 1249  
1384 1250 /* Trap word */
1385   -PPC_OP(tw)
  1251 +void do_tw (uint32_t cmp, int flags);
  1252 +void op_tw (void)
1386 1253 {
1387   - if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
1388   - (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
1389   - (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1390   - (T0 < T1 && (PARAM(1) & 0x02)) ||
1391   - (T0 > T1 && (PARAM(1) & 0x01)))
1392   - do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
  1254 + do_tw(T1, PARAM(1));
1393 1255 RETURN();
1394 1256 }
1395 1257  
1396   -PPC_OP(twi)
  1258 +void op_twi (void)
1397 1259 {
1398   - if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
1399   - (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
1400   - (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1401   - (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1402   - (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1403   - do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
  1260 + do_tw(PARAM(1), PARAM(2));
1404 1261 RETURN();
1405 1262 }
1406 1263  
... ...
target-ppc/op_helper.c
... ... @@ -29,6 +29,14 @@
29 29 #include "op_helper_mem.h"
30 30 #endif
31 31  
  32 +//#define DEBUG_OP
  33 +//#define DEBUG_EXCEPTIONS
  34 +//#define FLUSH_ALL_TLBS
  35 +
  36 +#define Ts0 (long)((target_long)T0)
  37 +#define Ts1 (long)((target_long)T1)
  38 +#define Ts2 (long)((target_long)T2)
  39 +
32 40 /*****************************************************************************/
33 41 /* Exceptions processing helpers */
34 42 void cpu_loop_exit(void)
... ... @@ -60,29 +68,260 @@ void do_raise_exception (uint32_t exception)
60 68 }
61 69  
62 70 /*****************************************************************************/
63   -/* Helpers for "fat" micro operations */
  71 +/* Fixed point operations helpers */
  72 +void do_addo (void)
  73 +{
  74 + T2 = T0;
  75 + T0 += T1;
  76 + if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
  77 + xer_ov = 0;
  78 + } else {
  79 + xer_so = 1;
  80 + xer_ov = 1;
  81 + }
  82 +}
  83 +
  84 +void do_addco (void)
  85 +{
  86 + T2 = T0;
  87 + T0 += T1;
  88 + if (likely(T0 >= T2)) {
  89 + xer_ca = 0;
  90 + } else {
  91 + xer_ca = 1;
  92 + }
  93 + if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
  94 + xer_ov = 0;
  95 + } else {
  96 + xer_so = 1;
  97 + xer_ov = 1;
  98 + }
  99 +}
  100 +
  101 +void do_adde (void)
  102 +{
  103 + T2 = T0;
  104 + T0 += T1 + xer_ca;
  105 + if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
  106 + xer_ca = 0;
  107 + } else {
  108 + xer_ca = 1;
  109 + }
  110 +}
  111 +
  112 +void do_addeo (void)
  113 +{
  114 + T2 = T0;
  115 + T0 += T1 + xer_ca;
  116 + if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
  117 + xer_ca = 0;
  118 + } else {
  119 + xer_ca = 1;
  120 + }
  121 + if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
  122 + xer_ov = 0;
  123 + } else {
  124 + xer_so = 1;
  125 + xer_ov = 1;
  126 + }
  127 +}
  128 +
  129 +void do_addmeo (void)
  130 +{
  131 + T1 = T0;
  132 + T0 += xer_ca + (-1);
  133 + if (likely(!(T1 & (T1 ^ T0) & (1 << 31)))) {
  134 + xer_ov = 0;
  135 + } else {
  136 + xer_so = 1;
  137 + xer_ov = 1;
  138 + }
  139 + if (likely(T1 != 0))
  140 + xer_ca = 1;
  141 +}
  142 +
  143 +void do_addzeo (void)
  144 +{
  145 + T1 = T0;
  146 + T0 += xer_ca;
  147 + if (likely(!((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)))) {
  148 + xer_ov = 0;
  149 + } else {
  150 + xer_so = 1;
  151 + xer_ov = 1;
  152 + }
  153 + if (likely(T0 >= T1)) {
  154 + xer_ca = 0;
  155 + } else {
  156 + xer_ca = 1;
  157 + }
  158 +}
  159 +
  160 +void do_divwo (void)
  161 +{
  162 + if (likely(!((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0))) {
  163 + xer_ov = 0;
  164 + T0 = (Ts0 / Ts1);
  165 + } else {
  166 + xer_so = 1;
  167 + xer_ov = 1;
  168 + T0 = (-1) * ((uint32_t)T0 >> 31);
  169 + }
  170 +}
  171 +
  172 +void do_divwuo (void)
  173 +{
  174 + if (likely((uint32_t)T1 != 0)) {
  175 + xer_ov = 0;
  176 + T0 = (uint32_t)T0 / (uint32_t)T1;
  177 + } else {
  178 + xer_so = 1;
  179 + xer_ov = 1;
  180 + T0 = 0;
  181 + }
  182 +}
  183 +
  184 +void do_mullwo (void)
  185 +{
  186 + int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
  187 +
  188 + if (likely((int32_t)res == res)) {
  189 + xer_ov = 0;
  190 + } else {
  191 + xer_ov = 1;
  192 + xer_so = 1;
  193 + }
  194 + T0 = (int32_t)res;
  195 +}
  196 +
  197 +void do_nego (void)
  198 +{
  199 + if (likely(T0 != INT32_MIN)) {
  200 + xer_ov = 0;
  201 + T0 = -Ts0;
  202 + } else {
  203 + xer_ov = 1;
  204 + xer_so = 1;
  205 + }
  206 +}
  207 +
  208 +void do_subfo (void)
  209 +{
  210 + T2 = T0;
  211 + T0 = T1 - T0;
  212 + if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
  213 + xer_ov = 0;
  214 + } else {
  215 + xer_so = 1;
  216 + xer_ov = 1;
  217 + }
  218 + RETURN();
  219 +}
  220 +
  221 +void do_subfco (void)
  222 +{
  223 + T2 = T0;
  224 + T0 = T1 - T0;
  225 + if (likely(T0 > T1)) {
  226 + xer_ca = 0;
  227 + } else {
  228 + xer_ca = 1;
  229 + }
  230 + if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
  231 + xer_ov = 0;
  232 + } else {
  233 + xer_so = 1;
  234 + xer_ov = 1;
  235 + }
  236 +}
  237 +
  238 +void do_subfe (void)
  239 +{
  240 + T0 = T1 + ~T0 + xer_ca;
  241 + if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
  242 + xer_ca = 0;
  243 + } else {
  244 + xer_ca = 1;
  245 + }
  246 +}
  247 +
  248 +void do_subfeo (void)
  249 +{
  250 + T2 = T0;
  251 + T0 = T1 + ~T0 + xer_ca;
  252 + if (likely(!((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)))) {
  253 + xer_ov = 0;
  254 + } else {
  255 + xer_so = 1;
  256 + xer_ov = 1;
  257 + }
  258 + if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
  259 + xer_ca = 0;
  260 + } else {
  261 + xer_ca = 1;
  262 + }
  263 +}
  264 +
  265 +void do_subfmeo (void)
  266 +{
  267 + T1 = T0;
  268 + T0 = ~T0 + xer_ca - 1;
  269 + if (likely(!(~T1 & (~T1 ^ T0) & (1 << 31)))) {
  270 + xer_ov = 0;
  271 + } else {
  272 + xer_so = 1;
  273 + xer_ov = 1;
  274 + }
  275 + if (likely(T1 != -1))
  276 + xer_ca = 1;
  277 +}
  278 +
  279 +void do_subfzeo (void)
  280 +{
  281 + T1 = T0;
  282 + T0 = ~T0 + xer_ca;
  283 + if (likely(!((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)))) {
  284 + xer_ov = 0;
  285 + } else {
  286 + xer_ov = 1;
  287 + xer_so = 1;
  288 + }
  289 + if (likely(T0 >= ~T1)) {
  290 + xer_ca = 0;
  291 + } else {
  292 + xer_ca = 1;
  293 + }
  294 +}
  295 +
64 296 /* shift right arithmetic helper */
65 297 void do_sraw (void)
66 298 {
67 299 int32_t ret;
68 300  
  301 + if (likely(!(T1 & 0x20UL))) {
  302 + if (likely(T1 != 0)) {
  303 + ret = (int32_t)T0 >> (T1 & 0x1fUL);
  304 + if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
69 305 xer_ca = 0;
70   - if (T1 & 0x20) {
71   - ret = (-1) * (T0 >> 31);
72   - if (ret < 0 && (T0 & ~0x80000000) != 0)
  306 + } else {
73 307 xer_ca = 1;
74   -#if 1 // TRY
75   - } else if (T1 == 0) {
  308 + }
  309 + } else {
76 310 ret = T0;
77   -#endif
  311 + xer_ca = 0;
  312 + }
  313 + } else {
  314 + ret = (-1) * ((uint32_t)T0 >> 31);
  315 + if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
  316 + xer_ca = 0;
78 317 } else {
79   - ret = (int32_t)T0 >> (T1 & 0x1f);
80   - if (ret < 0 && ((int32_t)T0 & ((1 << T1) - 1)) != 0)
81 318 xer_ca = 1;
82 319 }
  320 + }
83 321 T0 = ret;
84 322 }
85 323  
  324 +/*****************************************************************************/
86 325 /* Floating point operations helpers */
87 326 void do_fctiw (void)
88 327 {
... ... @@ -116,29 +355,23 @@ void do_fctiwz (void)
116 355  
117 356 void do_fnmadd (void)
118 357 {
119   - FT0 = (FT0 * FT1) + FT2;
120   - if (!isnan(FT0))
121   - FT0 = -FT0;
  358 + FT0 = float64_mul(FT0, FT1, &env->fp_status);
  359 + FT0 = float64_add(FT0, FT2, &env->fp_status);
  360 + if (likely(!isnan(FT0)))
  361 + FT0 = float64_chs(FT0);
122 362 }
123 363  
124 364 void do_fnmsub (void)
125 365 {
126   - FT0 = (FT0 * FT1) - FT2;
127   - if (!isnan(FT0))
128   - FT0 = -FT0;
129   -}
130   -
131   -void do_fdiv (void)
132   -{
133   - if (FT0 == -0.0 && FT1 == -0.0)
134   - FT0 = 0.0 / 0.0;
135   - else
136   - FT0 /= FT1;
  366 + FT0 = float64_mul(FT0, FT1, &env->fp_status);
  367 + FT0 = float64_sub(FT0, FT2, &env->fp_status);
  368 + if (likely(!isnan(FT0)))
  369 + FT0 = float64_chs(FT0);
137 370 }
138 371  
139 372 void do_fsqrt (void)
140 373 {
141   - FT0 = sqrt(FT0);
  374 + FT0 = float64_sqrt(FT0, &env->fp_status);
142 375 }
143 376  
144 377 void do_fres (void)
... ... @@ -148,7 +381,7 @@ void do_fres (void)
148 381 uint64_t i;
149 382 } p;
150 383  
151   - if (isnormal(FT0)) {
  384 + if (likely(isnormal(FT0))) {
152 385 FT0 = (float)(1.0 / FT0);
153 386 } else {
154 387 p.d = FT0;
... ... @@ -174,8 +407,9 @@ void do_frsqrte (void)
174 407 uint64_t i;
175 408 } p;
176 409  
177   - if (isnormal(FT0) && FT0 > 0.0) {
178   - FT0 = (float)(1.0 / sqrt(FT0));
  410 + if (likely(isnormal(FT0) && FT0 > 0.0)) {
  411 + FT0 = float64_sqrt(FT0, &env->fp_status);
  412 + FT0 = float32_div(1.0, FT0, &env->fp_status);
179 413 } else {
180 414 p.d = FT0;
181 415 if (p.i == 0x8000000000000000ULL) {
... ... @@ -204,16 +438,18 @@ void do_fsel (void)
204 438  
205 439 void do_fcmpu (void)
206 440 {
207   - if (isnan(FT0) || isnan(FT1)) {
208   - T0 = 0x01;
  441 + if (likely(!isnan(FT0) && !isnan(FT1))) {
  442 + if (float64_lt(FT0, FT1, &env->fp_status)) {
  443 + T0 = 0x08UL;
  444 + } else if (!float64_le(FT0, FT1, &env->fp_status)) {
  445 + T0 = 0x04UL;
  446 + } else {
  447 + T0 = 0x02UL;
  448 + }
  449 + } else {
  450 + T0 = 0x01UL;
209 451 env->fpscr[4] |= 0x1;
210 452 env->fpscr[6] |= 0x1;
211   - } else if (FT0 < FT1) {
212   - T0 = 0x08;
213   - } else if (FT0 > FT1) {
214   - T0 = 0x04;
215   - } else {
216   - T0 = 0x02;
217 453 }
218 454 env->fpscr[3] = T0;
219 455 }
... ... @@ -221,8 +457,16 @@ void do_fcmpu (void)
221 457 void do_fcmpo (void)
222 458 {
223 459 env->fpscr[4] &= ~0x1;
224   - if (isnan(FT0) || isnan(FT1)) {
225   - T0 = 0x01;
  460 + if (likely(!isnan(FT0) && !isnan(FT1))) {
  461 + if (float64_lt(FT0, FT1, &env->fp_status)) {
  462 + T0 = 0x08UL;
  463 + } else if (!float64_le(FT0, FT1, &env->fp_status)) {
  464 + T0 = 0x04UL;
  465 + } else {
  466 + T0 = 0x02UL;
  467 + }
  468 + } else {
  469 + T0 = 0x01UL;
226 470 env->fpscr[4] |= 0x1;
227 471 /* I don't know how to test "quiet" nan... */
228 472 if (0 /* || ! quiet_nan(...) */) {
... ... @@ -232,56 +476,51 @@ void do_fcmpo (void)
232 476 } else {
233 477 env->fpscr[4] |= 0x8;
234 478 }
235   - } else if (FT0 < FT1) {
236   - T0 = 0x08;
237   - } else if (FT0 > FT1) {
238   - T0 = 0x04;
239   - } else {
240   - T0 = 0x02;
241 479 }
242 480 env->fpscr[3] = T0;
243 481 }
244 482  
245   -void do_fabs (void)
  483 +void do_rfi (void)
246 484 {
247   - union {
248   - double d;
249   - uint64_t i;
250   - } p;
251   -
252   - p.d = FT0;
253   - p.i &= ~0x8000000000000000ULL;
254   - FT0 = p.d;
  485 + env->nip = env->spr[SPR_SRR0] & ~0x00000003;
  486 + T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
  487 + do_store_msr(env, T0);
  488 +#if defined (DEBUG_OP)
  489 + dump_rfi();
  490 +#endif
  491 + env->interrupt_request |= CPU_INTERRUPT_EXITTB;
255 492 }
256 493  
257   -void do_fnabs (void)
  494 +void do_tw (uint32_t cmp, int flags)
258 495 {
259   - union {
260   - double d;
261   - uint64_t i;
262   - } p;
263   -
264   - p.d = FT0;
265   - p.i |= 0x8000000000000000ULL;
266   - FT0 = p.d;
  496 + if (!likely(!((Ts0 < (int32_t)cmp && (flags & 0x10)) ||
  497 + (Ts0 > (int32_t)cmp && (flags & 0x08)) ||
  498 + (Ts0 == (int32_t)cmp && (flags & 0x04)) ||
  499 + (T0 < cmp && (flags & 0x02)) ||
  500 + (T0 > cmp && (flags & 0x01)))))
  501 + do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
267 502 }
268 503  
269 504 /* Instruction cache invalidation helper */
270   -#define ICACHE_LINE_SIZE 32
271   -
272   -void do_check_reservation (void)
273   -{
274   - if ((env->reserve & ~0x03) == T0)
275   - env->reserve = -1;
276   -}
277   -
278 505 void do_icbi (void)
279 506 {
280   - /* Invalidate one cache line */
  507 + uint32_t tmp;
  508 + /* Invalidate one cache line :
  509 + * PowerPC specification says this is to be treated like a load
  510 + * (not a fetch) by the MMU. To be sure it will be so,
  511 + * do the load "by hand".
  512 + */
  513 +#if defined(TARGET_PPC64)
  514 + if (!msr_sf)
  515 + T0 &= 0xFFFFFFFFULL;
  516 +#endif
  517 + tmp = ldl_kernel(T0);
281 518 T0 &= ~(ICACHE_LINE_SIZE - 1);
282 519 tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);
283 520 }
284 521  
  522 +/*****************************************************************************/
  523 +/* MMU related helpers */
285 524 /* TLB invalidation helpers */
286 525 void do_tlbia (void)
287 526 {
... ... @@ -290,6 +529,62 @@ void do_tlbia (void)
290 529  
291 530 void do_tlbie (void)
292 531 {
  532 +#if !defined(FLUSH_ALL_TLBS)
293 533 tlb_flush_page(env, T0);
  534 +#else
  535 + do_tlbia();
  536 +#endif
  537 +}
  538 +
  539 +/*****************************************************************************/
  540 +/* Softmmu support */
  541 +#if !defined (CONFIG_USER_ONLY)
  542 +
  543 +#define MMUSUFFIX _mmu
  544 +#define GETPC() (__builtin_return_address(0))
  545 +
  546 +#define SHIFT 0
  547 +#include "softmmu_template.h"
  548 +
  549 +#define SHIFT 1
  550 +#include "softmmu_template.h"
  551 +
  552 +#define SHIFT 2
  553 +#include "softmmu_template.h"
  554 +
  555 +#define SHIFT 3
  556 +#include "softmmu_template.h"
  557 +
  558 +/* try to fill the TLB and return an exception if error. If retaddr is
  559 + NULL, it means that the function was called in C code (i.e. not
  560 + from generated code or from helper.c) */
  561 +/* XXX: fix it to restore all registers */
  562 +void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
  563 +{
  564 + TranslationBlock *tb;
  565 + CPUState *saved_env;
  566 + target_phys_addr_t pc;
  567 + int ret;
  568 +
  569 + /* XXX: hack to restore env in all cases, even if not called from
  570 + generated code */
  571 + saved_env = env;
  572 + env = cpu_single_env;
  573 + ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
  574 + if (!likely(ret == 0)) {
  575 + if (likely(retaddr)) {
  576 + /* now we have a real cpu fault */
  577 + pc = (target_phys_addr_t)retaddr;
  578 + tb = tb_find_pc(pc);
  579 + if (likely(tb)) {
  580 + /* the PC is inside the translated code. It means that we have
  581 + a virtual CPU fault */
  582 + cpu_restore_state(tb, env, pc, NULL);
  583 +}
  584 + }
  585 + do_raise_exception_err(env->exception_index, env->error_code);
  586 + }
  587 + env = saved_env;
294 588 }
  589 +#endif /* !CONFIG_USER_ONLY */
295 590  
... ...