m_genesis.kv 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 2 ;; ;;
m_genesis.kv 3 ;; This file is part of 'M', a MIPS system emulator. ;;
m_genesis.kv 4 ;; ;;
m_genesis.kv 5 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
m_genesis.kv 6 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
m_genesis.kv 7 ;; ;;
m_genesis.kv 8 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
m_genesis.kv 9 ;; distribute this software ; Should you use this software for any purpose, ;;
m_genesis.kv 10 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
m_genesis.kv 11 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
m_genesis.kv 12 ;; continue doing so for the indefinite future. In any case, please ;;
m_genesis.kv 13 ;; always : read and understand any software ; verify any PGP signatures ;;
m_genesis.kv 14 ;; that you use - for any purpose. ;;
m_genesis.kv 15 ;; ;;
m_genesis.kv 16 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
m_genesis.kv 17 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 18
m_genesis.kv 19 section .text
m_genesis.kv 20
m_genesis.kv 21 ;-----------------------------------------------------------------------------
m_genesis.kv 22 ; Get the current Exception Code, write to the specified destination
m_genesis.kv 23 ;-----------------------------------------------------------------------------
m_genesis.kv 24 %macro GetEXC 1 ; param is destination to write the exception code
m_genesis.kv 25 mov %1, CP0_Cause ; Dest := CP0_Cause
m_genesis.kv 26 shr %1, 2 ; Dest := Dest >> 2
m_genesis.kv 27 and %1, 0x1F ; Dest := Dest & 0x1F
m_genesis.kv 28 %endmacro
m_genesis.kv 29 ;-----------------------------------------------------------------------------
m_genesis.kv 30
m_genesis.kv 31 ;-----------------------------------------------------------------------------
m_genesis.kv 32 ; Set the current Exception Code from the given constant
m_genesis.kv 33 ;-----------------------------------------------------------------------------
m_genesis.kv 34 %macro SetEXC 1 ; param is the exception code to set
m_genesis.kv 35 and CP0_Cause, ~(0x1F << 2) ; Clear the current Exception Code
m_genesis.kv 36 or CP0_Cause, (%1 & 0x1F) << 2 ; set the new one
m_genesis.kv 37 %endmacro
m_genesis.kv 38 ;-----------------------------------------------------------------------------
m_genesis.kv 39
m_genesis.kv 40 ;------------------------------
m_genesis.kv 41 ; Exception (and IRQ) Handler |
m_genesis.kv 42 ;-----------------------------------------------------------------------------
m_genesis.kv 43 _Handle_Exception:
m_genesis.kv 44 Flg_Off InDelaySlot ; Clear the InDelaySlot Flag
m_genesis.kv 45 bt CP0_Status, CP0St_EXL ; CF := EXL
m_genesis.kv 46 jc _H_Exc_Off_Is_180 ; If EXL is 1, Offset := 0x180; else:
m_genesis.kv 47 ;; EXL is 0:
m_genesis.kv 48 mov Sr(CP0_Epc), PC ; CP0_Epc := PC
m_genesis.kv 49 Flg_Get RunningDelaySlot ; Are we running the delay slot?
m_genesis.kv 50 jnc _H_Exc_Not_R_Delay ; If yes, then skip, else:
m_genesis.kv 51 _H_Exc_R_Delay: ; We ARE running the delay slot:
m_genesis.kv 52 sub Sr(CP0_Epc), 0x4 ; CP0_Epc := CP0_Epc - 0x4
m_genesis.kv 53 bts CP0_Cause, CP0Cau_BD ; Set BD Flag in CP0_Cause
m_genesis.kv 54 jmp _H_Exc_Test_TLB ; Proceed to test for TLBism
m_genesis.kv 55 _H_Exc_Not_R_Delay: ; We are NOT running the delay slot:
m_genesis.kv 56 btr CP0_Cause, CP0Cau_BD ; Clear BD Flag in CP0_Cause
m_genesis.kv 57 _H_Exc_Test_TLB:
m_genesis.kv 58 ;; Test whether this was a TLB Exception:
m_genesis.kv 59 GetEXC eax ; EAX := the current exception code
m_genesis.kv 60 cmp eax, EXC_TLBL ; was it EXC_TLBL ?
m_genesis.kv 61 je __H_Exc_Was_TLB ; ... if yes, go to H_Exc_Was_TLB
m_genesis.kv 62 cmp eax, EXC_TLBS ; was it EXC_TLBS ?
m_genesis.kv 63 je __H_Exc_Was_TLB ; ... if yes, go to H_Exc_Was_TLB
m_genesis.kv 64 ;; This was NOT a TLB Exception:
m_genesis.kv 65 cmp eax, EXC_Int ; was code EXC_Int ?
m_genesis.kv 66 jne _H_Exc_Off_Is_180 ; if not, Offset := 0x180
m_genesis.kv 67 bt CP0_Cause, CP0Cau_IV ; Was CP0_Cause bit 23 (IV) zero?
m_genesis.kv 68 jnc _H_Exc_Off_Is_180 ; if was zero, Offset := 0x180
m_genesis.kv 69 ;; If CP0_Cause bit 23 != 0: Offset := 0x200
m_genesis.kv 70 mov eax, 0x200 ; Offset := 0x200
m_genesis.kv 71 jmp _H_Exc_Have_Offset ; Go to H_Exc_Have_Offset
m_genesis.kv 72 __H_Exc_Was_TLB: ; This WAS a TLB Exception:
m_genesis.kv 73 Flg_Get ExcWasTLBNoMatch ; CF := 'TLB No Match'
m_genesis.kv 74 ;; TODO: in 'cmips', this case was reversed? why?
m_genesis.kv 75 ;; For now, we'll do likewise:
m_genesis.kv 76 jnc _H_Exc_Off_Is_180 ; ... if 0, Offset := 0x180
m_genesis.kv 77 ;; Else: Offset := 0x0
m_genesis.kv 78 xor eax, eax ; Clear EAX (Offset := 0)
m_genesis.kv 79 jmp _H_Exc_Have_Offset ; Finish up
m_genesis.kv 80 _H_Exc_Off_Is_180: ; Offset := 0x180
m_genesis.kv 81 mov eax, 0x180 ; Set the Offset
m_genesis.kv 82 _H_Exc_Have_Offset: ; We finished calculating the Offset:
m_genesis.kv 83 bts CP0_Status, CP0St_EXL ; Set the EXL Flag
m_genesis.kv 84 mov PC, eax ; PC := Offset (eax)
m_genesis.kv 85 mov eax, 0x80000000 ; Base that will be used if BEV=0
m_genesis.kv 86 mov ebx, 0xBFC00200 ; Base that will be used if BEV=1
m_genesis.kv 87 bt CP0_Status, CP0St_BEV ; CF := the BEV Flag
m_genesis.kv 88 cmovc eax, ebx ; If CF = 1, use the BEV=1 Base
m_genesis.kv 89 add PC, eax ; PC := PC + Base
m_genesis.kv 90 ;; Done handling exception
m_genesis.kv 91 jmp _cycle ; Start next cycle.
m_genesis.kv 92 ;-----------------------------------------------------------------------------