-
Notifications
You must be signed in to change notification settings - Fork 0
/
ghc-asm.lisp
97 lines (90 loc) · 3.67 KB
/
ghc-asm.lisp
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
85
86
87
88
89
90
91
92
93
94
95
96
97
(in-package :pc)
(defvar *label-target* nil)
(declaim (ftype (function (t) t) push-ghc-instruction))
(defun get-op-instr (sym)
(case sym
(+ '(add))
(- '(sub))
(* '(mul))
(/ '(div))
(& '(and))
(or '(or))
(xor '(xor))
;; Conditionals
(< `(jlt ,*label-target*))
(= `(jeq ,*label-target*))
(> `(jgt ,*label-target*))
;; During processing of assignment operators target is nil
(+= '(add))
(-= '(sub))
(*= '(mul))
(/= '(div))
(&= '(and))
(or= '(or))
(xor= '(xor))
(:= '(mov))
(++ '(inc))
(-- '(dec))
(otherwise nil)))
(defvar *current-instructions* nil)
(defun hash-tab-from-alist (alist)
(let ((tab (make-hash-table :test #'eq)))
(loop for (key . val) in alist
do (setf (gethash key tab) val))
tab))
(defun ghc-compile-expr (expr target available-registers var-access-exprs var-address-exprs)
(if (atom expr)
(if (symbolp expr)
(car (gethash expr var-access-exprs))
expr)
(let ((instr (get-op-instr (car expr))))
(if instr
(progn
(when (null available-registers)
(error "Cannot compile exprs"))
(case (length (cdr expr))
(2 (let* ((tval (ghc-compile-expr (second expr) target available-registers
var-access-exprs var-address-exprs))
(reg1 (ghc-compile-expr (third expr) (car available-registers) (cdr available-registers)
var-access-exprs var-address-exprs)))
(if target
(progn
(when (and (not (eq tval target)))
(push-ghc-instruction `(mov ,target ,tval)))
(push-ghc-instruction `(,@instr ,target ,reg1))
target)
(progn
(push-ghc-instruction `(,@instr ,tval ,reg1))
tval))))
(1 (let* ((tval (ghc-compile-expr (second expr) (car available-registers) (cdr available-registers)
var-access-exprs var-address-exprs)))
(push-ghc-instruction `(,@instr ,tval))
tval))))
(cond ((eq (first expr) 'address)
(gethash (second expr) var-address-exprs))
((eq (first expr) 'label)
(second expr))
((eq (first expr) 'val)
(let ((val-inner (ghc-compile-expr (second expr) (car available-registers) (cdr available-registers)
var-access-exprs var-address-exprs)))
(if (symbolp val-inner)
(list val-inner)
(progn
(push-ghc-instruction `(mov ,target ,val-inner))
target)))))))))
(defun ghc-asm-dump (body stream)
(labels ((%param-to-string (par)
(cond ((symbolp par)
(string-downcase (symbol-name par)))
((integerp par)
(format nil "~A" par))
((listp par)
(format nil "[~A]" (%param-to-string (first par)))))))
(dolist (instr body)
(if (listp instr)
(format stream "~A ~{~A~^,~}~%"
(string-downcase (symbol-name (car instr)))
(mapcar #'%param-to-string (cdr instr)))
(format stream "~A~%"
(string-downcase (symbol-name instr)))))
(format *error-output* "Dumped ~A instructions~%" (length body))))