# HG changeset patch # User Steve Losh # Date 1479991502 0 # Node ID 2e803dec5d585ef3f8e94df33b77d89912f7493f # Parent 503bfe5cd173635960978e91c5d9e4fcd884d074 Attempt at a crazy DSL thing for opcodes. diff -r 503bfe5cd173 -r 2e803dec5d58 .lispwords --- a/.lispwords Tue Nov 22 21:41:34 2016 +0000 +++ b/.lispwords Thu Nov 24 12:45:02 2016 +0000 @@ -1,1 +1,2 @@ (1 macro-map) +(2 recompile-instruction-function) diff -r 503bfe5cd173 -r 2e803dec5d58 cl-chip8.asd --- a/cl-chip8.asd Tue Nov 22 21:41:34 2016 +0000 +++ b/cl-chip8.asd Thu Nov 24 12:45:02 2016 +0000 @@ -18,6 +18,7 @@ :qtgui :qtools :qtopengl + :trivia ) :serial t diff -r 503bfe5cd173 -r 2e803dec5d58 package.lisp --- a/package.lisp Tue Nov 22 21:41:34 2016 +0000 +++ b/package.lisp Thu Nov 24 12:45:02 2016 +0000 @@ -3,6 +3,7 @@ :cl :losh :iterate + :trivia :cl-arrows :chip8.quickutils) (:export)) diff -r 503bfe5cd173 -r 2e803dec5d58 src/emulator.lisp --- a/src/emulator.lisp Tue Nov 22 21:41:34 2016 +0000 +++ b/src/emulator.lisp Thu Nov 24 12:45:02 2016 +0000 @@ -79,6 +79,9 @@ ,@(iterate (for item :in items) (collect `(,macro ,@(ensure-list item))))))) +(defun required () + (error "Required")) + ;;;; Data --------------------------------------------------------------------- (declaim @@ -149,53 +152,8 @@ ;;;; Disassembler ------------------------------------------------------------- (defun disassemble-instruction (instruction) - (flet ((v (n) (symb 'v (format nil "~X" n)))) - (let ((_x__ (ldb (byte 4 8) instruction)) - (__x_ (ldb (byte 4 4) instruction)) - (___x (ldb (byte 4 0) instruction)) - (__xx (ldb (byte 8 0) instruction)) - (_xxx (ldb (byte 12 0) instruction))) - (case (logand #xF000 instruction) - (#x0000 (case instruction - (#x00E0 '(cls)) - (#x00EE '(ret)))) - (#x1000 `(jp ,_xxx)) - (#x2000 `(call ,_xxx)) - (#x3000 `(se ,(v _x__) ,__xx)) - (#x4000 `(sne ,(v _x__) ,__xx)) - (#x5000 (case (logand #x000F instruction) - (#x0 `(se ,(v _x__) ,(v __x_))))) - (#x6000 `(ld ,(v _x__) ,__xx)) - (#x7000 `(add ,(v _x__) ,__xx)) - (#x8000 (case (logand #x000F instruction) - (#x0 `(ld ,(v _x__) ,(v __x_))) - (#x1 `(or ,(v _x__) ,(v __x_))) - (#x2 `(and ,(v _x__) ,(v __x_))) - (#x3 `(xor ,(v _x__) ,(v __x_))) - (#x4 `(add ,(v _x__) ,(v __x_))) - (#x5 `(sub ,(v _x__) ,(v __x_))) - (#x6 `(shr ,(v _x__) ,(v __x_))) - (#x7 `(subn ,(v _x__) ,(v __x_))) - (#xE `(shl ,(v _x__) ,(v __x_))))) - (#x9000 (case (logand #x000F instruction) - (#x0 `(sne ,(v _x__) ,(v __x_))))) - (#xA000 `(ld i ,_xxx)) - (#xB000 `(jp ,(v 0) ,_xxx)) - (#xC000 `(rnd ,(v _x__) ,__xx)) - (#xD000 `(drw ,(v _x__) ,(v __x_) ,___x)) - (#xE000 (case (logand #x00FF instruction) - (#x9E `(skp ,(v _x__))) - (#xA1 `(sknp ,(v _x__))))) - (#xF000 (case (logand #x00FF instruction) - (#x07 `(ld ,(v _x__) dt)) - (#x0A `(ld ,(v _x__) k)) - (#x15 `(ld dt ,(v _x__))) - (#x18 `(ld st ,(v _x__))) - (#x1E `(add i ,(v _x__))) - (#x29 `(ld f ,(v _x__))) - (#x33 `(ld b ,(v _x__))) - (#x55 `(ld (mem i) ,_x__)) - (#x65 `(ld ,_x__ (mem i))))))))) + (declare (ignore instruction)) + nil) (defun bit-diagram (integer) (iterate (for high-bit :from 15 :downto 8) @@ -372,6 +330,20 @@ ;;;; Opcodes ------------------------------------------------------------------ +(defparameter *opcodes* (make-hash-table)) + +(defun dispatch-instruction (chip opcode) + (declare (ignore chip opcode)) + nil) + +(defstruct opcode + (pattern (required) :type keyword) + (matcher (required) :type list) + (function-name (required) :type symbol) + (arglist (required) :type list) + (bindings (required) :type list) + (format-info (required) :type list)) + (eval-when (:compile-toplevel :load-toplevel :execute) (defun parse-opcode-argument-bindings (argument-list) (flet ((normalize-arg (arg) @@ -384,9 +356,48 @@ (when (not (eql symbol '_)) (collect `(,symbol (ldb (byte ,(* nibbles 4) ,(* position 4)) - opcode)))))))) + opcode))))))) + + (defun parse-opcode-matcher (opcode) + (map 'list (lambda (char) + (or (digit-char-p char 16) '_)) + (symbol-name opcode))) + + (defun record-opcode (opcode function-name arglist format-info) + (setf (gethash function-name *opcodes*) + (make-opcode :pattern opcode + :matcher (parse-opcode-matcher opcode) + :function-name function-name + :arglist arglist + :bindings (parse-opcode-argument-bindings arglist) + :format-info format-info))) -(defmacro define-opcode (name argument-list &body body) + (defmacro recompile-instruction-matcher + (function arglist opcode-info-symbol clause-body) + `(compile ',function + `(lambda ,',arglist + (match* ((ldb (byte 4 12) opcode) + (ldb (byte 4 8) opcode) + (ldb (byte 4 4) opcode) + (ldb (byte 4 0) opcode)) + ,@(iterate (for (nil ,opcode-info-symbol) :in-hashtable *opcodes*) + (collect (list (opcode-matcher ,opcode-info-symbol) + ,clause-body))))))) + + (defun recompile-disassemble-instruction () + (recompile-instruction-matcher disassemble-instruction + (opcode) + op-info + `(let (,@(opcode-bindings op-info)) + (format nil ,@(opcode-format-info op-info))))) + + (defun recompile-dispatch-instruction () + (recompile-instruction-matcher dispatch-instruction + (chip opcode) + op-info + `(,(opcode-function-name op-info) chip opcode)))) + +(defmacro define-opcode (opcode name argument-list format-info &body body) `(progn (declaim (ftype (function (chip int16) (values null &optional)) @@ -398,95 +409,100 @@ `(aref registers ,index))) (let ,(parse-opcode-argument-bindings argument-list) ,@body)) - nil)))) + nil)) + (record-opcode ,opcode ',name ',argument-list ',format-info) + (recompile-disassemble-instruction) + (recompile-dispatch-instruction) + ',name)) -(macro-map ;; LD ... - ((name arglist destination source) - ((op-ld-i