Re: 8051 assembler in Common Lisp



Peter Seibel <peter@xxxxxxxxxxxxxxx> writes:

> To provide some food for thought, here's a sketch of part of an
> assembler ...

Whoops. *Here's* that sketch:

(defpackage :asm51 (:use :cl))

(in-package :asm51)

(defmacro deftext (name &body body)
"Compile a body of ops and labels into a form that can be included in a larger assembly."
`(eval-when (:compile-toplevel :load-toplevel :execute)
(setf (get ',name 'compiled-text) ,(compile-body body))))

(defun gettext (name)
(get name 'compiled-text))

(defun compile-body (body)
(pass3 (pass2 (pass1 body))))

(defun pass1 (body)
"Macroexpand non labels. Output of this stage is a list of
labels and ops which can contain references to the labels."
(loop for expression in body
when (symbolp expression) nconc (list expression)
else nconc (asm-macroexpand expression)))

(defun asm-macroexpand (expression)
"This is a no-op at the moment. But it would be straightforward
to allow folks to define assembler macros that expand a form
into a list of ops and labels, similar to the way the HTML
macros in Chapter 31 of Practical Common Lisp work."
(list expression))

(defun pass2 (body)
"Compute the addresses of all the labels."
(loop with labels = ()
with offset = 0
for thing in body
when (symbolp thing) do (setf labels (acons thing offset labels))
else do (incf offset (size-of thing)) and collect thing into ops
finally (return (list labels ops))))

(defun pass3 (labels-and-ops)
"Generate actual code"
(destructuring-bind (labels ops) labels-and-ops
(loop with code = (make-array 100 :element-type '(unsigned-byte 8) :adjustable t :fill-pointer 0)
for op in ops do (generate-code op labels code)
finally (return code))))

(defun size-of (thing)
(destructuring-bind (op &rest operands) thing
(size-of-op op operands)))

(defgeneric size-of-op (op operands))

(defmethod size-of-op ((op (eql 'goto)) operands)
(declare (ignore operands))
2)

(defmethod size-of-op ((op (eql 'nop)) operands)
(declare (ignore operands))
1)

(defmethod size-of-op ((op (eql 'push)) operands)
(declare (ignore operands))
2)

(defun generate-code (op labels buffer)
(destructuring-bind (op &rest operands) op
(generate-code-for-op op (resolve-labels operands labels) buffer)))

(defun resolve-labels (operands labels)
(loop for x in operands
when (symbolp x) collect (cdr (assoc x labels))
else collect x))

(defgeneric generate-code-for-op (op operands bufffer)
(:documentation "Generate the actual machine code for a given
OP with the given OPERANDS into BUFFER. All labels have already
been translated into absolute addresses. The fill-pointer can
be used to abtain the current address if the output is supposed
to be a relative address."))

(defmethod generate-code-for-op ((op (eql 'nop)) operands buffer)
(declare (ignore operands))
(vector-push-extend 0 buffer))

(defmethod generate-code-for-op ((op (eql 'goto)) operands buffer)
(vector-push-extend 1 buffer)
(vector-push-extend (first operands) buffer))

(defmethod generate-code-for-op ((op (eql 'push)) operands buffer)
(vector-push-extend 2 buffer)
(vector-push-extend (first operands) buffer))

-Peter

--
Peter Seibel * peter@xxxxxxxxxxxxxxx
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
.



Relevant Pages

  • Re: shift register data
    ... You do not need these packages. ... + can not have such operands in this context. ... buffer until the buffer is filled (I am counting the number of bytes ...
    (comp.lang.vhdl)
  • Re: using a general browser as a form-based capture method
    ... The browser must have the form data content in memory, plus the labels ... and probably even a buffer with the proposed POST action text block. ...
    (comp.lang.javascript)
  • Re: Text without Z buffer
    ... > glDepthMask is used to activate/deactivate depth buffer writes. ... > not change depth buffer test! ... The labels are ...
    (comp.graphics.api.opengl)