|
|
@@ -3,12 +3,13 @@ |
|
|
|
(struct mem |
|
|
|
(regs pc sp flags bank)) |
|
|
|
|
|
|
|
(define (make-mem) |
|
|
|
(mem (make-regs) |
|
|
|
0 |
|
|
|
0 |
|
|
|
0 |
|
|
|
(make-bank))) |
|
|
|
(define (make-mem [start #x00] [bs '()]) |
|
|
|
(set-bytes start bs |
|
|
|
(mem (make-regs) |
|
|
|
start |
|
|
|
0 |
|
|
|
0 |
|
|
|
(make-bank)))) |
|
|
|
|
|
|
|
(define (make-regs) |
|
|
|
(make-vector 8 0)) |
|
|
@@ -38,8 +39,8 @@ |
|
|
|
(struct-copy mem m [bank newbank])))) |
|
|
|
(error "unknown register index"))) |
|
|
|
|
|
|
|
(define (make-bank) |
|
|
|
(make-vector 65536 #x00)) |
|
|
|
(define (make-bank [def #x00]) |
|
|
|
(make-vector 65536 def)) |
|
|
|
|
|
|
|
(define (mod-8bit val) |
|
|
|
(modulo val 256)) |
|
|
@@ -51,6 +52,10 @@ |
|
|
|
(begin |
|
|
|
(struct-copy mem m [pc (mod-16bit addr)]))) |
|
|
|
|
|
|
|
(define (set-flags f m) |
|
|
|
(begin |
|
|
|
(struct-copy mem m [flags (mod-8bit f)]))) |
|
|
|
|
|
|
|
(define (get-byte addr m) |
|
|
|
(let ([b (mem-bank m)]) |
|
|
|
(if (and (>= addr 0) |
|
|
@@ -74,16 +79,50 @@ |
|
|
|
(cdr bs) |
|
|
|
(set-byte addr (car bs) m)))) |
|
|
|
|
|
|
|
(define (get-x byte) |
|
|
|
(arithmetic-shift (bitwise-and #b11000000 byte) -6)) |
|
|
|
|
|
|
|
(define (get-y byte) |
|
|
|
(arithmetic-shift (bitwise-and #b00111000 byte) -3)) |
|
|
|
|
|
|
|
(define (get-z byte) |
|
|
|
(bitwise-and #b00000111 byte)) |
|
|
|
|
|
|
|
(define (inc-sp m) |
|
|
|
(struct-copy mem m [sp (add1 (mem-sp m))])) |
|
|
|
|
|
|
|
(define (inc-pc m) |
|
|
|
(struct-copy mem m [pc (add1 (mem-pc m))])) |
|
|
|
|
|
|
|
|
|
|
|
(define (make-16b-addr x y) |
|
|
|
(bitwise-ior y (arithmetic-shift x 8))) |
|
|
|
|
|
|
|
(define (make-8b-ld-reg-imm y m) |
|
|
|
(letrec ([pc (mem-pc m)] |
|
|
|
[x (get-byte pc m)]) |
|
|
|
(cons (8b-ld-reg-imm y x) |
|
|
|
(set-pc (add1pc pc) m)))) |
|
|
|
|
|
|
|
(define (make-8b-ld-reg-reg y z m) |
|
|
|
(cons (8b-ld-reg-reg y z) |
|
|
|
m)) |
|
|
|
|
|
|
|
(define (make-alu-imm z m) |
|
|
|
(letrec ([pc (mem-pc m)] |
|
|
|
[x (get-byte pc m)]) |
|
|
|
(cons (case z |
|
|
|
[(4) (8b-and-imm x)] |
|
|
|
[(5) (8b-xor-imm x)] |
|
|
|
[(6) (8b-or-imm x)] |
|
|
|
[else (nop)]) |
|
|
|
(inc-pc m)))) |
|
|
|
|
|
|
|
(define (make-nop m) |
|
|
|
(cons (nop) m)) |
|
|
|
|
|
|
|
(define (make-stop m) |
|
|
|
(cons 'STOP m)) |
|
|
|
|
|
|
|
(define (8b-ld-reg-imm reg imm) |
|
|
|
(lambda (m) |
|
|
|
(set-reg reg imm m))) |
|
|
@@ -94,6 +133,33 @@ |
|
|
|
(get-reg src m) |
|
|
|
m))) |
|
|
|
|
|
|
|
(define (8b-xor-imm imm) |
|
|
|
(lambda (m) |
|
|
|
(let ([a (bitwise-xor (get-reg 7 m) |
|
|
|
(mod-8bit imm))]) |
|
|
|
(displayln (format "~a xor ~a = ~a" (display-byte-hex (get-reg 7 m)) |
|
|
|
(display-byte-hex (mod-8bit imm)) |
|
|
|
a)) |
|
|
|
(set-flags (if (= a 0) #b10000000 #x00) |
|
|
|
(set-reg 7 a m))))) |
|
|
|
|
|
|
|
(define (8b-or-imm imm) |
|
|
|
(lambda (m) |
|
|
|
(let ([a (bitwise-ior (get-reg 7 m) |
|
|
|
(mod-8bit imm))]) |
|
|
|
(set-flags (if (= a 0) #b10000000 #x00) |
|
|
|
(set-reg 7 a m))))) |
|
|
|
|
|
|
|
(define (8b-and-imm imm) |
|
|
|
(lambda (m) |
|
|
|
(let ([a (bitwise-and (get-reg 7 m) |
|
|
|
(mod-8bit imm))]) |
|
|
|
(set-flags (if (= a 0) #b10000000 #x00) |
|
|
|
(set-reg 7 a m))))) |
|
|
|
|
|
|
|
(define (nop) |
|
|
|
(lambda (m) m)) |
|
|
|
|
|
|
|
(define (display-byte-hex v) |
|
|
|
(~a #:align 'right #:left-pad-string "0" #:width 2 |
|
|
|
(format "~x" v))) |
|
|
@@ -134,7 +200,7 @@ |
|
|
|
(define (print-mem v) |
|
|
|
(display (format " $~a" (display-byte-hex v)))) |
|
|
|
(let ([s (display-word-hex start)] |
|
|
|
[e (display-word-hex (mod-16bit (+ start count)))]) |
|
|
|
[e (display-word-hex (mod-16bit (+ start (sub1 count))))]) |
|
|
|
(display (format "$~a >" s)) |
|
|
|
(let ([splice (vector-take |
|
|
|
(vector-drop (mem-bank m) start) |
|
|
@@ -143,6 +209,46 @@ |
|
|
|
(display (format " < $~a\n" e) )) |
|
|
|
(void)) |
|
|
|
|
|
|
|
(define (add1pc pc) |
|
|
|
(mod-16bit (add1 pc))) |
|
|
|
|
|
|
|
(define (within x y z) |
|
|
|
(and (>= x y) (<= x z))) |
|
|
|
|
|
|
|
(define (decode-op m) |
|
|
|
(letrec ([pc (mem-pc m)] |
|
|
|
[op (get-byte pc m)] |
|
|
|
[npc (add1pc pc)] |
|
|
|
[x (get-x op)] |
|
|
|
[y (get-y op)] |
|
|
|
[z (get-z op)]) |
|
|
|
(cond |
|
|
|
[(= #x00 op) (make-nop (set-pc npc m))] |
|
|
|
[(= #x10 op) (make-stop (set-pc npc m))] |
|
|
|
[(= 1 x) |
|
|
|
(make-8b-ld-reg-reg y z (set-pc npc m))] |
|
|
|
[(and (= 3 x) (within z 4 6)) |
|
|
|
(make-alu-imm y (set-pc npc m))] |
|
|
|
[(and (= 0 x) (= 6 z)) |
|
|
|
(make-8b-ld-reg-imm y (set-pc npc m))] |
|
|
|
[else (make-nop (set-pc npc m))]))) |
|
|
|
|
|
|
|
(define (run-vm start bank-start bank-count bs) |
|
|
|
(let ([m (make-mem start bs)]) |
|
|
|
(define (fin m) |
|
|
|
(begin (print-state m) |
|
|
|
(print-regs m) |
|
|
|
(print-part-bank bank-start bank-count m))) |
|
|
|
(define (run-op m) |
|
|
|
(letrec ([op-pc (decode-op m)] |
|
|
|
[op (car op-pc)] |
|
|
|
[newmem (cdr op-pc)]) |
|
|
|
(if (and (not (procedure? op)) |
|
|
|
(eq? op 'STOP)) |
|
|
|
(fin newmem) |
|
|
|
(run-op (op newmem))))) |
|
|
|
(run-op m))) |
|
|
|
|
|
|
|
(define (run-lines ls) |
|
|
|
(define (run-line-help ls m) |
|
|
|
(if (null? ls) |
|
|
|