#lang racket
(require "assembler.rkt" "stack.rkt" "state.rkt" "programs.rkt")
(provide (all-defined-out))
(define data (stack 0 (make-vector 8)))
(define return (stack 0 (make-vector 8)))
(define a 0)
(define b 0)
(define p 0)
(define i 0)
(define r 0)
(define s 0)
(define t 0)
(define memory-size MEM-SIZE)
(define memory (make-vector MEM-SIZE))
(define memory-wrap #f)
(define comm-data '())
(define comm-type '())
(define comm-recv '())
(define instructions (make-vector 35))
(define BIT 18)
(define (load-state! state mem-size [mem-wrap #f])
(set! a (progstate-a state))
(set! b (progstate-b state))
(set! p (progstate-p state))
(set! i (progstate-i state))
(set! r (progstate-r state))
(set! s (progstate-s state))
(set! t (progstate-t state))
(set! data (copy-stack (progstate-data state)))
(set! return (copy-stack (progstate-return state)))
(set! memory (vector-copy (progstate-memory state)))
(set! memory-size mem-size)
(set! memory-wrap mem-wrap)
)
(define (current-state)
(progstate a b p i r s t (copy-stack data) (copy-stack return) (vector-copy memory 0 MEM-SIZE)))
(define (current-commstate)
(commstate (list->vector (reverse comm-data))
(list->vector (reverse comm-type))
(list->vector (reverse comm-recv))
(length comm-data)))
(define (reset! [bit 18])
(set! BIT bit)
(set! comm-data '())
(set! comm-type '())
(set! comm-recv '()))
(define (reset-p! [start 0])
(set! p start))
(define (display-data [state (current-state)])
(display (format "|d> ~x ~x" (progstate-t state) (progstate-s state)))
(display-stack (progstate-data state))
(newline))
(define (display-return)
(display (format "|r> ~x" r))
(display-stack return)
(newline))
(define (display-memory n)
(for ([i (in-range 0 n)])
(display (format "~x " (vector-ref memory i))))
(newline))
(define (display-state [state (current-state)])
(pretty-display (format "p:~a a:~a b:~a r:~a"
(progstate-p state) (progstate-a state)
(progstate-b state) (progstate-r state)))
(display-data state))
(define (display-vector vec n name)
(when (> n 0)
(display name)
(for ([i (in-range 0 n)])
(display (format "~x " (vector-ref vec i))))
(newline)))
(define (display-comm)
(define comm (current-commstate))
(pretty-display (format "comm-data: ~a" (commstate-data comm)))
(pretty-display (format "comm-type: ~a" (commstate-type comm)))
(pretty-display (format "comm-recv: ~a" (commstate-type comm))))
(define (load-program in [start 0])
(foldl (lambda (word pos) (vector-set! memory pos word) (add1 pos))
start (read-program in)))
(define (18bit n)
(bitwise-bit-field n 0 BIT))
(define (push! value)
(push-stack! data s)
(set! s t)
(set! t (18bit value)))
(define (r-push! value)
(push-stack! return r)
(set! r value))
(define (pop!)
(let ([ret-val t])
(set! t s)
(set! s (pop-stack! data))
ret-val))
(define (r-pop!)
(let ([ret-val r])
(set! r (pop-stack! return))
ret-val))
(define (execute-word!)
(define (execute! opcode [jump-addr-pos 0])
(let ([jump-addr (bitwise-bit-field i 0 jump-addr-pos)])
((vector-ref instructions opcode) jump-addr)))
(and (execute! (bitwise-bit-field i 13 18) 10)
(execute! (bitwise-bit-field i 8 13) 8)
(execute! (bitwise-bit-field i 3 8) 3)
(execute! (arithmetic-shift (bitwise-bit-field i 0 3) 2))))
(define (incr curr)
(cond [(< curr #x07F) (add1 curr)]
[(= curr #x07F) #x000]
[(< curr #x0FF) (add1 curr)]
[(= curr #x0FF) #x080]
[else curr]))
(define (step-program! [debug? #f])
(set! i (vector-ref memory p))
(set! p (incr p))
(when debug? (display-state))
(execute-word!)
)
(define (step-program-n! n [debug? #f])
(for ([i (in-range 0 n)]) (step-program! debug?)))
(define (step-program!* [debug? #f])
(let ([next (vector-ref memory p)])
(unless (or (= next #x39ce7) (= next 0))
(step-program! debug?) (step-program!* debug?))))
(define define-instruction!
(let ([current-opcode 0])
(lambda (body)
(vector-set! instructions current-opcode body)
(set! current-opcode (add1 current-opcode)))))
(define (read-memory addr)
(if (member addr (list UP DOWN LEFT RIGHT IO))
(let ([value 12]) (cond [(= addr UP) (set! comm-data (cons value comm-data))
(set! comm-recv (cons value comm-recv))
(set! comm-type (cons 0 comm-type))]
[(= addr DOWN) (set! comm-data (cons value comm-data))
(set! comm-recv (cons value comm-recv))
(set! comm-type (cons 1 comm-type))]
[(= addr LEFT) (set! comm-data (cons value comm-data))
(set! comm-recv (cons value comm-recv))
(set! comm-type (cons 2 comm-type))]
[(= addr RIGHT) (set! comm-data (cons value comm-data))
(set! comm-recv (cons value comm-recv))
(set! comm-type (cons 3 comm-type))]
[(= addr IO) (set! comm-data (cons value comm-data))
(set! comm-recv (cons value comm-recv))
(set! comm-type (cons 4 comm-type))])
value)
(vector-ref memory (if memory-wrap (modulo addr memory-size) addr))))
(define (read-memory-@p addr)
(vector-ref memory addr))
(define (set-memory! addr value)
(cond [(= addr UP) (set! comm-data (cons value comm-data))
(set! comm-type (cons 5 comm-type))]
[(= addr DOWN) (set! comm-data (cons value comm-data))
(set! comm-type (cons 6 comm-type))]
[(= addr LEFT) (set! comm-data (cons value comm-data))
(set! comm-type (cons 7 comm-type))]
[(= addr RIGHT) (set! comm-data (cons value comm-data))
(set! comm-type (cons 8 comm-type))]
[(= addr IO) (set! comm-data (cons value comm-data))
(set! comm-type (cons 9 comm-type))]
[else (vector-set! memory (if memory-wrap (modulo addr memory-size) addr) value)]))
(define-instruction! (lambda (_) (set! p r) (r-pop!) #f)) (define-instruction! (lambda (_) (define temp p) (set! p r) (set! r temp) #f)) (define-instruction! (lambda (a) (set! p a) #f)) (define-instruction! (lambda (a) (r-push! p) (set! p a) #f)) (define-instruction! (lambda (_) (if (= r 0) (r-pop!) (begin (set! r (sub1 r)) (set! p (sub1 p)) #f))))
(define-instruction! (lambda (a) (if (= r 0) (begin (r-pop!) #f) (begin (set! r (sub1 r)) (set! p a) #f))))
(define-instruction! (lambda (a) (and (not (= t 0)) (set! p a) #f))) (define-instruction! (lambda (a) (and (not (bitwise-bit-set? t (sub1 BIT))) (set! p a) #f))) (define-instruction! (lambda (_) (push! (read-memory-@p p)) (set! p (incr p)))) (define-instruction! (lambda (_) (push! (read-memory a)) (set! a (incr a)))) (define-instruction! (lambda (_) (push! (read-memory b)))) (define-instruction! (lambda (_) (push! (read-memory a)))) (define-instruction! (lambda (_) (set-memory! p (pop!)) (set! p (incr p)))) (define-instruction! (lambda (_) (set-memory! a (pop!)) (set! a (incr a)))) (define-instruction! (lambda (_) (set-memory! b (pop!)))) (define-instruction! (lambda (_) (set-memory! a (pop!)))) (define-instruction! (lambda (_) (if (even? a) (multiply-step-even!)
(multiply-step-odd!))))
(define-instruction! (lambda (_) (set! t (18bit (arithmetic-shift t 1))))) (define-instruction! (lambda (_) (set! t (arithmetic-shift t -1)))) (define-instruction! (lambda (_) (set! t (18bit (bitwise-not t))))) (define-instruction! (lambda (_) (push! (+ (pop!) (pop!))))) (define-instruction! (lambda (_) (push! (bitwise-and (pop!) (pop!))))) (define-instruction! (lambda (_) (push! (bitwise-xor (pop!) (pop!))))) (define-instruction! (lambda (_) (pop!))) (define-instruction! (lambda (_) (push! t))) (define-instruction! (lambda (_) (push! (r-pop!)))) (define-instruction! (lambda (_) (push! s))) (define-instruction! (lambda (_) (push! a))) (define-instruction! (lambda (_) (void))) (define-instruction! (lambda (_) (r-push! (pop!)))) (define-instruction! (lambda (_) (set! b (pop!)))) (define-instruction! (lambda (_) (set! a (pop!))))
(define (multiply-step-even!)
(let ([t17 (bitwise-and t #x20000)]
[t0 (bitwise-and t #x1)])
(set! t (bitwise-ior t17 (arithmetic-shift t -1)))
(set! a (bitwise-ior (arithmetic-shift t0 (sub1 BIT)) (arithmetic-shift a -1)))))
(define (multiply-step-odd!)
(let* ([sum (+ t s)]
[sum17 (bitwise-and sum #x20000)]
[result (bitwise-ior (arithmetic-shift sum (sub1 BIT)) (arithmetic-shift a -1))])
(set! a (bitwise-bit-field result 0 BIT))
(set! t (bitwise-ior sum17 (bitwise-bit-field result BIT (* 2 BIT))))))