Make a fake-asm macro for (mips) assembly we want to show but not use + some other fixes (#277)

* use new fake-asm macro

* [timer] update some docs and code for clarity

* Fix typos

* uncomment "sync" instructions

* some decimal to hex

* move fake-asm's to gcommon

* [timer] document timer-mode more.

* Fix errors

* i dont like this
This commit is contained in:
ManDude 2021-02-22 06:02:12 +00:00 committed by GitHub
parent 4b1b7e9507
commit b92a2823bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 120 additions and 93 deletions

View file

@ -1934,17 +1934,26 @@
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
(deftype timer-mode (uint32) (deftype timer-mode (uint32)
(;(data uint32 :offset 0 :size 32) (;; clock selection:
;; 0: BUSCLK
;; 1: BUSCLK/16
;; 2: BUSCLK/256
;; 3: hblank
(clks uint8 :offset 0 :size 2) (clks uint8 :offset 0 :size 2)
(gate uint8 :offset 2 :size 1) (gate uint8 :offset 2 :size 1) ;; gate function enable
(gats uint8 :offset 3 :size 1) (gats uint8 :offset 3 :size 1) ;; gate selection: 0 = hblank, 1 = vblank
;; gate mode:
;; 0: count while gate signal is low
;; 1: start when gate signal rises
;; 2: start when gate signal falls
;; 3: start when gate signal rises/falls
(gatm uint8 :offset 4 :size 2) (gatm uint8 :offset 4 :size 2)
(zret uint8 :offset 6 :size 1) (zret uint8 :offset 6 :size 1) ;; zero return: clear counter when equal to reference value
(cue uint8 :offset 7 :size 1) (cue uint8 :offset 7 :size 1) ;; count-up enable
(cmpe uint8 :offset 8 :size 1) (cmpe uint8 :offset 8 :size 1) ;; compare-interrupt enable
(ovfe uint8 :offset 9 :size 1) (ovfe uint8 :offset 9 :size 1) ;; overflow-interrupt enable
(equf uint8 :offset 10 :size 1) (equf uint8 :offset 10 :size 1) ;; equal-flag
(ovff uint8 :offset 11 :size 1) (ovff uint8 :offset 11 :size 1) ;; overflow-flag
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4
@ -2022,12 +2031,12 @@
(define-extern timer-count (function timer-bank uint)) (define-extern timer-count (function timer-bank uint))
(define-extern disable-irq (function none)) (define-extern disable-irq (function none))
(define-extern enable-irq (function none)) (define-extern enable-irq (function none))
(define-extern stopwatch-init (function stopwatch none)) (define-extern stopwatch-init (function stopwatch int))
(define-extern stopwatch-reset (function stopwatch none)) (define-extern stopwatch-reset (function stopwatch int))
(define-extern stopwatch-start (function stopwatch none)) (define-extern stopwatch-start (function stopwatch int))
(define-extern stopwatch-stop (function stopwatch none)) (define-extern stopwatch-stop (function stopwatch uint))
(define-extern stopwatch-begin (function stopwatch none)) (define-extern stopwatch-begin (function stopwatch int))
(define-extern stopwatch-end (function stopwatch none)) (define-extern stopwatch-end (function stopwatch uint))
(define-extern stopwatch-elapsed-ticks (function stopwatch uint)) (define-extern stopwatch-elapsed-ticks (function stopwatch uint))
(define-extern stopwatch-elapsed-seconds (function stopwatch float)) (define-extern stopwatch-elapsed-seconds (function stopwatch float))

View file

@ -19,7 +19,7 @@
;; Each bucket contains: ;; Each bucket contains:
;; a tag, (64-bits), to point to the chain of the bucket ;; a tag, (64-bits), to point to the chain of the bucket
;; last, a pointer to the last tag of this bucket, so the bucket can be patched to point to the next. ;; last, a pointer to the last tag of this bucket, so that the bucket can be patched to point to the next.
(defun dma-buffer-add-buckets ((dma-buf dma-buffer) (count int)) (defun dma-buffer-add-buckets ((dma-buf dma-buffer) (count int))
"Add count buckets to the dma buffer. Each bucket is initialized empty." "Add count buckets to the dma buffer. Each bucket is initialized empty."

View file

@ -117,7 +117,7 @@
(defun dma-buffer-add-vu-function ((dma-buf dma-buffer) (vu-func vu-function) (arg2 int)) (defun dma-buffer-add-vu-function ((dma-buf dma-buffer) (vu-func vu-function) (arg2 int))
"Add DMA chain instructions to load the given VU function to VU program memory. "Add DMA chain instructions to load the given VU function to VU program memory.
The destination address in VU memory is specified inside of the vu-function. The destination address in VU memory is specified inside of the vu-function.
if arg2 = 0, then use FLUSHE, otherwise use FLUSHA, I think the runs _before_ the program upload. if arg2 = 0, then use FLUSHE, otherwise use FLUSHA, I think it runs _before_ the program upload.
Should run with TTE." Should run with TTE."
(local-vars (local-vars
(func-ptr uint) (func-ptr uint)

View file

@ -59,21 +59,21 @@
Like dma-send-no-scratch, this sets chcr to zero, which may be undesirable." Like dma-send-no-scratch, this sets chcr to zero, which may be undesirable."
(dma-sync (the-as pointer arg0) 0 0) (dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0) (flush-cache 0)
;;(.sync.l) (.sync.l)
(set! (-> arg0 madr) (set! (-> arg0 madr)
(logior (logand #xfffffff (the-as int madr)) ;; lower 28 bits are untouched (logior (logand #xfffffff (the-as int madr)) ;; lower 28 bits are untouched
;; if we are transferring to the scratchpad (at 70000000) ;; if we are transferring to the scratchpad (at 70000000)
;; we should set bit 31 in madr, per the manual. ;; we should set bit 31 in madr, per the manual.
(if (= (logand #x70000000 (the-as int madr)) #x70000000) (if (= (logand #x70000000 (the-as int madr)) #x70000000)
(shl 32768 16) ;; set bit 31 (shl #x8000 16) ;; set bit 31
0) 0)
) )
) )
(set! (-> arg0 qwc) qwc) (set! (-> arg0 qwc) qwc)
;(.sync.l) (.sync.l)
;; set str! ;; set str!
(set! (-> arg0 chcr) (new 'static 'dma-chcr :str 1)) (set! (-> arg0 chcr) (new 'static 'dma-chcr :str 1))
;(.sync.l) (.sync.l)
(none) (none)
) )
@ -81,17 +81,17 @@
"Send DMA! tadr should be a tag address, possibly in spad ram." "Send DMA! tadr should be a tag address, possibly in spad ram."
(dma-sync (the-as pointer arg0) 0 0) (dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0) (flush-cache 0)
;(.sync.l) (.sync.l)
(set! (-> arg0 qwc) 0) (set! (-> arg0 qwc) 0)
;; adjust address ;; adjust address
(set! (-> arg0 tadr) (set! (-> arg0 tadr)
(logior (logand 268435455 (the-as int tadr)) (logior (logand #xfffffff (the-as int tadr))
(if (= (logand 1879048192 (the-as int tadr)) 1879048192) (if (= (logand #x70000000 (the-as int tadr)) #x70000000)
(shl 32768 16) (shl #x8000 16)
0) 0)
) )
) )
;(.sync.l) (.sync.l)
;;(set! (-> arg0 chcr) 325) ;;(set! (-> arg0 chcr) 325)
(set! (-> arg0 chcr) (set! (-> arg0 chcr)
(new 'static 'dma-chcr (new 'static 'dma-chcr
@ -100,7 +100,7 @@
:tte 1 ;; send tags :tte 1 ;; send tags
:str 1) ;; go! :str 1) ;; go!
) )
;(.sync.l) (.sync.l)
(none) (none)
) )
@ -108,19 +108,19 @@
"Send DMA chain! TTE bit is not set, don't transfer tags." "Send DMA chain! TTE bit is not set, don't transfer tags."
(dma-sync (the-as pointer arg0) 0 0) (dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0) (flush-cache 0)
;;(.sync.l) (.sync.l)
(set! (-> arg0 qwc) 0) (set! (-> arg0 qwc) 0)
(set! (set!
(-> arg0 tadr) (-> arg0 tadr)
(logior (logior
(logand 268435455 (the-as int arg1)) (logand #xfffffff (the-as int arg1))
(the-as (the-as
uint uint
(if (= (logand 1879048192 (the-as int arg1)) 1879048192) (shl 32768 16) 0) (if (= (logand #x70000000 (the-as int arg1)) #x70000000) (shl #x8000 16) 0)
) )
) )
) )
;;(.sync.l) (.sync.l)
(set! (-> arg0 chcr) (set! (-> arg0 chcr)
(new 'static 'dma-chcr (new 'static 'dma-chcr
:dir 1 ;; from memory :dir 1 ;; from memory
@ -128,7 +128,7 @@
:tte 0 ;; no tags :tte 0 ;; no tags
:str 1) ;; go! :str 1) ;; go!
) )
;;(.sync.l) (.sync.l)
(none) (none)
) )
@ -141,14 +141,14 @@
(set! (set!
(-> arg0 tadr) (-> arg0 tadr)
(logior (logior
(logand 268435455 (the-as int arg1)) (logand #xfffffff (the-as int arg1))
(the-as (the-as
uint uint
(if (= (logand 1879048192 (the-as int arg1)) 1879048192) (shl 32768 16) 0) (if (= (logand #x70000000 (the-as int arg1)) #x70000000) (shl #x8000 16) 0)
) )
) )
) )
;;(.sync.l) (.sync.l)
;;(set! (-> arg0 chcr) 325) ;;(set! (-> arg0 chcr) 325)
(set! (-> arg0 chcr) (set! (-> arg0 chcr)
(new 'static 'dma-chcr (new 'static 'dma-chcr
@ -157,7 +157,7 @@
:tte 1 :tte 1
:str 1) :str 1)
) )
;;(.sync.l) (.sync.l)
(set! v0-1 0) (set! v0-1 0)
(none) (none)
) )
@ -169,12 +169,12 @@
(dma-sync (the-as pointer s5-0) 0 0) (dma-sync (the-as pointer s5-0) 0 0)
(flush-cache 0) (flush-cache 0)
(.sync.l) (.sync.l)
(set! (-> s5-0 madr) (logand #xFFFFFFF (the-as int madr))) (set! (-> s5-0 madr) (logand #xfffffff (the-as int madr)))
(set! (-> s5-0 sadr) (logand #xFFFFFFF (the-as int sadr))) (set! (-> s5-0 sadr) (logand #xfffffff (the-as int sadr)))
(set! (-> s5-0 qwc) qwc) (set! (-> s5-0 qwc) qwc)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1)) (set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
(if sync (if sync
(dma-sync (the-as pointer s5-0) 0 0)) (dma-sync (the-as pointer s5-0) 0 0))
(none) (none)
@ -185,13 +185,13 @@
(local-vars (s5-0 dma-bank-spr)) (local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_TO_BANK) (set! s5-0 SPR_TO_BANK)
(dma-sync (the-as pointer s5-0) 0 0) (dma-sync (the-as pointer s5-0) 0 0)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr))) (set! (-> s5-0 madr) (logand #xfffffff (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr))) (set! (-> s5-0 sadr) (logand #xfffffff (the-as int sadr)))
(set! (-> s5-0 qwc) qwc) (set! (-> s5-0 qwc) qwc)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1)) (set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0)) (if sync (dma-sync (the-as pointer s5-0) 0 0))
(none) (none)
) )
@ -202,13 +202,13 @@
(set! s5-0 SPR_FROM_BANK) (set! s5-0 SPR_FROM_BANK)
(dma-sync (the-as pointer s5-0) 0 0) (dma-sync (the-as pointer s5-0) 0 0)
(flush-cache 0) (flush-cache 0)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr))) (set! (-> s5-0 madr) (logand #xfffffff (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr))) (set! (-> s5-0 sadr) (logand #xfffffff (the-as int sadr)))
(set! (-> s5-0 qwc) qwc) (set! (-> s5-0 qwc) qwc)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1)) (set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0)) (if sync (dma-sync (the-as pointer s5-0) 0 0))
(none) (none)
) )
@ -218,13 +218,13 @@
(local-vars (s5-0 dma-bank-spr)) (local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_FROM_BANK) (set! s5-0 SPR_FROM_BANK)
(dma-sync (the-as pointer s5-0) 0 0) (dma-sync (the-as pointer s5-0) 0 0)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr))) (set! (-> s5-0 madr) (logand #xfffffff (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr))) (set! (-> s5-0 sadr) (logand #xfffffff (the-as int sadr)))
(set! (-> s5-0 qwc) qwc) (set! (-> s5-0 qwc) qwc)
;;(.sync.l) (.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1)) (set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0)) (if sync (dma-sync (the-as pointer s5-0) 0 0))
(none) (none)
) )
@ -264,7 +264,7 @@
(defun clear-vu1-mem () (defun clear-vu1-mem ()
"Clear the data memory of VU1, filling it with abadbeef "Clear the data memory of VU1, filling it with abadbeef
This uses the slow memory mapping of VU0's data memory at 0x11004000" This uses the slow memory mapping of VU1's data memory at 0x1100C000"
(local-vars (local-vars
(v1-0 (pointer uint32)) (v1-0 (pointer uint32))
(a0-0 int) (a0-0 int)
@ -371,15 +371,15 @@
) )
(set! qwc-remaining (- qwc-remaining (the-as uint qwc-transferred-now))) (set! qwc-remaining (- qwc-remaining (the-as uint qwc-transferred-now)))
;;(.sync.l) (.sync.l)
;; set up dma ;; set up dma
(set! (-> spr-to-bank madr) (the uint src)) (set! (-> spr-to-bank madr) (the uint src))
(set! (-> spr-to-bank sadr) 0) (set! (-> spr-to-bank sadr) 0)
(set! (-> spr-to-bank qwc) qwc-transferred-now) (set! (-> spr-to-bank qwc) qwc-transferred-now)
;;(.sync.l) (.sync.l)
;; start dma ;; start dma
(set! (-> spr-to-bank chcr) (new 'static 'dma-chcr :str 1)) (set! (-> spr-to-bank chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
;; sync ;; sync
(dma-sync (the-as pointer spr-to-bank) 0 0) (dma-sync (the-as pointer spr-to-bank) 0 0)
@ -391,9 +391,9 @@
(set! (-> spr-from-bank sadr) 0) (set! (-> spr-from-bank sadr) 0)
(set! (-> spr-from-bank qwc) qwc-transferred-now) (set! (-> spr-from-bank qwc) qwc-transferred-now)
;; transfer! ;; transfer!
;;(.sync.l) (.sync.l)
(set! (-> spr-from-bank chcr) (new 'static 'dma-chcr :str 1)) (set! (-> spr-from-bank chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l) (.sync.l)
;; sync! ;; sync!
(dma-sync (the-as pointer spr-from-bank) 0 0) (dma-sync (the-as pointer spr-from-bank) 0 0)
;; advance dst. ;; advance dst.

View file

@ -14,19 +14,27 @@
;; this matches the Tn_MODE register structure of the ps2 EE timers. ;; this matches the Tn_MODE register structure of the ps2 EE timers.
;; Only the lower 32 bits of these registers are usable, and the upper 16 hardwired to zero ;; Only the lower 32 bits of these registers are usable, and the upper 16 hardwired to zero
;; TODO : define constants for these bitfields?
(deftype timer-mode (uint32) (deftype timer-mode (uint32)
(;(data uint32 :offset 0 :size 32) (;; clock selection:
;; 0: BUSCLK
;; 1: BUSCLK/16
;; 2: BUSCLK/256
;; 3: hblank
(clks uint8 :offset 0 :size 2) (clks uint8 :offset 0 :size 2)
(gate uint8 :offset 2 :size 1) (gate uint8 :offset 2 :size 1) ;; gate function enable
(gats uint8 :offset 3 :size 1) (gats uint8 :offset 3 :size 1) ;; gate selection: 0 = hblank, 1 = vblank
;; gate mode:
;; 0: count while gate signal is low
;; 1: start when gate signal rises
;; 2: start when gate signal falls
;; 3: start when gate signal rises/falls
(gatm uint8 :offset 4 :size 2) (gatm uint8 :offset 4 :size 2)
(zret uint8 :offset 6 :size 1) (zret uint8 :offset 6 :size 1) ;; zero return: clear counter when equal to reference value
(cue uint8 :offset 7 :size 1) (cue uint8 :offset 7 :size 1) ;; count-up enable
(cmpe uint8 :offset 8 :size 1) (cmpe uint8 :offset 8 :size 1) ;; compare-interrupt enable
(ovfe uint8 :offset 9 :size 1) (ovfe uint8 :offset 9 :size 1) ;; overflow-interrupt enable
(equf uint8 :offset 10 :size 1) (equf uint8 :offset 10 :size 1) ;; equal-flag
(ovff uint8 :offset 11 :size 1) (ovff uint8 :offset 11 :size 1) ;; overflow-flag
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4

View file

@ -5,16 +5,6 @@
;; name in dgo: timer ;; name in dgo: timer
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; Sneakily disable these instructions for readibility (remove this later)
;; SYNC is an EE instruction that waits for various memory access to be completed
;; (this might not be necessary for x86_64)
(defmacro .sync.l () `(none))
(defmacro .sync.p () `(none))
;; Copies the contents of a cop0 (system control) register to a gpr
(defmacro .mfc0 (dest src) `(none))
;; Copies the contents of a gpr to a cop0 (system control) register
(defmacro .mtc0 (dest src) `(none))
(defun timer-reset ((timer timer-bank)) (defun timer-reset ((timer timer-bank))
"Reset a timer's counter to zero" "Reset a timer's counter to zero"
@ -63,7 +53,6 @@
"Init a stopwatch" "Init a stopwatch"
(set! (-> obj begin-level) 0) (set! (-> obj begin-level) 0)
(set! (-> obj prev-time-elapsed) 0) (set! (-> obj prev-time-elapsed) 0)
(none)
) )
@ -76,7 +65,6 @@
(set! (-> obj start-time) count) (set! (-> obj start-time) count)
) )
) )
(none)
) )
(defun stopwatch-start ((obj stopwatch)) (defun stopwatch-start ((obj stopwatch))
@ -88,7 +76,6 @@
(set! (-> obj start-time) count) (set! (-> obj start-time) count)
) )
) )
(none)
) )
(defun stopwatch-stop ((obj stopwatch)) (defun stopwatch-stop ((obj stopwatch))
@ -97,16 +84,15 @@
(set! (-> obj begin-level) 0) (set! (-> obj begin-level) 0)
(let ((count 0)) (let ((count 0))
(let ((count 0)) (let ((count 0))
(.mfc0 count Count) ; wrong register? a typo in a rlet? who knows. (.mfc0 count Count) ;; wrong register? a typo in a rlet? who knows.
(+! (-> obj prev-time-elapsed) (- count (-> obj start-time))) (+! (-> obj prev-time-elapsed) (- count (-> obj start-time)))
) )
) )
) )
(none)
) )
(defun stopwatch-begin ((obj stopwatch)) (defun stopwatch-begin ((obj stopwatch))
"Begin a stopwatch layer. Starts the stopwatch if it has not yet begun" "Begin a stopwatch level, and starts it if it hasn't yet"
(when (zero? (-> obj begin-level)) (when (zero? (-> obj begin-level))
(let ((count 0)) (let ((count 0))
(.mfc0 count Count) (.mfc0 count Count)
@ -114,12 +100,12 @@
) )
) )
(+! (-> obj begin-level) 1) (+! (-> obj begin-level) 1)
(none)
) )
;; NOTE : there is no guard against ending a stopwatch too many times!
(defun stopwatch-end ((obj stopwatch)) (defun stopwatch-end ((obj stopwatch))
"End a stopwatch layer. Stops the stopwatch if it has ended as many times as it has begun" "End a stopwatch level. Stops the stopwatch if it's back to level zero.
There is no guard against ending a stopwatch too many times, and a negative level
will cause errors!"
(+! (-> obj begin-level) -1) (+! (-> obj begin-level) -1)
(when (zero? (-> obj begin-level)) (when (zero? (-> obj begin-level))
(set! (-> obj begin-level) 0) (set! (-> obj begin-level) 0)
@ -128,17 +114,16 @@
(+! (-> obj prev-time-elapsed) (- count (-> obj start-time))) (+! (-> obj prev-time-elapsed) (- count (-> obj start-time)))
) )
) )
(none)
) )
(defun stopwatch-elapsed-ticks ((obj stopwatch)) (defun stopwatch-elapsed-ticks ((obj stopwatch))
"Returns the elapsed time so far (in clock cycles) of a stopwatch" "Returns the elapsed time so far (in clock cycles) of a stopwatch"
(let ((elapsed (-> obj prev-time-elapsed))) (let ((elapsed (-> obj prev-time-elapsed)))
(when (> (-> obj begin-level) 0) (when (> (-> obj begin-level) 0)
(let ((count 0)) (let ((count (the uint 0)))
(.mfc0 count Count) (.mfc0 count Count)
(+! elapsed (- count (-> obj start-time))) (+! elapsed (- count (-> obj start-time)))
;(set! count elapsed) ;; ?? (set! count elapsed) ;; ??
) )
) )
elapsed elapsed

View file

@ -498,3 +498,16 @@
(defmacro <0.si (a) (defmacro <0.si (a)
`(< (the-as int ,a) (the-as int 0)) `(< (the-as int ,a) (the-as int 0))
) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (Fake) MIPS Macros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; these are macros for MIPS instructions which we may want to keep in the source code for
;; readibility/curiosity/documentation, but will not translate into any actual instructions at all
;; A macro that generates a macro for the specified instruction
(defmacro fake-asm (asm-name &rest args)
`(defmacro ,asm-name (,@args) `(none))
)

View file

@ -1371,3 +1371,15 @@
) )
) )
) )
(#when PC_PORT
;; SYNC is an EE instruction that waits for various memory access and DMA to be completed
;; DMA will be instant in the PC port, so these are no longer necessary
(fake-asm .sync.l)
(fake-asm .sync.p)
;; Copies the contents of a cop0 (system control) register to a gpr
(fake-asm .mfc0 dest src)
;; Copies the contents of a gpr to a cop0 (system control) register
(fake-asm .mtc0 dest src)
)