# HG changeset patch # User Steve Losh # Date 1479261704 0 # Node ID f7f47291a61aca73fb06dffeb1d35d32b95c1b81 # Parent d7119e2cc512952a12c547c56170a467b884b3a8 Start writing this thing I guess diff -r d7119e2cc512 -r f7f47291a61a .lispwords --- a/.lispwords Tue Nov 15 23:12:46 2016 +0000 +++ b/.lispwords Wed Nov 16 02:01:44 2016 +0000 @@ -0,0 +1,1 @@ +(1 macro-map) diff -r d7119e2cc512 -r f7f47291a61a src/emulator.lisp --- a/src/emulator.lisp Tue Nov 15 23:12:46 2016 +0000 +++ b/src/emulator.lisp Wed Nov 16 02:01:44 2016 +0000 @@ -3,6 +3,286 @@ (setf *print-length* 10) (setf *print-base* 10) (declaim (optimize (speed 1) (safety 3) (debug 3))) -; (declaim (optimize (speed 3) (safety 0) (debug 0))) +(declaim (optimize (speed 3) (safety 0) (debug 3))) + + +;;;; Types -------------------------------------------------------------------- +(deftype int8 () '(unsigned-byte 8)) +(deftype int12 () '(unsigned-byte 12)) +(deftype int16 () '(unsigned-byte 16)) + +(deftype basic-array (element-type size) + `(simple-array ,(upgraded-array-element-type element-type) (,size))) + +(deftype stack (size) + `(vector ,(upgraded-array-element-type 'int12) ,size)) + + +;;;; Utils -------------------------------------------------------------------- +(declaim (inline nibble not= +_8 -_8)) + +(defun make-simple-array (element-type size &rest args) + (apply #'make-array size + :adjustable nil + :fill-pointer nil + :element-type element-type + args)) + +(defun nibble (position integer) + (ldb (byte 4 (* position 4)) integer)) + +(defun not= (x y) + (not (= x y))) + +(defun +_8 (x y) + (let ((result (+ x y))) + (values (ldb (byte 8 0) result) + (if (> result 255) 1 0)))) + +(defun -_8 (x y) + (let ((result (- x y))) + (values (ldb (byte 8 0) result) + (if (> x y) 1 0)))) + + +(defmacro macro-map ((lambda-list items) &rest body) + (with-gensyms (macro) + `(macrolet ((,macro ,(ensure-list lambda-list) ,@body)) + ,@(iterate (for item :in items) + (collect `(,macro ,@(ensure-list item))))))) + + +;;;; Data --------------------------------------------------------------------- +(defstruct chip + (memory (make-simple-array 'int8 4096) + :type (basic-array int8 4096) + :read-only t) + (registers (make-simple-array 'int8 16) + :type (basic-array int8 16) + :read-only t) + (video (make-simple-array 'fixnum #.(* 64 32)) + :type (basic-array fixnum #.(* 64 32)) + :read-only t) + (video-dirty t :type boolean) + (keys (make-simple-array 'boolean 16) + :type (basic-array boolean 16) + :read-only t) + (index 0 :type int16) + (program-counter 0 :type int12) + (delay-timer 0 :type int8) + (sound-timer 0 :type int8) + (random-state (make-random-state t) + :type random-state + :read-only t) + (stack (make-array 16 + :adjustable nil + :fill-pointer 0 + :element-type 'int12) + :type (stack 16))) + +(define-with-macro chip + memory registers video keys + index program-counter + delay-timer sound-timer + random-state + video-dirty + stack) + + +;;;; Opcodes ------------------------------------------------------------------ +(defun parse-opcode-argument-bindings (argument-list) + (flet ((normalize-arg (arg) + (destructuring-bind (symbol &optional (nibbles 1)) + (ensure-list arg) + (list symbol nibbles)))) + (iterate + (for (symbol nibbles) :in (mapcar #'normalize-arg argument-list)) + (for position :first 3 :then (- position nibbles)) + (when (not (eql symbol '_)) + (collect `(,symbol (ldb (byte ,(* nibbles 4) + ,(* position 4)) + opcode))))))) + +(defmacro define-opcode (name argument-list &body body) + `(progn + (declaim (ftype (function (chip int16) + (values null &optional)) + ,name)) + (defun ,name (chip opcode) + (declare (ignorable opcode)) + (with-chip (chip) + (macrolet ((register (index) + `(aref registers ,index))) + (let ,(parse-opcode-argument-bindings argument-list) + ,@body)) + nil)))) +(macro-map ;; LD ... + ((name arglist destination source) + ((op-ld-i