-
+ C5AFA1184E847BA45411669A68D1CC0F62A2BACB17155541F525A70D4EDEFD9A62789675F30C1EB79621D8737674FE39BA7A5D913D30FE18E8B785F3CF48276D
m/mipsinst/m_instrs.asm
(0 . 0)(1 . 557)
3482 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3483 ;; ;;
3484 ;; This file is part of 'M', a MIPS system emulator. ;;
3485 ;; ;;
3486 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
3487 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
3488 ;; ;;
3489 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
3490 ;; distribute this software ; Should you use this software for any purpose, ;;
3491 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
3492 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
3493 ;; continue doing so for the indefinite future. In any case, please ;;
3494 ;; always : read and understand any software ; verify any PGP signatures ;;
3495 ;; that you use - for any purpose. ;;
3496 ;; ;;
3497 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
3498 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3499
3500 ;; TODO: Tests!!!
3501
3502 ;-----------------------------------------------------------------------------
3503 section .rodata
3504 align GRAIN, db 0x90
3505 _M_Table:
3506 A32 _bad ; 0x00 : UNDEFINED
3507 A32 _bad ; 0x01 : UNDEFINED
3508 A32 _m_tlbwi ; 0x02 : tlbwi (01000010000000000000000000000010)
3509 A32 _bad ; 0x03 : UNDEFINED
3510 A32 _bad ; 0x04 : UNDEFINED
3511 A32 _bad ; 0x05 : UNDEFINED
3512 A32 _m_tlbwr ; 0x06 : tlbwr (01000010000000000000000000000110)
3513 A32 _bad ; 0x07 : UNDEFINED
3514 A32 _m_tlbp ; 0x08 : tlbp (01000010000000000000000000001000)
3515 A32 _bad ; 0x09 : UNDEFINED
3516 A32 _bad ; 0x0a : UNDEFINED
3517 A32 _bad ; 0x0b : UNDEFINED
3518 A32 _bad ; 0x0c : UNDEFINED
3519 A32 _bad ; 0x0d : UNDEFINED
3520 A32 _bad ; 0x0e : UNDEFINED
3521 A32 _bad ; 0x0f : UNDEFINED
3522 A32 _bad ; 0x10 : UNDEFINED
3523 A32 _bad ; 0x11 : UNDEFINED
3524 A32 _bad ; 0x12 : UNDEFINED
3525 A32 _bad ; 0x13 : UNDEFINED
3526 A32 _bad ; 0x14 : UNDEFINED
3527 A32 _bad ; 0x15 : UNDEFINED
3528 A32 _bad ; 0x16 : UNDEFINED
3529 A32 _bad ; 0x17 : UNDEFINED
3530 A32 _m_eret ; 0x18 : eret (01000010000000000000000000011000)
3531 A32 _bad ; 0x19 : UNDEFINED
3532 A32 _bad ; 0x1a : UNDEFINED
3533 A32 _bad ; 0x1b : UNDEFINED
3534 A32 _bad ; 0x1c : UNDEFINED
3535 A32 _bad ; 0x1d : UNDEFINED
3536 A32 _bad ; 0x1e : UNDEFINED
3537 A32 _bad ; 0x1f : UNDEFINED
3538 ;-----------------------------------------------------------------------------
3539
3540 section .text
3541
3542 ;-----------------------------------------------------------------------
3543 ; 'M-Type' Instructions (tlbwi, tlbwr, tlbp, eret, mfc0, mtc0, wait) : |
3544 ;-----------------------------------------------------------------------
3545
3546 ;-----------------------------------------------------------------------------
3547 ; TLBWI - Write Indexed TLB Entry.
3548 ; Write a TLB entry indexed by the Index register.
3549 ; The TLB entry pointed to by the Index register is written from the contents
3550 ; of the EntryHi, EntryLo0, EntryLo1, and PageMask registers.
3551 ; Syntax: tlbwi
3552 ; Encoding: 0100 0010 0000 0000 0000 0000 0000 0010
3553 ; PRIVILEGED (permitted in Kernel Mode only.)
3554 ;-----------------------------------------------------------------------------
3555 align GRAIN, db 0x90
3556 _m_tlbwi:
3557 ; no fields
3558 mov AUX, Sr(CP0_Index) ; Get CP0_Index register
3559 call _write_tlb_entry ; Write the indexed TLB entry.
3560 jmp _end_cycle
3561 ;-----------------------------------------------------------------------------
3562
3563 ;-----------------------------------------------------------------------------
3564 ; TLBWR - Write Random TLB Entry.
3565 ; Write a TLB entry indexed by the Random register.
3566 ; The TLB entry pointed to by the Random register is written from the contents
3567 ; of the EntryHi, EntryLo0, EntryLo1, and PageMask registers.
3568 ; Syntax: tlbwr
3569 ; Encoding: 0100 0010 0000 0000 0000 0000 0000 0110
3570 ; PRIVILEGED (permitted in Kernel Mode only.)
3571 ;-----------------------------------------------------------------------------
3572 align GRAIN, db 0x90
3573 _m_tlbwr:
3574 ; no fields
3575 mov ecx, Sr(CP0_Wired) ; ecx := CP0_Wired
3576 mov ebx, TLB_ENTRIES_COUNT ; ebx := #tlbentries
3577 sub ebx, ecx ; ebx := #tlbentries - Wired
3578 mov edx, 0 ; edx (upper half of dividend) := 0
3579 mov eax, CP0_Count ; eax (lower half of divident) := cnt
3580 div ebx ; edx:eax / ebx
3581 add edx, ecx ; edx (remainder) := edx + wired
3582 mov AUX, edx ; make edx the index for tlb write
3583 call _write_tlb_entry ; Write the indexed TLB entry.
3584 jmp _end_cycle
3585 ;-----------------------------------------------------------------------------
3586
3587 ;-----------------------------------------------------------------------------
3588 ; TLBP - Probe TLB for Matching Entry.
3589 ; Find a matching entry in the TLB.
3590 ; The Index register is loaded with the address of the TLB entry whose
3591 ; contents match the contents of the EntryHi register. If no TLB entry
3592 ; matches, the high-order bit of the Index register is set.
3593 ; Syntax: tlbp
3594 ; Encoding: 0100 0010 0000 0000 0000 0000 0000 1000
3595 ; PRIVILEGED (permitted in Kernel Mode only.)
3596 ;-----------------------------------------------------------------------------
3597 align GRAIN, db 0x90
3598 _m_tlbp:
3599 ; no fields
3600 mov Sr(CP0_Index), 0x80000000 ; CP0_Index := 0x80000000
3601 ;; Get the active ASID:
3602 mov edx, Sr(CP0_EntryHi) ; edx := CP0_EntryHi
3603 mov ecx, edx ; ecx := edx
3604 and edx, 0xFF ; edx := edx & 0xFF (get current ASID)
3605 ;; Get the desired tag:
3606 and ecx, 0xFFFFF000 ; ecx := ecx & 0xFFFFF000
3607 shr ecx, 13 ; ecx := ecx >> 13 (current Tag)
3608 ;; For each slot in table (0 .. 15), attempt lookup
3609 xor AUX, AUX ; Start with the 0-th entry in table
3610 _m_tlbp_lookup_entry:
3611 mov eax, TLB_E(AUX) ; eax := current TLB entry
3612 mov ebx, eax ; ebx := eax
3613 and ebx, TLB_VPN2_Mask ; get VPN2 of this entry
3614 cmp ebx, ecx ; cmp(entry.VPN2, vAddr.tag)
3615 jne _m_tlbp_lookup_nope ; if entry.VPN2 != vAddr.tag: no match
3616 bt eax, TLB_G ; is entry.G = 1?
3617 jc _m_tlbp_lookup_match ; then match.
3618 shr eax, TLB_ASID_Shift ; eax := eax >> TLB_ASID_Shift
3619 and eax, TLB_ASID_Mask ; eax := entry.ASID
3620 cmp eax, edx ; entry.ASID = current ASID ?
3621 jne _m_tlbp_lookup_nope ; if neither G=1 nor ASID match.
3622 ;; otherwise:
3623 _m_tlbp_lookup_match: ; TLB Match:
3624 mov Sr(CP0_Index), AUX ; Save the index
3625 jmp _end_cycle ; Fin.
3626 _m_tlbp_lookup_nope: ; try next one in the table, if any
3627 inc AUX ; index := index + 1
3628 cmp AUX, TLB_ENTRIES_COUNT ; see if still in range 0 .. n-1
3629 jb _m_tlbp_lookup_entry ; if in range, go to next entry
3630 ;; if we found nothing, we end up with CP0_Index = 0x80000000
3631 jmp _end_cycle ; Fin.
3632 ;-----------------------------------------------------------------------------
3633
3634 ;-----------------------------------------------------------------------------
3635 ; ERET - Exception Return.
3636 ; Return from interrupt, exception, or error trap.
3637 ; Syntax: eret
3638 ; Encoding: 0100 0010 0000 0000 0000 0000 0001 1000
3639 ; PRIVILEGED (permitted in Kernel Mode only.)
3640 ;;-----------------------------------------------------------------------------
3641 align GRAIN, db 0x90
3642 _m_eret:
3643 ; no fields
3644 Flg_Get InDelaySlot ; CF := whether we are in delay slot
3645 jc _m_eret_abort ; ... if so, abort this instruction; else:
3646 ;; proceed:
3647 Flg_Off LL_Bit ; Clear the LL_Bit Flag
3648 btr CP0_Status, CP0St_ERL ; CF := CP0St_ERL Flag, and clear it
3649 jnc _m_eret_erl_false ; If ERL was not set, do erl_false; else:
3650 _m_eret_erl_true:
3651 mov PC, Sr(CP0_ErrorEpc) ; PC := CP0_ErrorEpc
3652 jmp _m_eret_done ; Done with this case
3653 _m_eret_erl_false:
3654 mov PC, Sr(CP0_Epc) ; PC := CP0_Epc
3655 btr CP0_Status, CP0St_EXL ; Clear the EXL Flag
3656 _m_eret_done:
3657 sub PC, 0x4 ; Counteract the usual PC = PC + 4
3658 _m_eret_abort:
3659 jmp _end_cycle
3660 ;-----------------------------------------------------------------------------
3661
3662 ;-----------------------------------------------------------------------------
3663 ; MFC0 - Move from Coprocessor 0.
3664 ; Move the contents of a coprocessor 0 register to a general register.
3665 ; The contents of the coprocessor 0 register specified by the combination of
3666 ; rd and sel (q) are loaded into general register rt. Note that not all
3667 ; coprocessor 0 registers support the sel field. In those instances, the sel
3668 ; field must be zero.
3669 ; Operation: $t = CPR[0, rD, q]
3670 ; Syntax: mfc0 $t, $d, q
3671 ; Encoding: 0100 0000 000t tttt dddd d000 0000 0qqq
3672 ; PRIVILEGED (permitted in Kernel Mode only.)
3673 ;-----------------------------------------------------------------------------
3674 align GRAIN, db 0x90
3675 _m_mfc0:
3676 CPType ; Load Q, rD, rT (ecx, eax, ebx)
3677 JTABLE eax, _MFC0_Table ; Dispatch on rD via MFC0 Table.
3678 ;; We continue in _mfc0_rXX where XX is rD.
3679 ;-----------------------------------------------------------------------------
3680
3681 ;-----------------------------------------------------------------------------
3682 ; MFC0 Cases. Parameters: Q (ecx), rD (eax), rT (ebx)
3683 ;-----------------------------------------------------------------------------
3684 _mfc0_r00: ; 0x00
3685 test ecx, ecx ; Sel != 0 ?
3686 jnz _mfc0_unknown ; ... then unknown; else:
3687 mov TMP, Sr(CP0_Index) ; return CP0_Index
3688 jmp _mfc0_writeback ; Done
3689 ;-----------------------------------------------------------------------------
3690 _mfc0_r01: ; 0x01
3691 jmp _mfc0_unknown
3692 ;-----------------------------------------------------------------------------
3693 _mfc0_r02: ; 0x02
3694 mov TMP, Sr(CP0_EntryLo0) ; return CP0_EntryLo0
3695 jmp _mfc0_writeback ; Done
3696 ;-----------------------------------------------------------------------------
3697 _mfc0_r03: ; 0x03
3698 mov TMP, Sr(CP0_EntryLo1) ; return CP0_EntryLo1
3699 jmp _mfc0_writeback ; Done
3700 ;-----------------------------------------------------------------------------
3701 _mfc0_r04: ; 0x04
3702 test ecx, ecx ; Sel != 0 ?
3703 jnz _mfc0_unknown ; ... then unknown; else:
3704 mov TMP, Sr(CP0_Context) ; return CP0_Context
3705 jmp _mfc0_writeback ; Done
3706 ;-----------------------------------------------------------------------------
3707 _mfc0_r05: ; 0x05
3708 test ecx, ecx ; Sel != 0 ?
3709 jnz _mfc0_unknown ; ... then unknown; else:
3710 mov TMP, Sr(CP0_PageMask) ; return CP0_PageMask
3711 jmp _mfc0_writeback ; Done
3712 ;-----------------------------------------------------------------------------
3713 _mfc0_r06: ; 0x06
3714 test ecx, ecx ; Sel != 0 ?
3715 jnz _mfc0_unknown ; ... then unknown; else:
3716 mov TMP, Sr(CP0_Wired) ; return CP0_Wired
3717 jmp _mfc0_writeback ; Done
3718 ;-----------------------------------------------------------------------------
3719 _mfc0_r07: ; 0x07
3720 jmp _mfc0_unknown
3721 ;-----------------------------------------------------------------------------
3722 _mfc0_r08: ; 0x08
3723 test ecx, ecx ; Sel != 0 ?
3724 jnz _mfc0_unknown ; ... then unknown; else:
3725 mov TMP, Sr(CP0_BadVAddr) ; return CP0_BadVAddr
3726 jmp _mfc0_writeback ; Done
3727 ;-----------------------------------------------------------------------------
3728 _mfc0_r09: ; 0x09
3729 test ecx, ecx ; Sel != 0 ?
3730 jnz _mfc0_unknown ; ... then unknown; else:
3731 mov TMP, CP0_Count ; return CP0_Count ('fast reg')
3732 jmp _mfc0_writeback ; Done
3733 ;-----------------------------------------------------------------------------
3734 _mfc0_r10: ; 0x0a
3735 test ecx, ecx ; Sel != 0 ?
3736 jnz _mfc0_unknown ; ... then unknown; else:
3737 mov TMP, Sr(CP0_EntryHi) ; return CP0_EntryHi
3738 jmp _mfc0_writeback ; Done
3739 ;-----------------------------------------------------------------------------
3740 _mfc0_r11: ; 0x0b
3741 test ecx, ecx ; Sel != 0 ?
3742 jnz _mfc0_unknown ; ... then unknown; else:
3743 mov TMP, CP0_Compare ; return CP0_Compare ('fast reg')
3744 jmp _mfc0_writeback ; Done
3745 ;-----------------------------------------------------------------------------
3746 _mfc0_r12: ; 0x0c
3747 test ecx, ecx ; Sel != 0 ?
3748 jnz _mfc0_unknown ; ... then unknown; else:
3749 mov TMP, CP0_Status ; return CP0_Status ('fast reg')
3750 jmp _mfc0_writeback ; Done
3751 ;-----------------------------------------------------------------------------
3752 _mfc0_r13: ; 0x0d
3753 test ecx, ecx ; Sel != 0 ?
3754 jnz _mfc0_unknown ; ... then unknown; else:
3755 mov TMP, CP0_Cause ; return CP0_Cause ('fast reg')
3756 jmp _mfc0_writeback ; Done
3757 ;-----------------------------------------------------------------------------
3758 _mfc0_r14: ; 0x0e
3759 test ecx, ecx ; Sel != 0 ?
3760 jnz _mfc0_unknown ; ... then unknown; else:
3761 mov TMP, Sr(CP0_Epc) ; return CP0_Epc
3762 jmp _mfc0_writeback ; Done
3763 ;-----------------------------------------------------------------------------
3764 _mfc0_r15: ; 0x0f
3765 mov TMP, 0x00018000 ; processor id (qemu 4kc)
3766 jmp _mfc0_writeback ; Done
3767 ;-----------------------------------------------------------------------------
3768 _mfc0_r16: ; 0x10
3769 cmp r_Q, 0 ; Is sel = 0?
3770 je _mfc0_r16_q_0 ; If sel = 0...
3771 cmp r_Q, 1 ; Is sel = 1?
3772 je _mfc0_r16_q_1 ; If sel = 1...
3773 jmp _mfc0_unknown ; Unknown sel
3774 _mfc0_r16_q_0:
3775 mov TMP, 0x80008082 ; return 0x80008082
3776 jmp _mfc0_writeback ; Done
3777 _mfc0_r16_q_1:
3778 mov TMP, 0x1e190c8a ; return 0x1e190c8a
3779 jmp _mfc0_writeback ; Done
3780 ;-----------------------------------------------------------------------------
3781 _mfc0_r17: ; 0x11
3782 jmp _mfc0_unknown
3783 ;-----------------------------------------------------------------------------
3784 _mfc0_r18: ; 0x12
3785 xor TMP, TMP ; TMP = 0
3786 jmp _mfc0_writeback ; Done
3787 ;-----------------------------------------------------------------------------
3788 _mfc0_r19: ; 0x13
3789 xor TMP, TMP ; TMP = 0
3790 jmp _mfc0_writeback ; Done
3791 ;-----------------------------------------------------------------------------
3792 _mfc0_r20: ; 0x14
3793 jmp _mfc0_unknown
3794 ;-----------------------------------------------------------------------------
3795 _mfc0_r21: ; 0x15
3796 jmp _mfc0_unknown
3797 ;-----------------------------------------------------------------------------
3798 _mfc0_r22: ; 0x16
3799 jmp _mfc0_unknown
3800 ;-----------------------------------------------------------------------------
3801 _mfc0_r23: ; 0x17
3802 jmp _mfc0_unknown
3803 ;-----------------------------------------------------------------------------
3804 _mfc0_r24: ; 0x18
3805 jmp _mfc0_unknown
3806 ;-----------------------------------------------------------------------------
3807 _mfc0_r25: ; 0x19
3808 jmp _mfc0_unknown
3809 ;-----------------------------------------------------------------------------
3810 _mfc0_r26: ; 0x1a
3811 jmp _mfc0_unknown
3812 ;-----------------------------------------------------------------------------
3813 _mfc0_r27: ; 0x1b
3814 jmp _mfc0_unknown
3815 ;-----------------------------------------------------------------------------
3816 _mfc0_r28: ; 0x1c
3817 jmp _mfc0_unknown
3818 ;-----------------------------------------------------------------------------
3819 _mfc0_r29: ; 0x1d
3820 jmp _mfc0_unknown
3821 ;-----------------------------------------------------------------------------
3822 _mfc0_r30: ; 0x1e
3823 jmp _mfc0_unknown
3824 ;-----------------------------------------------------------------------------
3825 _mfc0_r31: ; 0x1f
3826 jmp _mfc0_unknown
3827 ;-----------------------------------------------------------------------------
3828 _mfc0_writeback: ; Write result and go to next cycle
3829 Wr_Reg rT, TMP ; Regs[rT] := TMP (result)
3830 jmp _end_cycle ; Fin
3831 ;-----------------------------------------------------------------------------
3832 _mfc0_unknown:
3833 ; 'The results are UNDEFINED if coprocessor 0 does not contain a
3834 ; register as specified by rd and sel.'
3835 ACHTUNG "Unknown CP0 Reg Selector in MFC0!" ;; TODO: print detail
3836 jmp _end_cycle ; Do nothing, carry on.
3837 ;-----------------------------------------------------------------------------
3838
3839 ;-----------------------------------------------------------------------------
3840 ; MTC0 - Move to Coprocessor 0.
3841 ; Move the contents of a general register to a coprocessor 0 register.
3842 ; The contents of general register rt are loaded into the coprocessor 0
3843 ; register specified by the combination of rd and sel (q). Not all
3844 ; coprocessor 0 registers support the the sel field. In those instances, the
3845 ; sel field must be set to zero.
3846 ; Operation: CPR[0, rD, q] = $t
3847 ; Syntax: mfc0 $t, $d, q
3848 ; Encoding: 0100 0000 100t tttt dddd d000 0000 0qqq
3849 ; PRIVILEGED (permitted in Kernel Mode only.)
3850 ;-----------------------------------------------------------------------------
3851 align GRAIN, db 0x90
3852 _m_mtc0:
3853 CPType ; Load Q, rD, rT (ecx, eax, ebx)
3854 mov rT, R(rT) ; ebx := Regs[rT]
3855 JTABLE eax, _MTC0_Table ; Dispatch on rD via MTC0 Table.
3856 ;; We continue in _mtc0_rXX where XX is rD.
3857 ;-----------------------------------------------------------------------------
3858
3859 ;-----------------------------------------------------------------------------
3860 ; MTC0 Cases. Parameters: Q (ecx), rD (eax), Regs[rT] (ebx)
3861 ;-----------------------------------------------------------------------------
3862 _mtc0_r00: ; 0x00
3863 test ecx, ecx ; Sel != 0 ?
3864 jnz _mtc0_unknown ; ... then unknown; else:
3865 mov eax, Sr(CP0_Index) ; eax := CP0_Index
3866 and ebx, 0xF ; T := T & 0xF
3867 and eax, 0x80000000 ; eax := eax & 0x80000000
3868 or eax, ebx ; eax := eax | T
3869 mov Sr(CP0_Index), eax ; CP0_Index := eax
3870 jmp _end_cycle ; Done
3871 ;-----------------------------------------------------------------------------
3872 _mtc0_r01: ; 0x01
3873 jmp _mtc0_unknown
3874 ;-----------------------------------------------------------------------------
3875 _mtc0_r02: ; 0x02
3876 and ebx, 0x3FFFFFF ; T := T & 0x3FFFFFF
3877 mov Sr(CP0_EntryLo0), ebx ; CP0_EntryLo0 := T
3878 jmp _end_cycle ; Done
3879 ;-----------------------------------------------------------------------------
3880 _mtc0_r03: ; 0x03
3881 and ebx, 0x3FFFFFF ; T := T & 0x3FFFFFF
3882 mov Sr(CP0_EntryLo1), ebx ; CP0_EntryLo1 := T
3883 jmp _end_cycle ; Done
3884 ;-----------------------------------------------------------------------------
3885 _mtc0_r04: ; 0x04
3886 %define CONTEXTMASK 0xFF800000
3887 %define nCONTEXTMASK (0xFFFFFFFF ^ 0xFF800000)
3888 mov eax, Sr(CP0_Context) ; eax := CP0_Context
3889 and ebx, CONTEXTMASK ; T := T & CONTEXTMASK
3890 and eax, nCONTEXTMASK ; eax := eax & ~CONTEXTMASK
3891 or eax, ebx ; eax := eax | T
3892 mov Sr(CP0_Context), eax ; CP0_Context := eax
3893 jmp _end_cycle ; Done
3894 ;-----------------------------------------------------------------------------
3895 _mtc0_r05: ; 0x05
3896 test ecx, ecx ; Sel != 0 ?
3897 jnz _mtc0_unknown ; ... then unknown; else:
3898 test ebx, ebx ; T != 0 ?
3899 jnz _mtc0_r05_untest_pgmask ; If so, eggog
3900 and ebx, 0x1FFE000 ; T := T & 0x1FFE000
3901 mov Sr(CP0_PageMask), ebx ; CP0_PageMask := T
3902 jmp _end_cycle ; Done
3903 _mtc0_r05_untest_pgmask: ; Proper kernel won't do this. But if someone does:
3904 ACHTUNG "MTC0: Unsupported Page Mask!" ; maybe halt w/ sirens?
3905 jmp _end_cycle ; Let's continue (probably wedged...)
3906 ;-----------------------------------------------------------------------------
3907 _mtc0_r06: ; 0x06
3908 test ecx, ecx ; Sel != 0 ?
3909 jnz _mtc0_unknown ; ... then unknown; else:
3910 and ebx, 0xF ; T := T & 0xF
3911 mov Sr(CP0_Wired), ebx ; CP0_Wired := T
3912 jmp _end_cycle ; Done
3913 ;-----------------------------------------------------------------------------
3914 _mtc0_r07: ; 0x07
3915 jmp _mtc0_unknown
3916 ;-----------------------------------------------------------------------------
3917 _mtc0_r08: ; 0x08
3918 jmp _mtc0_unknown
3919 ;-----------------------------------------------------------------------------
3920 _mtc0_r09: ; 0x09
3921 test ecx, ecx ; Sel != 0 ?
3922 jnz _mtc0_unknown ; ... then unknown; else:
3923 mov CP0_Count, ebx ; CP0_Count := T ('fast reg')
3924 jmp _end_cycle ; Done
3925 ;-----------------------------------------------------------------------------
3926 _mtc0_r10: ; 0x0a
3927 test ecx, ecx ; Sel != 0 ?
3928 jnz _mtc0_unknown ; ... then unknown; else:
3929 and ebx, ~0x1F00 ; T := T & ~0x1F00
3930 mov Sr(CP0_EntryHi), ebx ; CP0_EntryHi := T
3931 jmp _end_cycle ; Done
3932 ;-----------------------------------------------------------------------------
3933 _mtc0_r11: ; 0x0b
3934 test ecx, ecx ; Sel != 0 ?
3935 jnz _mtc0_unknown ; ... then unknown; else:
3936 ClrIRQ TIMER_IRQ ; Clear MIPS Timer IRQ
3937 mov CP0_Compare, ebx ; CP0_Compare := T ('fast reg')
3938 jmp _end_cycle ; Done
3939 ;-----------------------------------------------------------------------------
3940 _mtc0_r12: ; 0x0c
3941 test ecx, ecx ; Sel != 0 ?
3942 jnz _mtc0_unknown ; ... then unknown; else:
3943 %define STATUSMASK 0x7D7CFF17
3944 mov eax, CP0_Status ; eax := CP0_Status
3945 and ebx, STATUSMASK ; T := T & STATUSMASK
3946 and eax, ~STATUSMASK ; eax := eax & ~STATUSMASK
3947 or eax, ebx ; eax := eax | T
3948 mov CP0_Status, eax ; CP0_Status := eax
3949 jmp _end_cycle ; Done
3950 ;-----------------------------------------------------------------------------
3951 _mtc0_r13: ; 0x0d
3952 test ecx, ecx ; Sel != 0 ?
3953 jnz _mtc0_unknown ; ... then unknown; else:
3954 %define CAUSEMASK ((1 << 23) | (1 << 22) | (3 << 8))
3955 mov eax, CP0_Cause ; eax := CP0_Cause
3956 and ebx, CAUSEMASK ; T := T & CAUSEMASK
3957 and eax, ~CAUSEMASK ; eax := eax & ~CAUSEMASK
3958 or eax, ebx ; eax := eax | T
3959 mov CP0_Cause, eax ; CP0_Cause := eax
3960 jmp _end_cycle ; Done
3961 ;-----------------------------------------------------------------------------
3962 _mtc0_r14: ; 0x0e
3963 test ecx, ecx ; Sel != 0 ?
3964 jnz _mtc0_unknown ; ... then unknown; else:
3965 mov Sr(CP0_Epc), ebx ; CP0_Epc := T
3966 jmp _end_cycle ; Done
3967 ;-----------------------------------------------------------------------------
3968 _mtc0_r15: ; 0x0f
3969 jmp _mtc0_unknown
3970 ;-----------------------------------------------------------------------------
3971 _mtc0_r16: ; 0x10
3972 jmp _end_cycle ; Done
3973 ;-----------------------------------------------------------------------------
3974 _mtc0_r17: ; 0x11
3975 jmp _mtc0_unknown
3976 ;-----------------------------------------------------------------------------
3977 _mtc0_r18: ; 0x12
3978 jmp _end_cycle ; Done
3979 ;-----------------------------------------------------------------------------
3980 _mtc0_r19: ; 0x13
3981 jmp _end_cycle ; Done
3982 ;-----------------------------------------------------------------------------
3983 _mtc0_r20: ; 0x14
3984 jmp _mtc0_unknown ; Done
3985 ;-----------------------------------------------------------------------------
3986 _mtc0_r21: ; 0x15
3987 jmp _mtc0_unknown ; Done
3988 ;-----------------------------------------------------------------------------
3989 _mtc0_r22: ; 0x16
3990 jmp _mtc0_unknown ; Done
3991 ;-----------------------------------------------------------------------------
3992 _mtc0_r23: ; 0x17
3993 jmp _mtc0_unknown ; Done
3994 ;-----------------------------------------------------------------------------
3995 _mtc0_r24: ; 0x18
3996 jmp _mtc0_unknown ; Done
3997 ;-----------------------------------------------------------------------------
3998 _mtc0_r25: ; 0x19
3999 jmp _mtc0_unknown ; Done
4000 ;-----------------------------------------------------------------------------
4001 _mtc0_r26: ; 0x1a
4002 jmp _mtc0_unknown ; Done
4003 ;-----------------------------------------------------------------------------
4004 _mtc0_r27: ; 0x1b
4005 jmp _mtc0_unknown ; Done
4006 ;-----------------------------------------------------------------------------
4007 _mtc0_r28: ; 0x1c
4008 jmp _mtc0_unknown ; Done
4009 ;-----------------------------------------------------------------------------
4010 _mtc0_r29: ; 0x1d
4011 jmp _mtc0_unknown ; Done
4012 ;-----------------------------------------------------------------------------
4013 _mtc0_r30: ; 0x1e
4014 jmp _mtc0_unknown ; Done
4015 ;-----------------------------------------------------------------------------
4016 _mtc0_r31: ; 0x1f
4017 jmp _mtc0_unknown ; Done
4018 ;-----------------------------------------------------------------------------
4019 _mtc0_unknown:
4020 ; 'The results are UNDEFINED if coprocessor 0 does not contain a
4021 ; register as specified by rd and sel.'
4022 ACHTUNG "Unknown CP0 Reg Selector in MTC0!" ;; TODO: print detail
4023 jmp _end_cycle ; Done
4024 ;-----------------------------------------------------------------------------
4025
4026 ;-----------------------------------------------------------------------------
4027 ; WAIT - Enter Standby Mode.
4028 ; Wait for Event.
4029 ; Puts the emulator into 'wait' mode.
4030 ; Encoding: 0100 001- ---- ---- ---- ---- --10 0000
4031 ; PRIVILEGED (permitted in Kernel Mode only.)
4032 ;-----------------------------------------------------------------------------
4033 align GRAIN, db 0x90
4034 _m_wait:
4035 ; no fields
4036 Flg_On Waiting ; Set 'Waiting' Flag.
4037 jmp _end_cycle
4038 ;-----------------------------------------------------------------------------