+ (error "Unrecognised opcode" (instr 'opcode))))))
+
+(define (compare-instrs A-ptr B-ptr modifier test)
+ (let ((A-instr (core-get A-ptr))
+ (B-instr (core-get B-ptr)))
+ (case modifier
+ ((A) (test (A-instr 'A-num) (B-instr 'A-num)))
+ ((B) (test (A-instr 'B-num) (B-instr 'B-num)))
+ ((AB) (test (A-instr 'A-num) (B-instr 'B-num)))
+ ((BA) (test (A-instr 'B-num) (B-instr 'A-num)))
+ ((F) (and
+ (test (A-instr 'A-num) (B-instr 'A-num))
+ (test (A-instr 'B-num) (B-instr 'B-num))))
+ ((X) (and
+ (test (A-instr 'A-num) (B-instr 'B-num))
+ (test (A-instr 'B-num) (B-instr 'A-num))))
+ ((I) (and
+ (if (eq? test =)
+ (and
+ (eq? (A-instr 'opcode) (B-instr 'opcode))
+ (eq? (A-instr 'modifier) (B-instr 'modifier))
+ (eq? (A-instr 'A-mode) (B-instr 'B-mode))
+ (eq? (A-instr 'B-mode) (B-instr 'A-mode)))
+ #t)
+ (test (A-instr 'A-num) (B-instr 'B-num))
+ (test (A-instr 'B-num) (B-instr 'A-num)))))))
+
+(define (instr-zero? ptr modifier decrement)
+ (let ((instr (core-get ptr)))
+ (case modifier
+ ((A AB)
+ (if decrement (instr 'set-A-num! (addr+ (instr 'A-num) -1)))
+ (= 0 (instr 'A-num)))
+ ((A AB)
+ (if decrement (instr 'set-B-num! (addr+ (instr 'B-num) -1)))
+ (= 0 (instr 'B-num)))
+ ((X I F)
+ (if decrement
+ (begin
+ (instr 'set-A-num! (addr+ (instr 'A-num) -1))
+ (instr 'set-B-num! (addr+ (instr 'B-num) -1))))
+ (and (= 0 (instr 'A-num))
+ (= 0 (instr 'B-num)))))))
+
+(define (combine-and-store core A-ptr B-ptr modifier name f)
+ (case modifier
+ ((A) (core B-ptr 'set! 'A-num
+ (f (core B-ptr 'A-num) (core A-ptr 'A-num)) name))
+ ((B) (core B-ptr 'set! 'B-num
+ (f (core B-ptr 'B-num) (core A-ptr 'B-num)) name))
+ ((AB) (core B-ptr 'set! 'B-num
+ (f (core B-ptr 'B-num) (core A-ptr 'A-num)) name))
+ ((BA) (core B-ptr 'set! 'A-num
+ (f (core B-ptr 'A-num) (core A-ptr 'B-num)) name))
+ ((F I) (core B-ptr 'set! 'A-num
+ (f (core B-ptr 'A-num) (core A-ptr 'A-num)) name)
+ (core B-ptr 'set! 'B-num
+ (f (core B-ptr 'B-num) (core A-ptr 'B-num)) name))
+ ((X) (core B-ptr 'set! 'A-num
+ (f (core B-ptr 'A-num) (core A-ptr 'B-num)) name)
+ (core B-ptr 'set! 'B-num
+ (f (core B-ptr 'B-num) (core A-ptr 'A-num)) name))))
+
+(define (eval-operand core mode num ptr name)
+ (addr+ ptr
+ (case mode
+ ((immediate) 0)
+ ((direct) num)
+ ((indirect-A) (addr+ num (core (addr+ ptr num) 'A-num)))
+ ((indirect-B) (addr+ num (core (addr+ ptr num) 'B-num)))
+ ((pre-indirect-A)
+ (let ((aux-ptr (addr+ ptr num)))
+ (core aux-ptr 'set! 'A-num (addr+ -1 (core aux-ptr 'A-num)) name)
+ (addr+ num (core aux-ptr 'A-num))))
+ ((pre-indirect-B)
+ (let ((aux-ptr (addr+ ptr num)))
+ (core aux-ptr 'set! 'B-num (addr+ -1 (core aux-ptr 'B-num)) name)
+ (addr+ num (core aux-ptr 'B-num))))
+ ((post-indirect-A)
+ (let* ((aux-ptr (addr+ ptr num))
+ (old-A-num (core aux-ptr 'A-num)))
+ (core aux-ptr 'set! 'A-num (addr+ 1 (core aux-ptr 'A-num)) name)
+ (addr+ num old-A-num)))
+ ((post-indirect-B)
+ (let* ((aux-ptr (addr+ ptr num))
+ (old-B-num (core aux-ptr 'B-num)))
+ (core aux-ptr 'set! 'B-num (addr+ 1 (core aux-ptr 'B-num)) name)
+ (addr+ num old-B-num)))
+ (else
+ (error "Unrecognized mode" mode)))))
+
+;;; Main procedure
+;;
+
+;;; TEST CODE
+
+(define addressing-test
+ (make-prog 'at (list
+ (make-instr 'DAT 'F 'immediate 42 'immediate 53 'at)
+ (make-instr 'DAT 'F 'immediate 123 'immediate 256 'at)
+ (make-instr 'MOV 'A 'indirect-B 4 'direct 7 'at)
+ (make-instr 'NOP 'I 'immediate 0 'immediate 0 'at)
+ (make-instr 'NOP 'I 'immediate 0 'immediate 0 'at)
+ (make-instr 'NOP 'I 'immediate 0 'immediate 0 'at)
+ (make-instr 'DAT 'F 'immediate -5 'immediate -6 'at)) 2))
+
+(define imp
+ (make-prog 'imp (list (make-instr 'MOV 'I 'direct 0 'direct 1 'imp)) 0))
+
+(define dwarf
+ (make-prog 'dwarf (list
+ (make-instr 'DAT 'F 'immediate 0 'immediate -1 'dwarf)
+ (make-instr 'ADD 'AB 'immediate 5 'direct -1 'dwarf)
+ (make-instr 'MOV 'I 'direct -2 'indirect-B -2 'dwarf)
+ (make-instr 'JMP 'I 'immediate -2 'immediate 0 'dwarf)) 1))
+
+(initialize-core)
+(define players (install-progs (list dwarf imp)))
+
+(dump-core)