;;; -*- Mode:LISP; Package:SIM; Readtable:CL; Base:10 -*-

; dest, s1, s2 could be:
;   (open 4)
;   (active 2)
;   (return 0)
;   (global 555)

; (alu dest <- s1 aluop s2)
; (jump condition target)
; (jump-xct-next condition target)

(defun parse-reg-adr (reg-adr &aux (limit *registers-per-frame*) base-code offset immediate)
  (declare (values base offset immediate))
  (setq offset (cadr reg-adr))
  (when (< offset 0) (ferror nil "bad offset"))
  (ecase (car reg-adr)
    (open
     (setq base-code %i-base-open))
    (active
     (setq base-code %i-base-active))
    (return
     (setq base-code %i-base-return))
    (global
     (setq base-code %i-base-global)
     (setq limit (* *registers-per-frame* *total-frames*))
     (setq immediate (floor offset *registers-per-frame*))
     (setq offset (remainder offset *registers-per-frame*))))
  (when (>= offset limit)
    (ferror nil "bad reg adr"))
  (values base-code offset immediate))
     

(defstruct (alu-inst (:type :list))
  flag
  dest
  arrow
  s1
  aluop
  s2)

(defun assemble-instruction (sym-inst &aux (val 0))
  (ecase (car sym-inst)
    (alu
     (let (base-code offset immediate old-immediate)
       ;;dest
       (multiple-value (base-code offset old-immediate)
	 (parse-reg-adr (alu-inst-dest sym-inst)))
       (setq val (dpb base-code %%i-dest-base val))
       (setq val (dpb offset %%i-dest-offset val))
       
       ;;s1
       (multiple-value (base-code offset immediate)
	 (parse-reg-adr (alu-inst-s1 sym-inst)))
       (setq val (dpb base-code %%i-src-1-base val))
       (setq val (dpb offset %%i-src-1-offset val))
       (when (and immediate old-immediate
		  (not (= immediate old-immediate)))
	 (ferror nil "inconsistant global bases"))

       ;;s2
       (multiple-value (base-code offset immediate)
	 (parse-reg-adr (alu-inst-s2 sym-inst)))
       (setq val (dpb base-code %%i-src-2-base val))
       (setq val (dpb offset %%i-src-2-offset val))
       (when (and immediate old-immediate
		  (not (= immediate old-immediate)))
	 (ferror nil "inconsistant global bases"))

       (ecase (alu-inst-aluop sym-inst)
	 (setz (setq val (dpb %i-aluf-setz %%i-aluf val)))
	 (add (setq val (dpb %i-aluf-add %%i-aluf val)))
	 )
       ))
    )
  val)
       
	 