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,6 +32,15 @@
32 32
33 #define TARGET_HAS_ICE 1 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 /* PVR definitions for most known PowerPC */ 45 /* PVR definitions for most known PowerPC */
37 enum { 46 enum {
target-ppc/exec.h
@@ -20,8 +20,12 @@ @@ -20,8 +20,12 @@
20 #if !defined (__PPC_H__) 20 #if !defined (__PPC_H__)
21 #define __PPC_H__ 21 #define __PPC_H__
22 22
  23 +#include "config.h"
  24 +
23 #include "dyngen-exec.h" 25 #include "dyngen-exec.h"
24 26
  27 +#define TARGET_LONG_BITS 32
  28 +
25 register struct CPUPPCState *env asm(AREG0); 29 register struct CPUPPCState *env asm(AREG0);
26 register uint32_t T0 asm(AREG1); 30 register uint32_t T0 asm(AREG1);
27 register uint32_t T1 asm(AREG2); 31 register uint32_t T1 asm(AREG2);
target-ppc/helper.c
@@ -17,11 +17,21 @@ @@ -17,11 +17,21 @@
17 * License along with this library; if not, write to the Free Software 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 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 //#define DEBUG_MMU 31 //#define DEBUG_MMU
23 //#define DEBUG_BATS 32 //#define DEBUG_BATS
24 //#define DEBUG_EXCEPTIONS 33 //#define DEBUG_EXCEPTIONS
  34 +//#define FLUSH_ALL_TLBS
25 35
26 /*****************************************************************************/ 36 /*****************************************************************************/
27 /* PowerPC MMU emulation */ 37 /* PowerPC MMU emulation */
@@ -394,92 +404,6 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -394,92 +404,6 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
394 } 404 }
395 #endif 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 /* Perform address translation */ 407 /* Perform address translation */
484 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, 408 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
485 int is_user, int is_softmmu) 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,13 +500,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
576 error_code = EXCP_INVAL | EXCP_INVAL_INVAL; 500 error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
577 break; 501 break;
578 } 502 }
  503 + break;
579 case -5: 504 case -5:
580 /* No match in segment table */ 505 /* No match in segment table */
581 exception = EXCP_DSEG; 506 exception = EXCP_DSEG;
582 error_code = 0; 507 error_code = 0;
583 break; 508 break;
584 } 509 }
585 - if (rw) 510 + if (exception == EXCP_DSI && rw == 1)
586 error_code |= 0x02000000; 511 error_code |= 0x02000000;
587 /* Store fault address */ 512 /* Store fault address */
588 env->spr[SPR_DAR] = address; 513 env->spr[SPR_DAR] = address;
@@ -1491,6 +1416,7 @@ void do_interrupt (CPUState *env) @@ -1491,6 +1416,7 @@ void do_interrupt (CPUState *env)
1491 /* Jump to handler */ 1416 /* Jump to handler */
1492 env->nip = excp; 1417 env->nip = excp;
1493 env->exception_index = EXCP_NONE; 1418 env->exception_index = EXCP_NONE;
  1419 +#if 0
1494 /* ensure that no TB jump will be modified as 1420 /* ensure that no TB jump will be modified as
1495 the program flow was changed */ 1421 the program flow was changed */
1496 #ifdef __sparc__ 1422 #ifdef __sparc__
@@ -1498,6 +1424,7 @@ void do_interrupt (CPUState *env) @@ -1498,6 +1424,7 @@ void do_interrupt (CPUState *env)
1498 #else 1424 #else
1499 T0 = 0; 1425 T0 = 0;
1500 #endif 1426 #endif
  1427 +#endif
1501 env->interrupt_request |= CPU_INTERRUPT_EXITTB; 1428 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1502 } 1429 }
1503 #endif /* !CONFIG_USER_ONLY */ 1430 #endif /* !CONFIG_USER_ONLY */
target-ppc/op.c
@@ -548,16 +548,10 @@ PPC_OP(add) @@ -548,16 +548,10 @@ PPC_OP(add)
548 RETURN(); 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 RETURN(); 555 RETURN();
562 } 556 }
563 557
@@ -574,53 +568,24 @@ PPC_OP(addc) @@ -574,53 +568,24 @@ PPC_OP(addc)
574 RETURN(); 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 RETURN(); 575 RETURN();
593 } 576 }
594 577
595 /* add extended */ 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 PPC_OP(addeo) 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 RETURN(); 589 RETURN();
625 } 590 }
626 591
@@ -654,18 +619,10 @@ PPC_OP(addme) @@ -654,18 +619,10 @@ PPC_OP(addme)
654 RETURN(); 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 RETURN(); 626 RETURN();
670 } 627 }
671 628
@@ -682,26 +639,14 @@ PPC_OP(addze) @@ -682,26 +639,14 @@ PPC_OP(addze)
682 RETURN(); 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 RETURN(); 646 RETURN();
701 } 647 }
702 648
703 /* divide word */ 649 /* divide word */
704 -/* candidate for helper (too long) */  
705 PPC_OP(divw) 650 PPC_OP(divw)
706 { 651 {
707 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) { 652 if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
@@ -712,16 +657,10 @@ PPC_OP(divw) @@ -712,16 +657,10 @@ PPC_OP(divw)
712 RETURN(); 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 RETURN(); 664 RETURN();
726 } 665 }
727 666
@@ -736,16 +675,10 @@ PPC_OP(divwu) @@ -736,16 +675,10 @@ PPC_OP(divwu)
736 RETURN(); 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 RETURN(); 682 RETURN();
750 } 683 }
751 684
@@ -777,17 +710,10 @@ PPC_OP(mullw) @@ -777,17 +710,10 @@ PPC_OP(mullw)
777 RETURN(); 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 RETURN(); 717 RETURN();
792 } 718 }
793 719
@@ -800,15 +726,10 @@ PPC_OP(neg) @@ -800,15 +726,10 @@ PPC_OP(neg)
800 RETURN(); 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 RETURN(); 733 RETURN();
813 } 734 }
814 735
@@ -819,16 +740,10 @@ PPC_OP(subf) @@ -819,16 +740,10 @@ PPC_OP(subf)
819 RETURN(); 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 RETURN(); 747 RETURN();
833 } 748 }
834 749
@@ -844,52 +759,25 @@ PPC_OP(subfc) @@ -844,52 +759,25 @@ PPC_OP(subfc)
844 RETURN(); 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 RETURN(); 766 RETURN();
863 } 767 }
864 768
865 /* substract from extended */ 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 RETURN(); 774 RETURN();
876 } 775 }
877 776
  777 +void do_subfeo (void);
878 PPC_OP(subfeo) 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 RETURN(); 781 RETURN();
894 } 782 }
895 783
@@ -915,18 +803,10 @@ PPC_OP(subfme) @@ -915,18 +803,10 @@ PPC_OP(subfme)
915 RETURN(); 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 RETURN(); 810 RETURN();
931 } 811 }
932 812
@@ -943,21 +823,10 @@ PPC_OP(subfze) @@ -943,21 +823,10 @@ PPC_OP(subfze)
943 RETURN(); 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 RETURN(); 830 RETURN();
962 } 831 }
963 832
@@ -1174,7 +1043,7 @@ PPC_OP(slw) @@ -1174,7 +1043,7 @@ PPC_OP(slw)
1174 } 1043 }
1175 1044
1176 /* shift right algebraic word */ 1045 /* shift right algebraic word */
1177 -PPC_OP(sraw) 1046 +void op_sraw (void)
1178 { 1047 {
1179 do_sraw(); 1048 do_sraw();
1180 RETURN(); 1049 RETURN();
@@ -1227,10 +1096,9 @@ PPC_OP(fmul) @@ -1227,10 +1096,9 @@ PPC_OP(fmul)
1227 } 1096 }
1228 1097
1229 /* fdiv - fdiv. */ 1098 /* fdiv - fdiv. */
1230 -void do_fdiv (void);  
1231 PPC_OP(fdiv) 1099 PPC_OP(fdiv)
1232 { 1100 {
1233 - do_fdiv(); 1101 + FT0 = float64_div(FT0, FT1, &env->fp_status);
1234 RETURN(); 1102 RETURN();
1235 } 1103 }
1236 1104
@@ -1331,25 +1199,24 @@ PPC_OP(fcmpo) @@ -1331,25 +1199,24 @@ PPC_OP(fcmpo)
1331 1199
1332 /*** Floating-point move ***/ 1200 /*** Floating-point move ***/
1333 /* fabs */ 1201 /* fabs */
1334 -void do_fabs (void);  
1335 PPC_OP(fabs) 1202 PPC_OP(fabs)
1336 { 1203 {
1337 - do_fabs(); 1204 + FT0 = float64_abs(FT0);
1338 RETURN(); 1205 RETURN();
1339 } 1206 }
1340 1207
1341 /* fnabs */ 1208 /* fnabs */
1342 -void do_fnabs (void);  
1343 PPC_OP(fnabs) 1209 PPC_OP(fnabs)
1344 { 1210 {
1345 - do_fnabs(); 1211 + FT0 = float64_abs(FT0);
  1212 + FT0 = float64_chs(FT0);
1346 RETURN(); 1213 RETURN();
1347 } 1214 }
1348 1215
1349 /* fneg */ 1216 /* fneg */
1350 PPC_OP(fneg) 1217 PPC_OP(fneg)
1351 { 1218 {
1352 - FT0 = -FT0; 1219 + FT0 = float64_chs(FT0);
1353 RETURN(); 1220 RETURN();
1354 } 1221 }
1355 1222
@@ -1367,40 +1234,30 @@ PPC_OP(fneg) @@ -1367,40 +1234,30 @@ PPC_OP(fneg)
1367 /* Special op to check and maybe clear reservation */ 1234 /* Special op to check and maybe clear reservation */
1368 PPC_OP(check_reservation) 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 RETURN(); 1239 RETURN();
1372 } 1240 }
1373 1241
1374 /* Return from interrupt */ 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 RETURN(); 1247 RETURN();
1382 } 1248 }
1383 1249
1384 /* Trap word */ 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 RETURN(); 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 RETURN(); 1261 RETURN();
1405 } 1262 }
1406 1263
target-ppc/op_helper.c
@@ -29,6 +29,14 @@ @@ -29,6 +29,14 @@
29 #include "op_helper_mem.h" 29 #include "op_helper_mem.h"
30 #endif 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 /* Exceptions processing helpers */ 41 /* Exceptions processing helpers */
34 void cpu_loop_exit(void) 42 void cpu_loop_exit(void)
@@ -60,29 +68,260 @@ void do_raise_exception (uint32_t exception) @@ -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 /* shift right arithmetic helper */ 296 /* shift right arithmetic helper */
65 void do_sraw (void) 297 void do_sraw (void)
66 { 298 {
67 int32_t ret; 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 xer_ca = 0; 305 xer_ca = 0;
70 - if (T1 & 0x20) {  
71 - ret = (-1) * (T0 >> 31);  
72 - if (ret < 0 && (T0 & ~0x80000000) != 0) 306 + } else {
73 xer_ca = 1; 307 xer_ca = 1;
74 -#if 1 // TRY  
75 - } else if (T1 == 0) { 308 + }
  309 + } else {
76 ret = T0; 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 } else { 317 } else {
79 - ret = (int32_t)T0 >> (T1 & 0x1f);  
80 - if (ret < 0 && ((int32_t)T0 & ((1 << T1) - 1)) != 0)  
81 xer_ca = 1; 318 xer_ca = 1;
82 } 319 }
  320 + }
83 T0 = ret; 321 T0 = ret;
84 } 322 }
85 323
  324 +/*****************************************************************************/
86 /* Floating point operations helpers */ 325 /* Floating point operations helpers */
87 void do_fctiw (void) 326 void do_fctiw (void)
88 { 327 {
@@ -116,29 +355,23 @@ void do_fctiwz (void) @@ -116,29 +355,23 @@ void do_fctiwz (void)
116 355
117 void do_fnmadd (void) 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 void do_fnmsub (void) 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 void do_fsqrt (void) 372 void do_fsqrt (void)
140 { 373 {
141 - FT0 = sqrt(FT0); 374 + FT0 = float64_sqrt(FT0, &env->fp_status);
142 } 375 }
143 376
144 void do_fres (void) 377 void do_fres (void)
@@ -148,7 +381,7 @@ void do_fres (void) @@ -148,7 +381,7 @@ void do_fres (void)
148 uint64_t i; 381 uint64_t i;
149 } p; 382 } p;
150 383
151 - if (isnormal(FT0)) { 384 + if (likely(isnormal(FT0))) {
152 FT0 = (float)(1.0 / FT0); 385 FT0 = (float)(1.0 / FT0);
153 } else { 386 } else {
154 p.d = FT0; 387 p.d = FT0;
@@ -174,8 +407,9 @@ void do_frsqrte (void) @@ -174,8 +407,9 @@ void do_frsqrte (void)
174 uint64_t i; 407 uint64_t i;
175 } p; 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 } else { 413 } else {
180 p.d = FT0; 414 p.d = FT0;
181 if (p.i == 0x8000000000000000ULL) { 415 if (p.i == 0x8000000000000000ULL) {
@@ -204,16 +438,18 @@ void do_fsel (void) @@ -204,16 +438,18 @@ void do_fsel (void)
204 438
205 void do_fcmpu (void) 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 env->fpscr[4] |= 0x1; 451 env->fpscr[4] |= 0x1;
210 env->fpscr[6] |= 0x1; 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 env->fpscr[3] = T0; 454 env->fpscr[3] = T0;
219 } 455 }
@@ -221,8 +457,16 @@ void do_fcmpu (void) @@ -221,8 +457,16 @@ void do_fcmpu (void)
221 void do_fcmpo (void) 457 void do_fcmpo (void)
222 { 458 {
223 env->fpscr[4] &= ~0x1; 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 env->fpscr[4] |= 0x1; 470 env->fpscr[4] |= 0x1;
227 /* I don't know how to test "quiet" nan... */ 471 /* I don't know how to test "quiet" nan... */
228 if (0 /* || ! quiet_nan(...) */) { 472 if (0 /* || ! quiet_nan(...) */) {
@@ -232,56 +476,51 @@ void do_fcmpo (void) @@ -232,56 +476,51 @@ void do_fcmpo (void)
232 } else { 476 } else {
233 env->fpscr[4] |= 0x8; 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 env->fpscr[3] = T0; 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 /* Instruction cache invalidation helper */ 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 void do_icbi (void) 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 T0 &= ~(ICACHE_LINE_SIZE - 1); 518 T0 &= ~(ICACHE_LINE_SIZE - 1);
282 tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE); 519 tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);
283 } 520 }
284 521
  522 +/*****************************************************************************/
  523 +/* MMU related helpers */
285 /* TLB invalidation helpers */ 524 /* TLB invalidation helpers */
286 void do_tlbia (void) 525 void do_tlbia (void)
287 { 526 {
@@ -290,6 +529,62 @@ void do_tlbia (void) @@ -290,6 +529,62 @@ void do_tlbia (void)
290 529
291 void do_tlbie (void) 530 void do_tlbie (void)
292 { 531 {
  532 +#if !defined(FLUSH_ALL_TLBS)
293 tlb_flush_page(env, T0); 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