aboutsummaryrefslogtreecommitdiffstats
path: root/atk16_schasm/macros.scm
blob: 45d2167f702f081f9f4a9e44f2175a5d4496159f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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)))))