raw
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 ;-----------------------------------------------------------------------------
m_genesis.kv 20 ; MIPS Processor State.
m_genesis.kv 21 ; Note: PC, nPC, CP0_Status, CP0_Cause, CP0_Compare, are housed in x86 regs.
m_genesis.kv 22 struc MCPU
m_genesis.kv 23 .Regs resd 32 ; The standard MIPS Register Set
m_genesis.kv 24 .LO resd 1 ; Multiplication/division results - Low Half
m_genesis.kv 25 .HI resd 1 ; Multiplication/division results - High Half
m_genesis.kv 26 .CP0_Index resd 1 ; Index into the TLB array
m_genesis.kv 27 .CP0_EntryHi resd 1 ; High-order portion of the TLB entry
m_genesis.kv 28 .CP0_EntryLo0 resd 1 ; Low portion of TLB entry for even-#'d pages
m_genesis.kv 29 .CP0_EntryLo1 resd 1 ; Low portion of TLB entry for odd-#'d pages
m_genesis.kv 30 .CP0_Context resd 1
m_genesis.kv 31 .CP0_Wired resd 1 ; The number of fixed ('wired') TLB entries
m_genesis.kv 32 .CP0_Epc resd 1 ; Exception program counter return address
m_genesis.kv 33 .CP0_BadVAddr resd 1 ; Addr. of most recent addr.-caused exception
m_genesis.kv 34 .CP0_ErrorEpc resd 1 ; Program counter at last exception
m_genesis.kv 35 .CP0_PageMask resd 1 ; Control variable page sizes in TLB entries
m_genesis.kv 36 ;; The TLB:
m_genesis.kv 37 .TLB_Entries resd TLB_ENTRIES_COUNT ; TLB entries (without PFN)
m_genesis.kv 38 .TLB_PFN_Even resd TLB_ENTRIES_COUNT ; TLB PFN0
m_genesis.kv 39 .TLB_PFN_Odd resd TLB_ENTRIES_COUNT ; TLB PFN1
m_genesis.kv 40 endstruc
m_genesis.kv 41 ;-----------------------------------------------------------------------------
m_genesis.kv 42
m_genesis.kv 43 ;-----------------------------------------------------------------------------
m_genesis.kv 44 ; Refer to the N-th TLB Entry:
m_genesis.kv 45 ;-----------------------------------------------------------------------------
m_genesis.kv 46 %define TLB_E(N) dword [M_Base_32 + MCPU.TLB_Entries + 4 * (N)]
m_genesis.kv 47 ; N-th PFN :
m_genesis.kv 48 %define TLB_PFN_E(N) dword [M_Base_32 + MCPU.TLB_PFN_Even + 4 * (N)]
m_genesis.kv 49 %define TLB_PFN_O(N) dword [M_Base_32 + MCPU.TLB_PFN_Odd + 4 * (N)]
m_genesis.kv 50 ;-----------------------------------------------------------------------------
m_genesis.kv 51
m_genesis.kv 52 ;-----------------------------------------------------------------------------
m_genesis.kv 53 section .bss
m_genesis.kv 54 align GRAIN ; MIPS CPU State
m_genesis.kv 55 MIPS_State resb MCPU_size
m_genesis.kv 56 section .text
m_genesis.kv 57 ;-----------------------------------------------------------------------------
m_genesis.kv 58
m_genesis.kv 59 ;-----------------------------------------------------------------------------
m_genesis.kv 60 ; Global 'fast' MIPS State:
m_genesis.kv 61 ; TODO: is it possible to use the upper halves of the 64bit regs for anything?
m_genesis.kv 62 ; ... or entirely worthless from intel's idiocy of 'auto-zero on mov' ?
m_genesis.kv 63 ;-----------------------------------------------------------------------------
m_genesis.kv 64 %define Flag_Reg edi ; Delay, Exception, etc flags
m_genesis.kv 65 %define RAM_Floor rsi ; Physical (x86) address of 1st RAM word
m_genesis.kv 66 %define RAM_Ceiling r8 ; Physical (x86) address of last RAM word
m_genesis.kv 67 %define PC r9d ; Current Program Counter
m_genesis.kv 68 %define nPC r10d ; 'Next' Program Counter
m_genesis.kv 69 %define CP0_Status r11d ; Processor status and control
m_genesis.kv 70 %define CP0_Cause r12d ; Cause of last general exception
m_genesis.kv 71 %define CP0_Count r13d ; Processor cycle count
m_genesis.kv 72 %define CP0_Compare r14d ; Timer interrupt control
m_genesis.kv 73 %define AUX r15d ; Additional TMP for certain ops
m_genesis.kv 74
m_genesis.kv 75 ; TODO: 'Suspend to RAM' routine for all of the above.
m_genesis.kv 76 ;-----------------------------------------------------------------------------
m_genesis.kv 77
m_genesis.kv 78 ;-----------------------------------------------------------------------------
m_genesis.kv 79 ; Access to MIPS Registers that live in MCPU (Emulator State) :
m_genesis.kv 80 ;-----------------------------------------------------------------------------
m_genesis.kv 81 ; Refer to given MIPS special Reg:
m_genesis.kv 82 ;-----------------------------------------------------------------------------
m_genesis.kv 83 %define Sr(N) dword [M_Base_32 + MCPU. %+ N]
m_genesis.kv 84 ;-----------------------------------------------------------------------------
m_genesis.kv 85 ; Refer to Nth Reg:
m_genesis.kv 86 ;-----------------------------------------------------------------------------
m_genesis.kv 87 %define R(N) Sr(Regs + 4 * (N))
m_genesis.kv 88 ;-----------------------------------------------------------------------------
m_genesis.kv 89
m_genesis.kv 90 ;-----------------------------------------------------------------------------
m_genesis.kv 91 ; Update given MIPS Reg # with new value, but always avoid overwriting R(0)
m_genesis.kv 92 ;-----------------------------------------------------------------------------
m_genesis.kv 93 ; TODO: measure if this is actually faster than simply R(31) := 0 every time
m_genesis.kv 94 %macro Wr_Reg 2 ; params: %1: Reg # %2: PC reg with new value
m_genesis.kv 95 xor AUX, AUX ; Clear AUX
m_genesis.kv 96 test %1, %1 ; Set Z if destination reg # is R(0)
m_genesis.kv 97 cmovz %2, AUX ; If Z: Replace written value with zero
m_genesis.kv 98 mov R(%1), %2 ; Regs[rD] := new value
m_genesis.kv 99 ;;;; alt variant:
m_genesis.kv 100 ; mov R(%1), %2 ; Regs[rD] := new value
m_genesis.kv 101 ; mov R(0), 0
m_genesis.kv 102 ;;;; TODO: which is actually faster ?
m_genesis.kv 103 %endmacro
m_genesis.kv 104 ;-----------------------------------------------------------------------------
m_genesis.kv 105
m_genesis.kv 106 ;-----------------------------------------------------------------------------
m_genesis.kv 107 ; Init MIPS CPU:
m_genesis.kv 108 ;-----------------------------------------------------------------------------
m_genesis.kv 109 _cpu_reset:
m_genesis.kv 110 xor eax, eax ; eax := 0
m_genesis.kv 111 mov AUX, eax ; Clear AUX register
m_genesis.kv 112 mov M_Base_64, MIPS_State ; Set RBP to point to MIPS CPU State
m_genesis.kv 113 ;; Init 'fast' MIPS Regs:
m_genesis.kv 114 mov PC, INIT_PC
m_genesis.kv 115 mov nPC, eax
m_genesis.kv 116 mov CP0_Status, eax
m_genesis.kv 117 mov CP0_Cause, eax
m_genesis.kv 118 mov CP0_Count, eax
m_genesis.kv 119 mov CP0_Compare, eax
m_genesis.kv 120 ;; Init 'slow' MIPS Regs:
m_genesis.kv 121 mov ecx, 0
m_genesis.kv 122 _init_reg:
m_genesis.kv 123 mov R(ecx), eax
m_genesis.kv 124 inc ecx
m_genesis.kv 125 cmp ecx, 32
m_genesis.kv 126 jb _init_reg
m_genesis.kv 127 xor ecx, ecx
m_genesis.kv 128 mov Sr(HI), eax
m_genesis.kv 129 mov Sr(LO), eax
m_genesis.kv 130 mov Sr(CP0_Index), eax
m_genesis.kv 131 mov Sr(CP0_EntryHi), eax
m_genesis.kv 132 mov Sr(CP0_EntryLo0), eax
m_genesis.kv 133 mov Sr(CP0_EntryLo1), eax
m_genesis.kv 134 mov Sr(CP0_Context), eax
m_genesis.kv 135 mov Sr(CP0_Wired), eax
m_genesis.kv 136 mov Sr(CP0_Epc), eax
m_genesis.kv 137 mov Sr(CP0_BadVAddr), eax
m_genesis.kv 138 mov Sr(CP0_ErrorEpc), eax
m_genesis.kv 139 Flg_Clear_All ; Reset all misc Flags to 0
m_genesis.kv 140 bts CP0_Status, CP0St_ERL ; Start in kernel mode w/ unmapped useg
m_genesis.kv 141 ret
m_genesis.kv 142 ;-----------------------------------------------------------------------------