Files
kurt/assembly.lisp

160 lines
3.9 KiB
Common Lisp

(in-package :cl-forth)
(defparameter *operations* (make-hash-table))
(eval-always
(defun normalize-op-list (asm-list)
(cons 'list
(mapcar (lambda (el) (cond ((stringp el) el)
((listp el) `(format nil ,@el))))
asm-list)))
(defun defop-format (str space-num asm-list)
(format str
(format nil "~~{~a~~a~~%~~}"
(make-string space-num :initial-element #\Space))
asm-list))
(defun replace-write (out-stream indent forms)
(if (consp forms)
(if (eq :write (car forms))
`(defop-format ,out-stream ,indent
,(normalize-op-list (cdr forms)))
(cons (replace-write out-stream indent (car forms))
(replace-write out-stream indent (cdr forms))))
forms)))
(defmacro defop (op-name+args (&key (indent 4)) &body body)
(with-gensyms (out-stream)
(destructuring-bind (op-name . args) (mklist op-name+args)
`(setf (gethash ',op-name *operations*)
(lambda (,out-stream ,@args)
,(if (or (stringp (car body)) (stringp (caar body)))
`(defop-format ,out-stream ,indent
,(normalize-op-list body))
(replace-write out-stream indent (car body))))))))
(defop (push a) ()
("push ~d" a))
(defop + ()
"pop rax"
"pop rbx"
"add rax, rbx"
"push rax")
(defop - ()
"pop rax"
"pop rbx"
"sub rbx, rax"
"push rbx")
(defop dump ()
"pop rdi"
"call dump")
(defop = ()
"mov rcx, 0"
"mov rdx, 1"
"pop rax"
"pop rbx"
"cmp rax, rbx"
"cmove rcx, rdx"
"push rcx")
(defop (exit code) ()
"mov rax, 60"
("mov rdi, ~a" code)
"syscall")
(defop (ise label-num) ()
"pop rax"
"test rax, rax"
("jz et_~a" label-num))
(defop (yoksa yap-num ise-num) (:indent 0)
(" jmp et_~a" yap-num)
("et_~a:" ise-num))
(defop (yap label-num &optional döngü-num) (:indent 0)
(if (null döngü-num)
(:write ("et_~a:" label-num))
(:write (" jmp et_~a" döngü-num)
("et_~a:" label-num))))
(defop ()
"pop rax"
"push rax"
"push rax")
(defop düş ()
"pop rax")
(defop (iken label-num) ()
"pop rax"
"test rax, rax"
("jz et_~a" label-num))
(defop (döngü label-num) (:indent 0)
("et_~a:" label-num))
(defop < ()
"mov rcx, 0"
"mov rdx, 1"
"pop rbx"
"pop rax"
"cmp rax, rbx"
"cmovl rcx, rdx"
"push rcx")
(defop > ()
"mov rcx, 0"
"mov rdx, 1"
"pop rbx"
"pop rax"
"cmp rax, rbx"
"cmovg rcx, rdx"
"push rcx")
(defun gen-code (op str)
(let ((op-fn (gethash (car op) *operations*)))
(if (null op-fn)
(error "~s is not a valid op" op)
(apply op-fn str (cdr op)))))
(defun gen-dump (str)
(format str "~{~a~%~}"
'("dump:"
" mov r9, -3689348814741910323"
" sub rsp, 40"
" mov BYTE [rsp+31], 10"
" lea rcx, [rsp+30]"
".L2:"
" mov rax, rdi"
" lea r8, [rsp+32]"
" mul r9"
" mov rax, rdi"
" sub r8, rcx"
" shr rdx, 3"
" lea rsi, [rdx+rdx*4]"
" add rsi, rsi"
" sub rax, rsi"
" add eax, 48"
" mov BYTE [rcx], al"
" mov rax, rdi"
" mov rdi, rdx"
" mov rdx, rcx"
" sub rcx, 1"
" cmp rax, 9"
" ja .L2"
" lea rax, [rsp+32]"
" mov edi, 1"
" sub rdx, rax"
" xor eax, eax"
" lea rsi, [rsp+32+rdx]"
" mov rdx, r8"
" mov rax, 1"
" syscall"
" add rsp, 40"
" ret")))