diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 51b9acbb7..46cc9e13d 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -1623,10 +1623,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; -;;;;;;;;;;;;; -;; timer-h -;;;;;;;;;;;;; - (deftype timer-mode (uint32) (;(data uint32 :offset 0 :size 32) (clks uint8 :offset 0 :size 2) @@ -1706,6 +1702,25 @@ ) ) +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; TIMER ;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; + +(define-extern timer-reset (function timer-bank none)) +(define-extern timer-count (function timer-bank uint)) +(define-extern disable-irq (function none)) +(define-extern enable-irq (function none)) +(define-extern stopwatch-init (function stopwatch none)) +(define-extern stopwatch-reset (function stopwatch none)) +(define-extern stopwatch-start (function stopwatch none)) +(define-extern stopwatch-stop (function stopwatch none)) +(define-extern stopwatch-begin (function stopwatch none)) +(define-extern stopwatch-end (function stopwatch none)) +(define-extern stopwatch-elapsed-ticks (function stopwatch uint)) +(define-extern stopwatch-elapsed-seconds (function stopwatch float)) + ;;;;;;;;;;;;; ;; vif-h ;;;;;;;;;;;;; @@ -31709,25 +31724,6 @@ ;;(define-extern sound-rpc-set-flava object) ;; unknown type ;;(define-extern sound-name object) ;; unknown type ;;(define-extern sound-rpc-continue-group object) ;; unknown type -;;(define-extern timer-mode object) ;; unknown type -;;(define-extern timer-hold-bank object) ;; unknown type -;;(define-extern stopwatch object) ;; unknown type -;;(define-extern *ticks-per-frame* object) ;; unknown type -;;(define-extern profile-bar object) ;; unknown type -;;(define-extern timer-bank object) ;; unknown type -;;(define-extern profile-frame object) ;; unknown type -(define-extern stopwatch-init function) -(define-extern stopwatch-elapsed-seconds function) -(define-extern stopwatch-begin function) -(define-extern stopwatch-elapsed-ticks function) -(define-extern disable-irq function) -(define-extern timer-reset function) -(define-extern enable-irq function) -(define-extern stopwatch-start function) -(define-extern timer-count function) -(define-extern stopwatch-end function) -(define-extern stopwatch-stop function) -(define-extern stopwatch-reset function) ;;(define-extern vif-stat object) ;; unknown type ;;(define-extern vif-fbrst object) ;; unknown type ;;(define-extern vif-err object) ;; unknown type diff --git a/goal_src/engine/ps2/timer-h.gc b/goal_src/engine/ps2/timer-h.gc index 2aada4642..fbb92bce5 100644 --- a/goal_src/engine/ps2/timer-h.gc +++ b/goal_src/engine/ps2/timer-h.gc @@ -55,6 +55,7 @@ :flag-assert #x900000034 ) +;; stopwatches are used to measure CPU clock cycles (deftype stopwatch (basic) ((prev-time-elapsed uint64 :offset-assert 8) (start-time uint64 :offset-assert 16) @@ -68,10 +69,10 @@ ;; Confusing! What IS this measuring exactly? Hmm... (define *ticks-per-frame* (/ 2500000 256)) ;; 2 500 000 / 256 = 9765 -(defun timer-init ((bank timer-bank) (mode timer-mode)) +(defun timer-init ((timer timer-bank) (mode timer-mode)) "Initiate a timer, start counting at a rate of 1 every 256 bus clocks (BUSCLK: ~147.456MHz)." - (set! (-> bank mode) mode) - (set! (-> bank count) 0) + (set! (-> timer mode) mode) + (set! (-> timer count) 0) ) ;; segfaults OpenGOAL as it does not support ps2 EE timers diff --git a/goal_src/engine/ps2/timer.gc b/goal_src/engine/ps2/timer.gc index 2de4515b6..956082fb7 100644 --- a/goal_src/engine/ps2/timer.gc +++ b/goal_src/engine/ps2/timer.gc @@ -5,3 +5,152 @@ ;; name in dgo: timer ;; 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)) + "Reset a timer's counter to zero" + (.sync.l) + (set! (-> timer count) 0) + (.sync.l) + ) + +(defun timer-count ((timer timer-bank)) + "Return a timer's counter value" + (.sync.l) + (let ((count (-> timer count))) + (.sync.l) + count + ) + ) + +;; cop0 status register "interrupt enable" flag +;; if cop0 status is needed anywhere else, move this elsewhere +(defconstant COP0_STATUS_IE (the-as uint #x1)) + +(defun disable-irq () + "Disable all interrupts" + (rlet ((status :class gpr :type uint)) + (let ((status-mask (lognot COP0_STATUS_IE))) + (.mfc0 status Status) + (logand! status status-mask) ;; should status-mask be replaced directly? + (.mtc0 Status status) + (.sync.p) + ) + ) + ) + +(defun enable-irq () + "Enable all interrupts" + (rlet ((status :class gpr :type uint)) + (.mfc0 status Status) + (logior! status COP0_STATUS_IE) + (.mtc0 Status status) + (.sync.p) + ) + ) + + +(defun stopwatch-init ((obj stopwatch)) + "Init a stopwatch" + (set! (-> obj begin-level) 0) + (set! (-> obj prev-time-elapsed) 0) + (none) + ) + + +(defun stopwatch-reset ((obj stopwatch)) + "Restart a stopwatch's times" + (set! (-> obj prev-time-elapsed) 0) + (when (> (-> obj begin-level) 0) + (let ((count 0)) + (.mfc0 count Count) + (set! (-> obj start-time) count) + ) + ) + (none) + ) + +(defun stopwatch-start ((obj stopwatch)) + "Start a stopwatch from scratch" + (when (zero? (-> obj begin-level)) + (set! (-> obj begin-level) 1) + (let ((count 0)) + (.mfc0 count Count) + (set! (-> obj start-time) count) + ) + ) + (none) + ) + +(defun stopwatch-stop ((obj stopwatch)) + "Fully stop a stopwatch and save its elapsed time" + (when (> (-> obj begin-level) 0) + (set! (-> obj begin-level) 0) + (let ((count 0)) + (let ((count 0)) + (.mfc0 count Count) ; wrong register? a typo in a rlet? who knows. + (+! (-> obj prev-time-elapsed) (- count (-> obj start-time))) + ) + ) + ) + (none) + ) + +(defun stopwatch-begin ((obj stopwatch)) + "Begin a stopwatch layer. Starts the stopwatch if it has not yet begun" + (when (zero? (-> obj begin-level)) + (let ((count 0)) + (.mfc0 count Count) + (set! (-> obj start-time) count) + ) + ) + (+! (-> obj begin-level) 1) + (none) + ) + +;; NOTE : there is no guard against ending a stopwatch too many times! +(defun stopwatch-end ((obj stopwatch)) + "End a stopwatch layer. Stops the stopwatch if it has ended as many times as it has begun" + (+! (-> obj begin-level) -1) + (when (zero? (-> obj begin-level)) + (set! (-> obj begin-level) 0) + (let ((count 0)) + (.mfc0 count Count) + (+! (-> obj prev-time-elapsed) (- count (-> obj start-time))) + ) + ) + (none) + ) + +(defun stopwatch-elapsed-ticks ((obj stopwatch)) + "Returns the elapsed time so far (in clock cycles) of a stopwatch" + (let ((elapsed (-> obj prev-time-elapsed))) + (when (> (-> obj begin-level) 0) + (let ((count 0)) + (.mfc0 count Count) + (+! elapsed (- count (-> obj start-time))) + ;(set! count elapsed) ;; ?? + ) + ) + elapsed + ) + ) + +(defglobalconstant EE_SECONDS_PER_TICK (/ 1.0 3000000)) ;; 300MHz is a "decent enough" estimate +(defmacro cpu-ticks-to-seconds (ticks) + `(* ,EE_SECONDS_PER_TICK ,ticks) + ) +(defun stopwatch-elapsed-seconds ((obj stopwatch)) + "Returns the elapsed time so far (in seconds) of a stopwatch" + (cpu-ticks-to-seconds (stopwatch-elapsed-ticks obj)) + ) + diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index 4f8a92c94..adb011f9c 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -201,7 +201,7 @@ ;; otherwise don't ignore it. `(define ,name (lambda :name ,name :segment debug ,bindings ,@body)) ) - + ;; function not loaded, set function to the nothing function. ;; we don't typecheck this. (define :no-typecheck #t ,name nothing) @@ -355,6 +355,22 @@ `(& (-> ,@args)) ) +(defmacro logior! (place amount) + `(set! ,place (logior ,place ,amount)) + ) + +(defmacro logxor! (place amount) + `(set! ,place (logxor ,place ,amount)) + ) + +(defmacro lognor! (place amount) + `(set! ,place (lognor ,place ,amount)) + ) + +(defmacro logand! (place amount) + `(set! ,place (logand ,place ,amount)) + ) + ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Bit Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/test-goal-typecoherency.bat b/test-goal-typecoherency.bat new file mode 100644 index 000000000..b16e29358 --- /dev/null +++ b/test-goal-typecoherency.bat @@ -0,0 +1,3 @@ +@echo off +out\build\Release\bin\goalc-test --gtest_filter="*TypeConsistency*" +pause \ No newline at end of file