aboutsummaryrefslogtreecommitdiffstats
path: root/atk16_schasm/macros.scm
diff options
context:
space:
mode:
Diffstat (limited to 'atk16_schasm/macros.scm')
-rw-r--r--atk16_schasm/macros.scm84
1 files changed, 84 insertions, 0 deletions
diff --git a/atk16_schasm/macros.scm b/atk16_schasm/macros.scm
new file mode 100644
index 0000000..45d2167
--- /dev/null
+++ b/atk16_schasm/macros.scm
@@ -0,0 +1,84 @@
+;; Assume that core.scm is loaded
+
+(define *unique-counter* 0)
+(define (next-unique)
+ (set! *unique-counter* (+ 1 *unique-counter*))
+ *unique-counter*)
+(define *macro-scratch-reg* R12)
+
+(define (%packed-string s)
+ ;; emit length
+ (define sl (string-length s))
+ (u16 sl) ; cast to u16 to get bounds check
+ (emit-word sl)
+
+ ;; compute packed words
+ (for-each (@ emit-byte) (string->ascii-list s)))
+
+(define-syntax emit-test-eq
+ (syntax-rules ()
+ ((_ lhs rhs dest set)
+ (begin (sub lhs rhs)
+ (br flag-zero (label dest) set: set)))))
+
+(define-syntax emit-test-lt
+ (syntax-rules ()
+ ((_ lhs rhs dest set)
+ (begin (sub lhs rhs)
+ (br flag-sign (label dest) set: set)))))
+
+(define-syntax emit-test-lte
+ (syntax-rules ()
+ ((_ lhs rhs dest set)
+ (begin (sub lhs rhs)
+ (sub lhs (u16 1))
+ (br flag-sign (label dest) set: set)))))
+
+(define-syntax %if-else
+ (syntax-rules ()
+ ((_ pred tb fb)
+ (let* ((lhs (eval (car 'pred)))
+ (op (cadr 'pred))
+ (rhs (eval (caddr 'pred)))
+ (n (next-unique))
+ (sym-false (string->symbol (format "~A-false" n)))
+ (sym-end (string->symbol (format "~A-end" n))))
+ (ld *macro-scratch-reg* lhs)
+
+ (cond
+ ((eq? '== op) (emit-test-eq *macro-scratch-reg* rhs sym-false #f))
+ ((eq? '!= op) (emit-test-eq *macro-scratch-reg* rhs sym-false #t))
+ ((eq? '< op) (emit-test-lt *macro-scratch-reg* rhs sym-false #f))
+ ((eq? '>= op) (emit-test-lt *macro-scratch-reg* rhs sym-false #t))
+ ((eq? '<= op) (emit-test-lte *macro-scratch-reg* rhs sym-false #f))
+ ((eq? '> op) (emit-test-lte *macro-scratch-reg* rhs sym-false #t))
+ (else (error "unsupported operator" op)))
+
+ tb
+ (ld PC (label sym-end))
+ (def-label sym-false)
+ fb
+ (def-label sym-end)))))
+
+(define-syntax %if
+ (syntax-rules ()
+ ((_ pred tb)
+ (let* ((lhs (eval (car 'pred)))
+ (op (cadr 'pred))
+ (rhs (eval (caddr 'pred)))
+ (n (next-unique))
+ (sym-end (string->symbol (format "~A-end" n))))
+ (ld *macro-scratch-reg* lhs)
+
+ (cond
+ ((eq? '== op) (emit-test-eq *macro-scratch-reg* rhs sym-end #f))
+ ((eq? '!= op) (emit-test-eq *macro-scratch-reg* rhs sym-end #t))
+ ((eq? '< op) (emit-test-lt *macro-scratch-reg* rhs sym-end #f))
+ ((eq? '>= op) (emit-test-lt *macro-scratch-reg* rhs sym-end #t))
+ ((eq? '<= op) (emit-test-lte *macro-scratch-reg* rhs sym-end #f))
+ ((eq? '> op) (emit-test-lte *macro-scratch-reg* rhs sym-end #t))
+ (else (error "unsupported operator" op)))
+
+ tb
+ (def-label sym-end)))))
+