;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; This file is part of 'M', a MIPS system emulator. ;; ;; ;; ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;; ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;; ;; ;; ;; You do not have, nor can you ever acquire the right to use, copy or ;; ;; distribute this software ; Should you use this software for any purpose, ;; ;; or copy and distribute it to anyone or in any manner, you are breaking ;; ;; the laws of whatever soi-disant jurisdiction, and you promise to ;; ;; continue doing so for the indefinite future. In any case, please ;; ;; always : read and understand any software ; verify any PGP signatures ;; ;; that you use - for any purpose. ;; ;; ;; ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; TODO: Tests!!! ;----------------------------------------------------------------------------- section .rodata align GRAIN, db 0x90 _M_Table: A32 _bad ; 0x00 : UNDEFINED A32 _bad ; 0x01 : UNDEFINED A32 _m_tlbwi ; 0x02 : tlbwi (01000010000000000000000000000010) A32 _bad ; 0x03 : UNDEFINED A32 _bad ; 0x04 : UNDEFINED A32 _bad ; 0x05 : UNDEFINED A32 _m_tlbwr ; 0x06 : tlbwr (01000010000000000000000000000110) A32 _bad ; 0x07 : UNDEFINED A32 _m_tlbp ; 0x08 : tlbp (01000010000000000000000000001000) A32 _bad ; 0x09 : UNDEFINED A32 _bad ; 0x0a : UNDEFINED A32 _bad ; 0x0b : UNDEFINED A32 _bad ; 0x0c : UNDEFINED A32 _bad ; 0x0d : UNDEFINED A32 _bad ; 0x0e : UNDEFINED A32 _bad ; 0x0f : UNDEFINED A32 _bad ; 0x10 : UNDEFINED A32 _bad ; 0x11 : UNDEFINED A32 _bad ; 0x12 : UNDEFINED A32 _bad ; 0x13 : UNDEFINED A32 _bad ; 0x14 : UNDEFINED A32 _bad ; 0x15 : UNDEFINED A32 _bad ; 0x16 : UNDEFINED A32 _bad ; 0x17 : UNDEFINED A32 _m_eret ; 0x18 : eret (01000010000000000000000000011000) A32 _bad ; 0x19 : UNDEFINED A32 _bad ; 0x1a : UNDEFINED A32 _bad ; 0x1b : UNDEFINED A32 _bad ; 0x1c : UNDEFINED A32 _bad ; 0x1d : UNDEFINED A32 _bad ; 0x1e : UNDEFINED A32 _bad ; 0x1f : UNDEFINED ;----------------------------------------------------------------------------- section .text ;----------------------------------------------------------------------- ; 'M-Type' Instructions (tlbwi, tlbwr, tlbp, eret, mfc0, mtc0, wait) : | ;----------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; TLBWI - Write Indexed TLB Entry. ; Write a TLB entry indexed by the Index register. ; The TLB entry pointed to by the Index register is written from the contents ; of the EntryHi, EntryLo0, EntryLo1, and PageMask registers. ; Syntax: tlbwi ; Encoding: 0100 0010 0000 0000 0000 0000 0000 0010 ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_tlbwi: ; no fields mov AUX, Sr(CP0_Index) ; Get CP0_Index register call _write_tlb_entry ; Write the indexed TLB entry. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; TLBWR - Write Random TLB Entry. ; Write a TLB entry indexed by the Random register. ; The TLB entry pointed to by the Random register is written from the contents ; of the EntryHi, EntryLo0, EntryLo1, and PageMask registers. ; Syntax: tlbwr ; Encoding: 0100 0010 0000 0000 0000 0000 0000 0110 ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_tlbwr: ; no fields mov ecx, Sr(CP0_Wired) ; ecx := CP0_Wired mov ebx, TLB_ENTRIES_COUNT ; ebx := #tlbentries sub ebx, ecx ; ebx := #tlbentries - Wired mov edx, 0 ; edx (upper half of dividend) := 0 mov eax, CP0_Count ; eax (lower half of divident) := cnt div ebx ; edx:eax / ebx add edx, ecx ; edx (remainder) := edx + wired mov AUX, edx ; make edx the index for tlb write call _write_tlb_entry ; Write the indexed TLB entry. jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; TLBP - Probe TLB for Matching Entry. ; Find a matching entry in the TLB. ; The Index register is loaded with the address of the TLB entry whose ; contents match the contents of the EntryHi register. If no TLB entry ; matches, the high-order bit of the Index register is set. ; Syntax: tlbp ; Encoding: 0100 0010 0000 0000 0000 0000 0000 1000 ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_tlbp: ; no fields mov Sr(CP0_Index), 0x80000000 ; CP0_Index := 0x80000000 ;; Get the active ASID: mov edx, Sr(CP0_EntryHi) ; edx := CP0_EntryHi mov ecx, edx ; ecx := edx and edx, 0xFF ; edx := edx & 0xFF (get current ASID) ;; Get the desired tag: and ecx, 0xFFFFF000 ; ecx := ecx & 0xFFFFF000 shr ecx, 13 ; ecx := ecx >> 13 (current Tag) ;; For each slot in table (0 .. 15), attempt lookup xor AUX, AUX ; Start with the 0-th entry in table _m_tlbp_lookup_entry: mov eax, TLB_E(AUX) ; eax := current TLB entry mov ebx, eax ; ebx := eax and ebx, TLB_VPN2_Mask ; get VPN2 of this entry cmp ebx, ecx ; cmp(entry.VPN2, vAddr.tag) jne _m_tlbp_lookup_nope ; if entry.VPN2 != vAddr.tag: no match bt eax, TLB_G ; is entry.G = 1? jc _m_tlbp_lookup_match ; then match. shr eax, TLB_ASID_Shift ; eax := eax >> TLB_ASID_Shift and eax, TLB_ASID_Mask ; eax := entry.ASID cmp eax, edx ; entry.ASID = current ASID ? jne _m_tlbp_lookup_nope ; if neither G=1 nor ASID match. ;; otherwise: _m_tlbp_lookup_match: ; TLB Match: mov Sr(CP0_Index), AUX ; Save the index jmp _end_cycle ; Fin. _m_tlbp_lookup_nope: ; try next one in the table, if any inc AUX ; index := index + 1 cmp AUX, TLB_ENTRIES_COUNT ; see if still in range 0 .. n-1 jb _m_tlbp_lookup_entry ; if in range, go to next entry ;; if we found nothing, we end up with CP0_Index = 0x80000000 jmp _end_cycle ; Fin. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; ERET - Exception Return. ; Return from interrupt, exception, or error trap. ; Syntax: eret ; Encoding: 0100 0010 0000 0000 0000 0000 0001 1000 ; PRIVILEGED (permitted in Kernel Mode only.) ;;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_eret: ; no fields Flg_Get InDelaySlot ; CF := whether we are in delay slot jc _m_eret_abort ; ... if so, abort this instruction; else: ;; proceed: Flg_Off LL_Bit ; Clear the LL_Bit Flag btr CP0_Status, CP0St_ERL ; CF := CP0St_ERL Flag, and clear it jnc _m_eret_erl_false ; If ERL was not set, do erl_false; else: _m_eret_erl_true: mov PC, Sr(CP0_ErrorEpc) ; PC := CP0_ErrorEpc jmp _m_eret_done ; Done with this case _m_eret_erl_false: mov PC, Sr(CP0_Epc) ; PC := CP0_Epc btr CP0_Status, CP0St_EXL ; Clear the EXL Flag _m_eret_done: sub PC, 0x4 ; Counteract the usual PC = PC + 4 _m_eret_abort: jmp _end_cycle ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MFC0 - Move from Coprocessor 0. ; Move the contents of a coprocessor 0 register to a general register. ; The contents of the coprocessor 0 register specified by the combination of ; rd and sel (q) are loaded into general register rt. Note that not all ; coprocessor 0 registers support the sel field. In those instances, the sel ; field must be zero. ; Operation: $t = CPR[0, rD, q] ; Syntax: mfc0 $t, $d, q ; Encoding: 0100 0000 000t tttt dddd d000 0000 0qqq ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_mfc0: CPType ; Load Q, rD, rT (ecx, eax, ebx) JTABLE eax, _MFC0_Table ; Dispatch on rD via MFC0 Table. ;; We continue in _mfc0_rXX where XX is rD. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MFC0 Cases. Parameters: Q (ecx), rD (eax), rT (ebx) ;----------------------------------------------------------------------------- _mfc0_r00: ; 0x00 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_Index) ; return CP0_Index jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r01: ; 0x01 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r02: ; 0x02 mov TMP, Sr(CP0_EntryLo0) ; return CP0_EntryLo0 jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r03: ; 0x03 mov TMP, Sr(CP0_EntryLo1) ; return CP0_EntryLo1 jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r04: ; 0x04 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_Context) ; return CP0_Context jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r05: ; 0x05 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_PageMask) ; return CP0_PageMask jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r06: ; 0x06 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_Wired) ; return CP0_Wired jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r07: ; 0x07 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r08: ; 0x08 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_BadVAddr) ; return CP0_BadVAddr jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r09: ; 0x09 test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, CP0_Count ; return CP0_Count ('fast reg') jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r10: ; 0x0a test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_EntryHi) ; return CP0_EntryHi jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r11: ; 0x0b test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, CP0_Compare ; return CP0_Compare ('fast reg') jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r12: ; 0x0c test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, CP0_Status ; return CP0_Status ('fast reg') jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r13: ; 0x0d test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, CP0_Cause ; return CP0_Cause ('fast reg') jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r14: ; 0x0e test ecx, ecx ; Sel != 0 ? jnz _mfc0_unknown ; ... then unknown; else: mov TMP, Sr(CP0_Epc) ; return CP0_Epc jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r15: ; 0x0f mov TMP, 0x00018000 ; processor id (qemu 4kc) jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r16: ; 0x10 cmp r_Q, 0 ; Is sel = 0? je _mfc0_r16_q_0 ; If sel = 0... cmp r_Q, 1 ; Is sel = 1? je _mfc0_r16_q_1 ; If sel = 1... jmp _mfc0_unknown ; Unknown sel _mfc0_r16_q_0: mov TMP, 0x80008082 ; return 0x80008082 jmp _mfc0_writeback ; Done _mfc0_r16_q_1: mov TMP, 0x1e190c8a ; return 0x1e190c8a jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r17: ; 0x11 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r18: ; 0x12 xor TMP, TMP ; TMP = 0 jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r19: ; 0x13 xor TMP, TMP ; TMP = 0 jmp _mfc0_writeback ; Done ;----------------------------------------------------------------------------- _mfc0_r20: ; 0x14 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r21: ; 0x15 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r22: ; 0x16 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r23: ; 0x17 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r24: ; 0x18 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r25: ; 0x19 jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r26: ; 0x1a jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r27: ; 0x1b jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r28: ; 0x1c jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r29: ; 0x1d jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r30: ; 0x1e jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_r31: ; 0x1f jmp _mfc0_unknown ;----------------------------------------------------------------------------- _mfc0_writeback: ; Write result and go to next cycle Wr_Reg rT, TMP ; Regs[rT] := TMP (result) jmp _end_cycle ; Fin ;----------------------------------------------------------------------------- _mfc0_unknown: ; 'The results are UNDEFINED if coprocessor 0 does not contain a ; register as specified by rd and sel.' ACHTUNG "Unknown CP0 Reg Selector in MFC0!" ;; TODO: print detail jmp _end_cycle ; Do nothing, carry on. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MTC0 - Move to Coprocessor 0. ; Move the contents of a general register to a coprocessor 0 register. ; The contents of general register rt are loaded into the coprocessor 0 ; register specified by the combination of rd and sel (q). Not all ; coprocessor 0 registers support the the sel field. In those instances, the ; sel field must be set to zero. ; Operation: CPR[0, rD, q] = $t ; Syntax: mfc0 $t, $d, q ; Encoding: 0100 0000 100t tttt dddd d000 0000 0qqq ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_mtc0: CPType ; Load Q, rD, rT (ecx, eax, ebx) mov rT, R(rT) ; ebx := Regs[rT] JTABLE eax, _MTC0_Table ; Dispatch on rD via MTC0 Table. ;; We continue in _mtc0_rXX where XX is rD. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; MTC0 Cases. Parameters: Q (ecx), rD (eax), Regs[rT] (ebx) ;----------------------------------------------------------------------------- _mtc0_r00: ; 0x00 test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: mov eax, Sr(CP0_Index) ; eax := CP0_Index and ebx, 0xF ; T := T & 0xF and eax, 0x80000000 ; eax := eax & 0x80000000 or eax, ebx ; eax := eax | T mov Sr(CP0_Index), eax ; CP0_Index := eax jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r01: ; 0x01 jmp _mtc0_unknown ;----------------------------------------------------------------------------- _mtc0_r02: ; 0x02 and ebx, 0x3FFFFFF ; T := T & 0x3FFFFFF mov Sr(CP0_EntryLo0), ebx ; CP0_EntryLo0 := T jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r03: ; 0x03 and ebx, 0x3FFFFFF ; T := T & 0x3FFFFFF mov Sr(CP0_EntryLo1), ebx ; CP0_EntryLo1 := T jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r04: ; 0x04 %define CONTEXTMASK 0xFF800000 %define nCONTEXTMASK (0xFFFFFFFF ^ 0xFF800000) mov eax, Sr(CP0_Context) ; eax := CP0_Context and ebx, CONTEXTMASK ; T := T & CONTEXTMASK and eax, nCONTEXTMASK ; eax := eax & ~CONTEXTMASK or eax, ebx ; eax := eax | T mov Sr(CP0_Context), eax ; CP0_Context := eax jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r05: ; 0x05 test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: test ebx, ebx ; T != 0 ? jnz _mtc0_r05_untest_pgmask ; If so, eggog and ebx, 0x1FFE000 ; T := T & 0x1FFE000 mov Sr(CP0_PageMask), ebx ; CP0_PageMask := T jmp _end_cycle ; Done _mtc0_r05_untest_pgmask: ; Proper kernel won't do this. But if someone does: ACHTUNG "MTC0: Unsupported Page Mask!" ; maybe halt w/ sirens? jmp _end_cycle ; Let's continue (probably wedged...) ;----------------------------------------------------------------------------- _mtc0_r06: ; 0x06 test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: and ebx, 0xF ; T := T & 0xF mov Sr(CP0_Wired), ebx ; CP0_Wired := T jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r07: ; 0x07 jmp _mtc0_unknown ;----------------------------------------------------------------------------- _mtc0_r08: ; 0x08 jmp _mtc0_unknown ;----------------------------------------------------------------------------- _mtc0_r09: ; 0x09 test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: mov CP0_Count, ebx ; CP0_Count := T ('fast reg') jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r10: ; 0x0a test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: and ebx, ~0x1F00 ; T := T & ~0x1F00 mov Sr(CP0_EntryHi), ebx ; CP0_EntryHi := T jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r11: ; 0x0b test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: ClrIRQ TIMER_IRQ ; Clear MIPS Timer IRQ mov CP0_Compare, ebx ; CP0_Compare := T ('fast reg') jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r12: ; 0x0c test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: %define STATUSMASK 0x7D7CFF17 mov eax, CP0_Status ; eax := CP0_Status and ebx, STATUSMASK ; T := T & STATUSMASK and eax, ~STATUSMASK ; eax := eax & ~STATUSMASK or eax, ebx ; eax := eax | T mov CP0_Status, eax ; CP0_Status := eax jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r13: ; 0x0d test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: %define CAUSEMASK ((1 << 23) | (1 << 22) | (255 << 8)) mov eax, CP0_Cause ; eax := CP0_Cause and ebx, CAUSEMASK ; T := T & CAUSEMASK and eax, ~CAUSEMASK ; eax := eax & ~CAUSEMASK or eax, ebx ; eax := eax | T mov CP0_Cause, eax ; CP0_Cause := eax jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r14: ; 0x0e test ecx, ecx ; Sel != 0 ? jnz _mtc0_unknown ; ... then unknown; else: mov Sr(CP0_Epc), ebx ; CP0_Epc := T jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r15: ; 0x0f jmp _mtc0_unknown ;----------------------------------------------------------------------------- _mtc0_r16: ; 0x10 jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r17: ; 0x11 jmp _mtc0_unknown ;----------------------------------------------------------------------------- _mtc0_r18: ; 0x12 jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r19: ; 0x13 jmp _end_cycle ; Done ;----------------------------------------------------------------------------- _mtc0_r20: ; 0x14 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r21: ; 0x15 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r22: ; 0x16 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r23: ; 0x17 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r24: ; 0x18 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r25: ; 0x19 jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r26: ; 0x1a jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r27: ; 0x1b jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r28: ; 0x1c jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r29: ; 0x1d jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r30: ; 0x1e jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_r31: ; 0x1f jmp _mtc0_unknown ; Done ;----------------------------------------------------------------------------- _mtc0_unknown: ; 'The results are UNDEFINED if coprocessor 0 does not contain a ; register as specified by rd and sel.' ACHTUNG "Unknown CP0 Reg Selector in MTC0!" ;; TODO: print detail jmp _end_cycle ; Done ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; WAIT - Enter Standby Mode. ; Wait for Event. ; Puts the emulator into 'wait' mode. ; Encoding: 0100 001- ---- ---- ---- ---- --10 0000 ; PRIVILEGED (permitted in Kernel Mode only.) ;----------------------------------------------------------------------------- align GRAIN, db 0x90 _m_wait: ; no fields Flg_On Waiting ; Set 'Waiting' Flag. jmp _end_cycle ;-----------------------------------------------------------------------------