Possibilité d'avoir plusieurs VM qui s'exécutent tour à tour + nettoyage.

This commit is contained in:
Georges Dupéron 2010-10-15 22:22:50 +02:00
parent be4c1636b7
commit 6e55560dfd

View File

@ -1,128 +1,118 @@
;; "objet" VM.
;; Instanciation :
;; (defvar vm (make-vm 100))
;; Appels de méthode :
;; (send vm get-memory 42)
;; (send vm set-memory 42 5)
;; (send vm get-register R1)
;; (send vm set-register R2 (send vm get-register 42))
(defun make-vm (size)
(let* ((memory (make-array size :initial-element 0))
(registres `(;; Registres généraux.
(R0 . 0)
(R1 . 0)
(R2 . 0)
;; Base de la pile.
(BP . 0)
;; Sommet de la pile.
(SP . 0)
;; Pointeur de code : fin de la mémoire.
(PC . ,(- size 1))
;; registres booléens = faux (nil).
(PP . nil)
(EQ . nil)
(PG . nil)
;; Quand HALT passe à t, on arrête la machine.
(HALT . nil)))
(actions `((get-memory . ,(lambda (index) (aref memory index)))
(set-memory . ,(lambda (index value) (setf (aref memeory index) value)))
(get-register . ,(lambda (reg) (cdr (assoc reg registres))))
(set-register . ,(lambda (reg) (setf (cdr (get-register reg))))))))
(lambda (message &rest params)
(apply (assoc message actions) params))))
;; TODO : Penser a cree une fonction qui initialise un tableau en fonction d'un parametre. (defun send (obj &rest params)
(setq memory (make-array 100)) (apply obj params))
(defun getValueInMemory (index) (defun get-memory (vm index) (send vm get-memory index))
(aref memory index)) (defun set-memory (vm index value) (send vm get-memory index value))
(defun get-register (vm register) (send vm get-register register))
(defun set-register (vm register value) (send vm set-register register value))
(defun setValueInMemory (index value) (defun LOAD (vm address register)
(setf (aref memory index) value)) (set-register vm register (get-memory vm address)))
(defun STORE (vm register address)
(set-memory vm address (get-register vm register)))
;;On initialise les registres a rien (peut etre faut il mettre 0 ?) (defun MOVE (vm reg1 reg2)
(setf R0 nil) (set-register vm reg2 (get-register vm reg1)))
(setf R1 nil)
(setf R2 nil)
;; On initialise le registre de pointeur de base a l'indice 0 du tableau memory (defun _OP_ (vm op reg1 reg2)
(setf BP 0) (set-register vm reg2 (funcall op
;; On initialise le registre de pointeur de pile a la valeur du pointeur de base (get-register vm reg2)
(setf SP BP) (get-register vm reg1))))
;; On initialise le registre du compteur ordinale a la taille du tableau - 1
;; TODO : Recupere la taille du tableau dynamiquement.
(setf PC 99)
;; On initialise les registres booleen a faux (nil) (defun ADD (vm reg1 reg2) (_OP_ vm #'+ reg1 reg2))
(setf PP nil) (defun SUB (vm reg1 reg2) (_OP_ vm #'- reg1 reg2))
(setf EQ nil) (defun MULT (vm reg1 reg2) (_OP_ vm #'* reg1 reg2))
(setf PG nil) (defun DIV (vm reg1 reg2) (_OP_ vm #'/ reg1 reg2))
(defun LOAD (address register) (defun INCR (vm register)
(setf register (getValueInMemory address))) (set-register vm register (+ (get-register vm register) 1)))
(defun STORE (register address) (defun DECR (vm register)
(setValueInMemory address register)) (set-register vm register (- (get-register vm register) 1)))
;; TODO : Remplir la fonction MOVE (defun PUSH (vm register)
(defun MOVE (reg1 reg2) (INCR vm 'SP)
) (STORE vm register (get-register vm 'SP)))
(defun ADD (reg1 reg2) (defun POP (vm register)
(setf reg2 (+ reg2 reg1))) (LOAD vm (get-register vm 'SP) register)
(DECR vm 'SP))
(defun SUB (reg1 reg2) (defun JMP (vm dst)
(setf reg2 (- reg2 reg1))) (set-register vm 'PC dst))
(defun MULT (reg1 reg2) (defun JSR (vm dst)
(setf reg2 (* reg2 reg1))) (PUSH vm 'PC)
(JMP vm dst))
(defun DIV (reg1 reg2)
(setf reg2 (/ reg2 reg1)))
(defun INCR (register)
(setf register (+ register 1)))
(defun DECR (register)
(setf register (- register 1)))
(defun PUSH (register)
(progn (INCR SP)
(STORE register SP)))
(defun POP (register)
(progn (LOAD SP register)
(DECR SP)))
;; TODO : Remplir la fonction JMP
(defun JMP (dst)
)
;; TODO : Remplir la fonction JSR
(defun JSR (dst)
)
;; TODO : Remplir la fonction RTN ;; TODO : Remplir la fonction RTN
(defun RTN () (defun RTN (vm)
) (POP vm 'PC))
(defun CMP (reg1 reg2) (defun CMP (vm reg1 reg2)
(cond ((= (getValueInMemory reg1) (getValueInMemory reg2)) (set-register vm 'EQ (= (get-register vm reg1) (get-register vm reg2)))
(progn (setf EQ T) (set-register vm 'PP (< (get-register vm reg1) (get-register vm reg2)))
(setf PP nil) (set-register vm 'PG (> (get-register vm reg1) (get-register vm reg2))))
(setf PG nil)))
((< (getValueInMemory reg1) (getValueInMemory reg2))
(progn (setf EQ nil)
(setf PP T)
(setf PG nil)))
(T
(progn (setf EQ nil)
(setf PP nil)
(setf PG T)))))
(defun JEQ (label) (defun _JCOND_ (vm pp eq pg vm dst)
(if EQ (if (or (and eq (get-register vm 'EQ))
(JMP label)) (and pg (get-register vm 'PG))
) (and pp (get-register vm 'PP)))
(JMP vm dst)))
(defun JPG (label) (defun JEQ (vm dst)
(if PG (_JCOND_ vm nil t nil vm dst))
(JMP label))
)
(defun JPP (label) (defun JPG (vm dst)
(if PP (_JCOND_ vm nil nil t vm dst))
(JMP label))
)
(defun JPE (label) (defun JPP (vm dst)
(if (or PP EQ) (_JCOND_ vm t nil nil vm dst))
(JMP label))
)
(defun JGE (label) (defun JPE (vm dst)
(if (or PG EQ) (_JCOND_ vm t t nil vm dst))
(JMP label))
)
(defun JNE (label) (defun JPE (vm dst)
(if (not EQ) (_JCOND_ vm nil t t vm dst))
(JMP label))
)
;; TODO : Remplir la fonction NOP (defun JNE (vm dst)
(defun NOP () (_JCOND_ vm t nil t vm dst))
)
;; TODO : Remplir la fonction HALT (defun NOP (vm))
(defun HALT ()
) (defun HALT (vm)
(set-register vm 'HALT t))