Commit fdabc366bd922d3029b42864ecf268103d8ca8e6
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
Showing
5 changed files
with
455 additions
and
363 deletions
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 |