URL
https://opencores.org/ocsvn/igor/igor/trunk
Subversion Repositories igor
[/] [igor/] [trunk/] [microprogram_assembler/] [assembler.lisp] - Rev 3
Compare with Previous | Blame | View Log
;;;
;;; Assembler!
;;;
(in-package #:mcasm)
(defvar *assembler-constants* (make-hash-table :test 'equal))
(defvar *assembler-labelnumbers* 0)
(defun next-labelnumber ()
(incf *assembler-labelnumbers*))
(defstruct constant-info
type
name
number)
(defun constant-info-to-string (info &key (key nil))
(format nil "~A~A~A~A"
(constant-info-type info)
(if key
"-"
" ")
(constant-info-name info)
(if key ""
(format nil " ~X" (constant-info-number info)))))
(defmacro def-const ((name number &key (type "const")) &body body)
`(let ((info (make-constant-info :type ,type
:name ',name
:number ,number)))
(setf (gethash (constant-info-to-string info :key nil) *assembler-constants*) info)
,@body))
(defmacro def-branch (name number)
`(def-const (,name ,number :type "branch")
(defparameter ,(intern (format nil "-BRANCH-~A-" name)) ,number)))
(def-branch O 1)
(def-branch C 2)
(def-branch N 4)
(def-branch Z 8)
(def-branch B 16)
(defmacro def-type (name number)
`(def-const (,name ,number :type "type")
(defparameter ,(intern (format nil "+TYPE-~A+" name)) ,number)))
(def-type none #x0)
(def-type int #x1)
(def-type float #x3)
(def-type cons #x4)
(def-type snoc #x5)
(def-type ptr #x6)
(def-type array #x7)
(def-type nil #x8)
(def-type t #x9)
(def-type char #xA)
(def-type symbol #xB)
(def-type function #xC)
(def-type builtin #xD)
(defparameter +n-regs+ #x400) ; number of registers
(defmacro defreg (name number)
`(def-const (,name ,number :type "reg")
(defparameter ,(intern (format nil "$~A" name)) ,number)))
(defmacro defmem (name number)
`(def-const (,name ,number :type "memory")
(defparameter ,(intern (format nil "%~A" name)) ,number)))
(defreg zero #x00)
(defreg one #x01)
(defreg two #x02)
(defreg s-addr #x03) ; address where an sframe has been stored
;;(defreg s-name #x04) ;; TODO do we want this?
;;(defreg s-fstack #x04)
(defreg s-condition #x04)
(defreg s-iterations #x05)
(defreg s-parent #x06)
;;(defreg e/f-addr #x07)
;;(defreg e/f-parent-addr #x08)
(defreg s-tmp #x09)
(defreg e-tmp1 #x0A)
(defreg e-tmp2 #x0B)
(defreg e-tmp3 #x0C)
(defreg f-tmp1 #x0D)
(defreg f-tmp2 #x0E)
(defreg f-tmp3 #x0F)
;;(defreg e-addr #x09) ;; TODO remove this
(defreg e-expr #x10)
(defreg e-arg #x11)
(defreg e-result #x12)
(defreg e-phase #x13)
(defreg e-addr #x14)
;;(defreg f-addr #x15) ;; TODO remove this
(defreg f-func #x16)
(defreg f-env #x17)
;;(defreg f-estack #x18)
(defreg f-addr #x19)
(defreg alloc-addr #x20)
(defreg alloc-top #x21)
(defreg alloc-size #x22)
(defreg store-list-start #x23)
(defreg store-list-end #x24)
(defreg store-list-addr #x25)
(defreg store-list-reg #x26)
(defreg store-list-val #x27)
(defreg apply-result #x28)
(defreg apply-result-val #x29)
(defreg apply-func #x2A)
(defreg builtin-arg1 #x2B)
(defreg builtin-arg2 #x2C)
(defreg builtin-arg3 #x2D)
(defreg builtin-arg1-val #x2E)
(defreg builtin-arg2-val #x2F)
(defreg builtin-arg3-val #x30)
(defreg tmp-result #x33)
(defreg apply-argc #x34)
(defreg apply-required-argc #x35)
(defreg car #x40)
(defreg cdr #x41)
(defreg list-terminator #x42)
(defreg interrupt-tmp #x45)
(defreg params-car #x50)
(defreg args-car #x51)
(defreg apply-eval-expr #x52)
(defreg apply-eval-env #x53)
(defreg apply-apply-args #x54)
(defreg apply-apply-params #x55)
(defreg env #x56)
(defreg tmp1 #x57)
(defreg tmp2 #x58)
(defreg tmp3 #x59)
(defreg tmp4 #x5A)
(defreg fetch-args-arg-reg #x60)
(defreg fetch-args-arg #x61)
(defreg fetch-args-argval-reg #x62)
(defreg fetch-args-argval #x63)
(defreg fetch-args-arglist #x64)
(defreg io-devnr #x65)
(defreg io-new-devnr #x66)
(defreg io-mem-addr #x67)
(defreg message #x68)
(defreg message-shift #x69)
(defreg message-mask #x6A)
(defreg message-tmp1 #x6B)
(defreg message-tmp2 #x6C)
(defreg mc-stack-top #x090)
(defreg mc-stack-min #x091)
(defreg mc-stack-max #x09E)
(defreg e/f-top #x09F)
(defreg e/f-below-marker #x100)
(defreg e/f-min #x104)
(defreg e/f-min-expr #x104)
(defreg e/f-min-arg #x105)
(defreg e/f-min-result #x106)
(defreg e/f-min-phase #x107)
;; (defreg e/f-max-expr #x118)
;; (defreg e/f-max-arg #x119)
;; (defreg e/f-max-result #x11A)
;; (defreg e/f-max-phase #x11B)
;; (defreg e/f-max #x11B)
;; (defreg e/f-above-marker #x11C)
(defreg e/f-max-expr #x3F8)
(defreg e/f-max-arg #x3F9)
(defreg e/f-max-result #x3FA)
(defreg e/f-max-phase #x3FB)
(defreg e/f-max #x3FB)
(defreg e/f-above-marker #x3FC)
(defreg e/f-frame-size #x3FD)
(defreg init1 #x3F0)
(defreg init2 #x3F1)
(defreg init3 #x3F2)
(defreg init-counter #x3F3)
(defreg init-counter2 #x3F4)
(defreg init-shift1 #x3F5)
(defreg init-shift2 #x3F6)
(defreg init-char-mask #x3F7)
(defreg init-chars-start #x3F8)
(defreg init-symbol-addr #x3F9)
(defreg init-symbol-str-addr #x3FA)
(defreg init-symbol-char-addr #x3FB)
(defreg init-symbol-array #x3FC)
;; needed variables (registers) for gc
;; register values that must be predefined
;; set these when testing gc standalone in emulator
(defreg gc-maxblocks #x70) ;; total memory size
(defreg gc-spaces #x71) ;; number of spaces we'll divide the memory in
(defreg gc-startofmem #x76) ;; start of variable address space
;; registers set by evaluator before invoking gc
;; set these when testing gc standalone in emulator
(defreg gc-rootptr #x78) ;; pointer to topmost object! hopefully
;; there will be only one
;; registers set by init, keep these throughout
(defreg gc-spacesize #x72) ;; size of each space: maxblocks / spaces
(defreg gc-sup #x73) ;; first address beyond legal space:
;; spaces * spacesize (NB: can be lower than
;; maxblocks)
(defreg gc-gcspace #x74) ;; start of gc exclusize space, sup - spacesize
;; registers used by everyone
(defreg gc-firstfree #x75) ;; first free memory block
;; (might exist already in other microcode)
;; scratch registers, can be used when gc is not running (but gc will
;; destroy them)
(defreg gc-1 #x80) ;; temp
(defreg gc-vi #x83)
(defreg gc-t #x84) ;; ptr-rev
(defreg gc-x #x85) ;; ptr-rev
(defreg gc-y #x86) ;; ptr-rev
(defreg gc-v #x87) ;; ptr-rev
(defreg gc-followp #x88) ;; ptr-rev
(defreg gc-cannext #x89) ;; ptr-rev
(defreg gc-canprev #x8a) ;; ptr-rev
(defreg gc-temp #x8b)
(defreg gc-mem #x8c)
(defreg gc-from #x84) ;; at this stage we're no longer using
(defreg gc-to #x85) ;; some of the above variables
(defreg gc-val #x86)
(defreg gc-temp2 #x87)
(defreg gc-baseaddr #x88)
(defreg gc-mem-limit #x7F)
;; div-variables (reusing gc-registers)
(defreg div-low #x88)
(defreg div-high #x89)
(defreg div-mid #x8a)
(defreg div-res #x8b)
(defreg div-sign #x8c)
(defreg mod-val1 #x87)
(defreg mod-val2 #x86)
(defparameter +gc-free+ #x00)
(defparameter +gc-used+ #x01)
(defparameter +gc-spaces+ #xA)
(defparameter +gc-limit+ #x1000) ; if free space is less than this, GC should be run
;; memory:
(defmem nil #x00)
(defmem t #x01)
(defmem if #x02)
(defmem quote #x03)
(defmem lambda #x04)
(defmem progn #x05)
(defparameter +first-builtin+ #x06)
(defmem cons #x06)
(defmem car #x07)
(defmem cdr #x08)
(defmem eval #x09)
(defmem apply #x0A)
(defmem type #x0B)
(defmem make-array #x0C)
(defmem array-size #x0D)
(defmem array-get #x0E)
(defmem array-set #x0F)
(defmem make-symbol #x10)
(defmem symbol-to-string #x11)
(defmem char-to-int #x12)
(defmem int-to-char #x13)
(defmem get-char #x14)
(defmem put-char #x15)
(defmem num-devices #x16)
(defmem device-type #x17)
(defmem set-address #x18)
(defmem get-address #x19)
(defmem error #x1A)
(defmem add #x1B)
(defmem sub #x1C)
(defmem mul #x1D)
(defmem div #x1E)
(defmem bitwise-and #x1F)
(defmem bitwise-or #x20)
(defmem bitwise-not #x21)
(defmem bitwise-shift #x22)
(defmem current-environment #x23)
(defmem make-eval-state #x24)
(defmem eval-partial #x25)
(defmem define #x26)
(defmem undefine #x27)
(defmem eq? #x28)
(defmem num-eq? #x29)
(defmem char-eq? #x2A)
(defmem less-than? #x2B)
(defmem mod #x2C)
(defmem set! #x2D)
(defmem set-car! #x2E)
(defmem set-cdr! #x2F)
(defmem function-data #x30)
(defmem builtin-name #x31)
(defmem device-size #x32)
(defmem device-status #x33)
(defparameter +last-builtin+ %device-status)
(defparameter +first-magic-var+ +first-builtin+)
(defparameter +last-magic-var+ +last-builtin+)
(defmem symbol-table #x3F)
(defparameter +first-phase+ #x40)
(defmem phase-eval #x40)
(defmem phase-eval-args #x41)
(defmem phase-apply #x42)
(defmem phase-eval-if #x43)
(defmem phase-initial #x44)
(defmem phase-env-lookup #x45)
(defmem phase-env-lookup-local #x46)
(defmem phase-apply-function #x47)
(defmem phase-bind-args #x48)
(defmem phase-eval-progn #x49)
(defmem phase-eval-args-top #x4A)
(defmem phase-eval-args-cdr #x4B)
(defmem phase-eval-args-cons #x4C)
(defmem phase-eval-symbol #x4D)
(defmem phase-set! #x4E)
(defparameter +last-phase+ %phase-set!)
(defmem timeout #x50)
(defmem err-invalid-phase #x51)
(defmem err-unbound-symbol #x52)
(defmem err-invalid-param-list #x53)
(defmem err-too-few-args #x54)
(defmem err-too-many-args #x55)
(defmem err-invalid-state #x56)
(defmem err-invalid-arg-list #x57)
(defmem err-type-error #x58)
(defmem err-not-a-list #x59)
(defmem err-not-a-function #x5A)
(defmem err-invalid-function #x5B)
(defmem err-malformed-form #x5C)
(defmem err-invalid-builtin #x5D)
(defmem err-invalid-array-index #x5E)
(defmem err-invalid-env #x5F)
(defmem err-not-a-pair #x60)
(defmem err-io-error #x61)
(defmem err-division-by-zero #x62)
(defmem err-overflow #x63)
(defparameter +last-symbol+ %err-overflow)
(defmem area-builtins #x100)
(defmem area-chars #x200)
(defmem area-ints #x280)
(defmem area-strings #x300)
(defmem area-symlist #xE00)
(defparameter +constant-chars+ (- %area-ints %area-chars))
(defparameter +constant-ints+ (- %area-strings %area-ints))
(defmem memory-root #xFFE)
(defmem mem-reserved-top #x1000)
(defmem boot-prog-start %mem-reserved-top)
(defparameter +memory-size+ (* 2 (* 1024 1024)))
(defmem io-mem-addr #x3FFFF00) ; TODO too large for immediate value
(defmem io-devices #x00)
(defmem io-curdev #x01)
(defmem io-cli #x02)
(defmem io-sai #x03)
(defmem io-intrdev #x04)
(defmem io-object #x10)
(defmem io-addr-l #x11)
(defmem io-addr-h #x12)
(defmem io-size-l #x13)
(defmem io-size-h #x14)
(defmem io-status #x15)
(defmem io-identification #x16)
(defmem io-irqenable #x17)
(defparameter +dev-boot+ #x03)
(defparameter +dev-serial+ #x00)
;;; Helper functions
;; Convert a argument to the argument type
(defun argument-to-type (arg)
(typecase arg
(integer 'imm)
(keyword 'label)
(t 'other)))
;; Make the instruction
;; Only set the opcode
(defun make-inst-opcode (opcode &key (debug 0) (break 0))
(let ((inst 0))
(setf (ldb (byte 6 42) inst) opcode)
(setf (ldb (byte 1 41) inst) debug)
(setf (ldb (byte 1 40) inst) break)
inst))
;; Parse an integer symbol and return the register number
(defun reg-to-num (reg)
(typecase reg
(symbol
(parse-integer (subseq (format nil "~A" reg) 1)))
(integer
reg)))
(defmacro rewrite-inst-part (inst &key from size value)
`(setf (ldb (byte ,size ,from) ,inst) ,value))
;; Make a function that returnes the binary representation of an instruction
(defmacro set-instruction ((&rest rest) &body body)
(let ((opcodevar (gensym))
(debugvar (gensym))
(instvar (gensym))
(breakvar (gensym)))
`(lambda (,opcodevar ,@rest &key (,debugvar 0) (,breakvar 0))
(let ((,instvar (make-inst-opcode ,opcodevar :debug ,debugvar :break ,breakvar)))
,@(loop for part in body
collect (cons 'rewrite-inst-part (cons instvar part)))
,instvar))))
;; The different opcode formats
(defparameter +opcodeformats+
`(
(noarg . (() ,(set-instruction ())))
(mem . ((r r imm) ,(set-instruction (r1 r2 imm)
(:size 11 :from 29 :value (reg-to-num r1))
(:size 11 :from 18 :value (reg-to-num r2))
(:size 18 :from 0 :value imm))))
(data . ((r r) ,(set-instruction (r1 r2)
(:size 11 :from 29 :value (reg-to-num r1))
(:size 11 :from 18 :value (reg-to-num r2)))))
(dataimm . ((r imm) ,(set-instruction (r1 imm)
(:size 11 :from 29 :value (reg-to-num r1))
;(:size 11 :from 18 :value (reg-to-num r2))
(:size 29 :from 0 :value imm))))
(onereg . ((r) ,(set-instruction (r1)
(:size 11 :from 29 :value (reg-to-num r1)))))
(alu . ((r r) ,(set-instruction (r1 r2)
(:size 11 :from 29 :value (reg-to-num r1))
(:size 11 :from 18 :value (reg-to-num r2)))))
(argtype0 . ((imm) ,(set-instruction (imm)
(:size 40 :from 0 :value imm))))
(argtype1 . ((r imm) ,(set-instruction (r1 imm)
(:size 11 :from 29 :value (reg-to-num r1))
(:size 29 :from 0 :value imm))))
(branch . ((r imm imm imm) ,(set-instruction (r1 mask flag addr)
(:size 11 :from 29 :value (reg-to-num r1))
(:size 8 :from 21 :value mask)
(:size 8 :from 13 :value flag)
(:size 13 :from 0 :value addr))))
))
;; Get the function from a format type
(defun get-format-function (format)
(second (cdr (assoc format +opcodeformats+))))
;; Add an instruction to the list
(defun add-instruction (opcode args function)
(setf *pre-assembly-data*
(append
(list (list opcode args function))
*pre-assembly-data*)))
;; Define an instruction
;; The generated function returns a list that contains the opcode,
;; the arguments and the function that makes the bit representation.
(defmacro make-instruction (name format opcode)
`(defun ,(intern (format nil "%~A" name)) (&rest args)
(when (eq *assembler-state* :gather)
(incf *assembler-position*))
(let ((f (cdr (assoc ',format +opcodeformats+))))
(when (not f)
(error "Missing opcode group for ~A for instruction ~A" ',format ',name))
(add-instruction ,opcode args f))))
;; Write a 48bit binary value to a stream
(defun write-48bit-unsigned (value s)
(write-byte (ldb (byte 8 40) value) s)
(write-byte (ldb (byte 8 32) value) s)
(write-byte (ldb (byte 8 24) value) s)
(write-byte (ldb (byte 8 16) value) s)
(write-byte (ldb (byte 8 8) value) s)
(write-byte (ldb (byte 8 0) value) s))
;; Assemble our instructions
(defun assemble-it (pre-assembly stream &key output-format simulator-lines)
(let ((pre-assembly (copy-tree (reverse pre-assembly))))
;; Assemble and write out
(format t "Writing out assembly~%")
(let ((instructions (loop for a in pre-assembly
unless (labelp a)
collect (apply (second (third a)) (first a) (second a)))))
(let ((number-of-instructions (length instructions)))
(dolist (inst instructions)
(cond ((eq output-format :human-readable)
(format stream "~12,'0X -- ~48,'0B~%" inst inst))
((eq output-format :simulator)
(format stream "~48,'0B~%" inst))
(t
(write-48bit-unsigned inst stream))))
(when simulator-lines
(dotimes (i (- simulator-lines number-of-instructions))
(format stream "~48,'0B~%" 0)))))))
;; Empty assembler cache
(defun reset-assembler ()
(setf *pre-assembly-data* (list)))
;;; Setup instructions and reset the assembler
(defun setup-assembler ()
(make-instruction nop noarg #x00)
(make-instruction halt noarg #x01)
;; ALU
(make-instruction add alu #x02)
(make-instruction sub alu #x03)
(make-instruction mul alu #x04)
(make-instruction div alu #x05)
(make-instruction and alu #x06)
(make-instruction or alu #x07)
(make-instruction xor alu #x08)
(make-instruction not alu #x09)
(make-instruction shift-l alu #x0A)
(make-instruction mod alu #x0B)
(make-instruction shift-r alu #x0C)
;; Memory
(make-instruction load mem #x10)
(make-instruction store mem #x11)
;; Branch
(make-instruction branch branch #x16)
;; Status
(make-instruction set-flag argtype1 #x17)
(make-instruction clear-flag argtype0 #x18)
(make-instruction get-flag argtype1 #x19)
;; Data
(make-instruction get-type data #x20)
(make-instruction set-type data #x21)
(make-instruction set-type-imm dataimm #x22)
(make-instruction set-datum data #x23)
(make-instruction set-datum-imm dataimm #x24)
(make-instruction get-gc data #x25)
(make-instruction set-gc data #x26)
(make-instruction set-gc-imm dataimm #x27)
(make-instruction cpy data #x28)
;; Compare
(make-instruction cmp-type data #x29)
(make-instruction cmp-type-imm dataimm #x2A)
(make-instruction cmp-datum data #x2B)
(make-instruction cmp-datum-imm dataimm #x2C)
(make-instruction cmp-gc data #x2D)
(make-instruction cmp-gc-imm dataimm #x2E)
(make-instruction cmp data #x2F)
;; Leds
(make-instruction set-leds onereg #x3F)
(reset-assembler)
t)
;; Info gathering or assembling state
;; The first get labels information and so on, the second assemble correct instructions
(defvar *assembler-state*)
(defvar *assembler-labels*)
(defvar *assembler-position*)
;; Debug functions
;; Write labels
(defun write-labels (file labels)
(format t "Writing out label information~%")
(with-open-file (s
(concatenate 'string file ".labels")
:element-type 'character
:direction :output
:if-does-not-exist :create
:if-exists :supersede)
(maphash
(lambda (key value)
(format s "~A ~X~%" key value))
labels)))
;; Write constant information
(defun write-constants (file constants labels)
(format t "Writing constant information~%")
(with-open-file (s
(concatenate 'string file ".const")
:element-type 'character
:direction :output
:if-does-not-exist :create
:if-exists :supersede)
(maphash
(lambda (key value)
(format s "label ~A ~X~%" key value))
labels)
(maphash (lambda (key value)
(declare (ignore key))
(format s "~A~%" (constant-info-to-string value)))
constants)))
;; The main assembly macro
;; Adds inst-prefixes and fixes labels
(defmacro with-assembly ((outfile &key output-format simulator-lines) &body body)
(let ((streamvar (gensym "STREAM")))
`(let ((*assembler-labels* (make-hash-table))
(*assembler-state* :gather)
(*assembler-position* 0))
(setf *assembler-labelnumbers* 0)
,@(loop
for inst in (copy-tree body)
when (not (labelp inst))
collect (rewrite-instruction inst :gather)
when (labelp inst)
collect `(setf (gethash ,inst *assembler-labels*) *assembler-position*))
(setf *assembler-labelnumbers* 0)
(format t "We got ~D instructions~%" *assembler-position*)
(with-open-file (,streamvar ,outfile
:element-type ,(cond ((or (eq output-format :human-readable)
(eq output-format :simulator))
''character)
(t ''unsigned-byte))
:direction :output
:if-does-not-exist :create
:if-exists :supersede)
(setf *assembler-state* :assemble)
(reset-assembler)
,@(loop
for inst in body
when (not (labelp inst))
collect (rewrite-instruction inst :assemble))
;; Write out assembled exectuable
(assemble-it *pre-assembly-data* ,streamvar :output-format ,output-format :simulator-lines ,simulator-lines)
;; Output debug info
(write-constants ,outfile *assembler-constants* *assembler-labels*)
(write-labels ,outfile *assembler-labels*)))))
;;; Microcode instructions
(defmacro with-new-label ((prefix var) &body body)
`(let ((,var (intern (format nil "~A-~A" (string-upcase ,prefix) (next-labelnumber)) (find-package "KEYWORD"))))
,@body))
(defmacro force-label (label)
`(when (labelp ,label)
(if (eq *assembler-state* :gather)
(setf ,label 0)
(progn
(unless (gethash ,label *assembler-labels*)
(error "Unknown label: ~A" ,label))
(setf ,label (gethash ,label *assembler-labels*))))))
(defmacro with-force-label ((label) &body body)
(if (integerp label)
`(progn
,@body)
`(let ((,label ,label))
(force-label ,label)
,@body)))
(defmacro with-force-label* ((var label) &body body)
`(let ((,var ,label))
(force-label ,var)
,@body))
(defmacro %when (comparison &body body)
`(with-new-label ("when" end)
,comparison
(branchimm-false end)
,@body
(make-label end)))
(defmacro %when-not (comparison &body body)
`(with-new-label ("when" end)
,comparison
(branchimm end)
,@body
(make-label end)))
(defmacro when= ((r1 r2) &body body)
`(with-new-label ("when=" end)
(%cmp-datum ,r1 ,r2)
(branchimm-false end)
,@body
(make-label end)))
(defmacro when!= ((r1 r2) &body body)
`(with-new-label ("when=" end)
(%cmp-datum ,r1 ,r2)
(branchimm end)
,@body
(make-label end)))
(defun some-stuff ()
(make-integer 3 4)
(make-integer 4 4)
(when= (3 4)
(make-integer 5 4)))
;; Make a indirect register
(defun indirect-register (reg)
(let ((i reg))
(setf (ldb (byte 1 10) i) 1)
i))
;; Branch
(defmacro %branch* (reg offset &rest flags)
(let ((maskvar (gensym))
(flagvar (gensym)))
`(let ((,maskvar (funcall #'logior ,@(loop for flag in flags
collect (intern (format nil "-BRANCH-~A-" (if (listp flag) (cadr flag) flag))))))
(,flagvar (funcall #'logior ,@(loop for flag in flags
when (not (listp flag))
collect (intern (format nil "-BRANCH-~A-" flag))))))
(%branch ,reg ,maskvar ,flagvar ,offset))))
(defun branchimm* (mask flag addr)
(with-force-label (addr) ;; Hack to fix labels in a few places, sorry about this.
(%branch $zero mask flag addr)))
;; Immediate branch true
(defun branchimm (addr)
(branchimm* #x8 #x8 addr))
;; Immediate branch false
(defun branchimm-false (addr)
(branchimm* #x8 0 addr))
;; Jmp
(defun jump (r addr)
(with-force-label (addr)
(%branch r 0 0 addr)))
(defun jump-imm (addr)
(with-force-label (addr)
(jump $zero addr)))
(defun jump-reg (r)
(jump r 0))
(defun make-object-imm (reg type value)
(%set-type-imm reg type)
(%set-datum-imm reg value))
(defun make-integer (reg value)
(make-object-imm reg +type-int+ value))
(defun %add* (d a b)
(%cpy d a)
(%add d b))
(defun %sub* (d a b)
(%cpy d a)
(%sub d b))
(defun %mul* (d a b)
(%cpy d a)
(%mul d b))
(defun %div* (d a b)
(%cpy d a)
(%div d b))
(defun %mod* (d a b)
(%cpy d a)
(%mod d b))
(defun %and* (d a b)
(%cpy d a)
(%and d b))
(defun %or* (d a b)
(%cpy d a)
(%or d b))
(defun %incr (reg)
(%add reg $one))
(defun %decr (reg)
(%sub reg $one))
(defun labeltest ()
(let ((label (gensym "IF-")))
(make-integer 10 #x5)
(make-label (intern (format nil "~A" label) (find-package "KEYWORD")))))
#|
;; Another simple test function
;; Suppose to be used to define the real API the assembler will have
(defun test-set2 ()
(with-assembly ("/tmp/microcode" :output-format :simulator :simulator-lines 100)
(make-integer 3 4)
(make-integer 4 4)
(when= (3 4)
(make-integer 5 4))
(when!= (3 4)
(make-integer 6 4))))
|#
;; Make microcode instruction functions
(setup-assembler)