anchor.diff:         (let ((enum ,enum))
            (gethash key enum)))))
   
  -(defgeneric reset (obj)
  -  (:documentation "Reset the OBJ to an initial state.")
  -  (:method (obj) (initialize-instance obj)))
  -
  -(defgeneric nmi (obj)
  -  (:documentation "Generate a non-maskable interrupt. Used for vblanking in NES.")
  -  (:method (obj)
  -    (stack-push-word (cpu-pc obj) obj)
  -    (stack-push (cpu-sr obj) obj)
  -    (setf (cpu-pc obj) (get-word #xfffa))))
  -
  -(defun get-instruction (opcode)
  -  "Get the mnemonic for OPCODE. Returns a symbol to be funcalled or nil."
  -  (first (aref *opcodes* opcode)))
  -
  -(declaim (inline wrap-byte wrap-word wrap-page))
  -(defun wrap-byte (val)
  -  "Wrap the given value to ensure it conforms to (typep val 'u16),
  -e.g. a Stack Pointer or general purpose register."
  -  (logand val #xff))
  -
  -(defun wrap-word (val)
  -  "Wrap the given value to ensure it conforms to (typep val 'u16),
  -e.g. a Program Counter address."
  -  (logand val #xffff))
  -
  -(defun wrap-page (address)
  -  "Wrap the given ADDRESS, ensuring that we don't cross a page boundary.
  -e.g. When the last two bytes of ADDRESS are #xff."
  -  (+ (logand address #xff00) (logand (1+ address) #xff)))
  -
  -(defun get-byte (address)
  -  "Get a byte from RAM at the given address."
  -  (aref *ram* address))
  -
  -(defun (setf get-byte) (new-val address)
  -  "Set ADDRESS in *ram* to NEW-VAL."
  -  (setf (aref *ram* address) new-val))
  -
  -(defun get-word (address &optional wrap-p)
  -  "Get a word from RAM starting at the given address."
  -  (+ (get-byte address)
  -     (ash (get-byte (if wrap-p (wrap-page address) (1+ address))) 8)))
  -
  -(defun (setf get-word) (new-val address)
  -  "Set ADDRESS and (1+ ADDRESS) in *ram* to NEW-VAL, little endian ordering."
  -  (setf (get-byte address) (wrap-byte (ash new-val -8))
  -        (get-byte (1+ address)) (wrap-byte new-val)))
  -
  -(defun get-range (start &optional end)
  -  "Get a range of bytes from RAM, starting from START and stopping at END if
  -provided."
  -  (subseq *ram* start end))
  -
  -(defun (setf get-range) (bytevector start)
  -  "Replace the contents of RAM, starting from START with BYTEVECTOR."
  -  (setf (subseq *ram* start (+ start (length bytevector))) bytevector))
  -
  -(declaim (inline stack-push stack-pop))
  -(defun stack-push (value cpu)
  -  "Push the given VALUE on the stack and decrement the SP."
  -  (setf (get-byte (+ (cpu-sp cpu) #x100)) (wrap-byte value))
  -  (setf (cpu-sp cpu) (wrap-byte (1- (cpu-sp cpu)))))
  -
  -(defun stack-push-word (value cpu)
  -  "Push the 16-bit word VALUE onto the stack."
  -  (stack-push (wrap-byte (ash value -8)) cpu)
  -  (stack-push (wrap-byte value) cpu))
  -
  -(defun stack-pop (cpu)
  -  "Pop the value pointed to by the SP and increment the SP."
  -  (setf (cpu-sp cpu) (wrap-byte (1+ (cpu-sp cpu))))
  -  (get-byte (+ (cpu-sp cpu) #x100)))
  -
  -(defun stack-pop-word (cpu)
  -  "Pop a 16-bit word off the stack."
  -  (+ (stack-pop cpu) (ash (stack-pop cpu) 8)))
  -
   (defenum status-bit (:carry :zero :interrupt :decimal
                        :break :unused :overflow :negative))
   
  
positive.code: 
  ;;; Helpers
  
  (defmacro defenum (name (&rest keys))
    "Define a function named %NAME, that takes KEY as an arg and returns the
  index of KEY. KEYS should be scalar values."
  
negative.code: MODES is a list of opcode metadata lists: (opcode cycles bytes mode)."
    `(progn
       (eval-when (:compile-toplevel :load-toplevel)
         ,@(loop for (op cycles bytes mode) in modes collect
             `(setf (aref *opcodes* ,op) ',(list name cycles bytes mode raw))))
       (defun ,name (cpu cycles bytes mode style)
         ,docs
         (incf (cpu-pc cpu))
  