-
+ 93767FBF28AC3CA8A8D7CEA92C2295D7F4A041C9B67B003EDC7CA1A32AE624B423F8F33E5D099403A9E68E794F0F5D90F4F3F2A12E8D3CEE4FCAFB12E7502684
m/mips_cpu.asm
(0 . 0)(1 . 113)
1913 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1914 ;; ;;
1915 ;; This file is part of 'M', a MIPS system emulator. ;;
1916 ;; ;;
1917 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
1918 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
1919 ;; ;;
1920 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
1921 ;; distribute this software ; Should you use this software for any purpose, ;;
1922 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
1923 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
1924 ;; continue doing so for the indefinite future. In any case, please ;;
1925 ;; always : read and understand any software ; verify any PGP signatures ;;
1926 ;; that you use - for any purpose. ;;
1927 ;; ;;
1928 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
1929 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1930
1931 section .text
1932
1933 ;-----------------------------------------------------------------------------
1934 ; Dispatch via rax, given index Register, and given Table (of 32-bit offsets)
1935 ;-----------------------------------------------------------------------------
1936 %macro JTABLE 2 ; %1 : index register, %2 : table offset
1937 mov eax, dword [%2 + 4 * %1]
1938 jmp rax
1939 %endmacro
1940 ;-----------------------------------------------------------------------------
1941
1942 ;----------------------------
1943 ; Start of MIPS CPU Cycle : |
1944 ;-----------------------------------------------------------------------------
1945 _wait_cycle:
1946 _cycle:
1947 inc CP0_Count ; Timer: CP0_Count := CP0_Count + 1
1948
1949 ;; Timer Interrupt
1950 cmp CP0_Count, CP0_Compare ; Has timer reached limit?
1951 jne _cycle_no_mips_timer ; If not, do not invoke interrupt
1952 SetIRQ TIMER_IRQ ; Timer reached limit, invoke timer IRQ
1953
1954 _cycle_no_mips_timer:
1955
1956 ;; Test if Interrupts are Disabled:
1957 bt CP0_Status, CP0St_IE ; CF := CP0St_IE
1958 jnc _cycle_no_irq ; If 0, IRQs are disabled, go to no_irq
1959 test CP0_Status, (1 << CP0St_ERL) | (1 << CP0St_EXL) ; If ERL/EXL:
1960 jnz _cycle_no_irq ; ... then also interrupts are disabled
1961
1962 GetSlaveIRQ ; See if slave threw interrupt
1963
1964 ;; Interrupts are Enabled; handle any pending Interrupt:
1965 mov eax, 0xFC00 ; ( 0xFC00 &
1966 and eax, CP0_Cause ; CP0_Cause &
1967 and eax, CP0_Status ; CP0_Status )
1968 jz _cycle_no_irq ; == 0 ? Then no pending IRQ, go to no_irq.
1969
1970 ;; If here, there is a pending interrupt, service it:
1971 _cycle_irq_handler:
1972
1973 Flg_Off Waiting ; Clear Waiting Flag
1974 SetEXC EXC_Int ; Set the EXC_Int Exception Code
1975
1976 ;; Copy InDelaySlot Flag to RunningDelaySlot Flag:
1977 Flg_Cpy RunningDelaySlot, InDelaySlot
1978
1979 jmp _Handle_Exception ; Handle exception and end cycle.
1980
1981 _cycle_no_irq: ; If ints disabled or none pending
1982
1983 Flg_Get Waiting ; CF := Waiting Flag
1984 jc _wait_cycle ; If Waiting, start next cycle, else:
1985
1986 ;; Copy InDelaySlot Flag to RunningDelaySlot Flag:
1987 Flg_Cpy RunningDelaySlot, InDelaySlot
1988
1989 ;; Fetch the instruction to execute:
1990 mov eax, PC ; vAddr := PC
1991 call _Virt_Read_Word ; EAX := MEM[Virt2Phys(PC)]
1992 mov r_I, eax ; Store fetched instruction
1993
1994 ;; Dispatch the current instruction:
1995 mov eax, r_I ; Get the original instruction :
1996
1997 ;; 'Accelerated NOPs'
1998 test eax, eax ; Is the current instruction null?
1999 jnz _not_nop ; ... if so, skip dispatch entirely!
2000 jmp _end_cycle ; go to tail of this cycle
2001 _not_nop: ; If not a NOP:
2002
2003 shr eax, 26 ; Get I-field (upper 6 bits of instr) ;
2004 JTABLE eax, _I_Table ; Dispatch on I-field via I-Table.
2005 ;;; Instruction executes, after which goes to _end_cycle
2006 ;-----------------------------------------------------------------------------
2007
2008 ;---------------------------------
2009 ; Tail End of a MIPS CPU Cycle : |
2010 ;-----------------------------------------------------------------------------
2011 _end_cycle:
2012 Flg_GOF RunningDelaySlot ; Were we running the delay slot?
2013 jnc _end_cycle_was_not_in_delay_slot ; if not, skip, else:
2014 ;; We WERE running in the delay slot:
2015 _end_cycle_was_in_delay_slot: ; If we were running the delay slot:
2016 mov PC, nPC ; PC := nPC
2017 Flg_Off InDelaySlot ; Clear the InDelaySlot Flag
2018 jmp _cycle ; Go to next cycle without advancing PC
2019 _end_cycle_was_not_in_delay_slot: ; If we were NOT running the delay slot:
2020 add PC, 0x4 ; PC := PC + 4
2021 ;; Test for Shutdown Condition:
2022 Flg_Get Shutdown ; CF := Shutdown Flag
2023 jc _shutdown ; ... if CF, then shut down.
2024 jmp _cycle ; ... otherwise, go to next cycle.
2025 ;-----------------------------------------------------------------------------