;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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 . ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text ;----------------------------------------------------------------------------- ; Get the current Exception Code, write to the specified destination ;----------------------------------------------------------------------------- %macro GetEXC 1 ; param is destination to write the exception code mov %1, CP0_Cause ; Dest := CP0_Cause shr %1, 2 ; Dest := Dest >> 2 and %1, 0x1F ; Dest := Dest & 0x1F %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Set the current Exception Code from the given constant ;----------------------------------------------------------------------------- %macro SetEXC 1 ; param is the exception code to set and CP0_Cause, ~(0x1F << 2) ; Clear the current Exception Code or CP0_Cause, (%1 & 0x1F) << 2 ; set the new one %endmacro ;----------------------------------------------------------------------------- ;------------------------------ ; Exception (and IRQ) Handler | ;----------------------------------------------------------------------------- _Handle_Exception: Flg_Off InDelaySlot ; Clear the InDelaySlot Flag bt CP0_Status, CP0St_EXL ; CF := EXL jc _H_Exc_Off_Is_180 ; If EXL is 1, Offset := 0x180; else: ;; EXL is 0: mov Sr(CP0_Epc), PC ; CP0_Epc := PC Flg_Get RunningDelaySlot ; Are we running the delay slot? jnc _H_Exc_Not_R_Delay ; If yes, then skip, else: _H_Exc_R_Delay: ; We ARE running the delay slot: sub Sr(CP0_Epc), 0x4 ; CP0_Epc := CP0_Epc - 0x4 bts CP0_Cause, CP0Cau_BD ; Set BD Flag in CP0_Cause jmp _H_Exc_Test_TLB ; Proceed to test for TLBism _H_Exc_Not_R_Delay: ; We are NOT running the delay slot: btr CP0_Cause, CP0Cau_BD ; Clear BD Flag in CP0_Cause _H_Exc_Test_TLB: ;; Test whether this was a TLB Exception: GetEXC eax ; EAX := the current exception code cmp eax, EXC_TLBL ; was it EXC_TLBL ? je __H_Exc_Was_TLB ; ... if yes, go to H_Exc_Was_TLB cmp eax, EXC_TLBS ; was it EXC_TLBS ? je __H_Exc_Was_TLB ; ... if yes, go to H_Exc_Was_TLB ;; This was NOT a TLB Exception: cmp eax, EXC_Int ; was code EXC_Int ? jne _H_Exc_Off_Is_180 ; if not, Offset := 0x180 bt CP0_Cause, CP0Cau_IV ; Was CP0_Cause bit 23 (IV) zero? jnc _H_Exc_Off_Is_180 ; if was zero, Offset := 0x180 ;; If CP0_Cause bit 23 != 0: Offset := 0x200 mov eax, 0x200 ; Offset := 0x200 jmp _H_Exc_Have_Offset ; Go to H_Exc_Have_Offset __H_Exc_Was_TLB: ; This WAS a TLB Exception: Flg_Get ExcWasTLBNoMatch ; CF := 'TLB No Match' ;; TODO: in 'cmips', this case was reversed? why? ;; For now, we'll do likewise: jnc _H_Exc_Off_Is_180 ; ... if 0, Offset := 0x180 ;; Else: Offset := 0x0 xor eax, eax ; Clear EAX (Offset := 0) jmp _H_Exc_Have_Offset ; Finish up _H_Exc_Off_Is_180: ; Offset := 0x180 mov eax, 0x180 ; Set the Offset _H_Exc_Have_Offset: ; We finished calculating the Offset: bts CP0_Status, CP0St_EXL ; Set the EXL Flag mov PC, eax ; PC := Offset (eax) mov eax, 0x80000000 ; Base that will be used if BEV=0 mov ebx, 0xBFC00200 ; Base that will be used if BEV=1 bt CP0_Status, CP0St_BEV ; CF := the BEV Flag cmovc eax, ebx ; If CF = 1, use the BEV=1 Base add PC, eax ; PC := PC + Base ;; Done handling exception jmp _cycle ; Start next cycle. ;-----------------------------------------------------------------------------