Debugger, begin runtime stuff
This commit is contained in:
parent
a36eea12d0
commit
f939d1b08b
36
asm/fib.scm
Normal file
36
asm/fib.scm
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
(variable result 0)
|
||||||
|
(push result)
|
||||||
|
(@)
|
||||||
|
(push fib)
|
||||||
|
(call)
|
||||||
|
(push cleanup)
|
||||||
|
(jmp)
|
||||||
|
fib
|
||||||
|
(dup)
|
||||||
|
(push 0)
|
||||||
|
(=)
|
||||||
|
(over)
|
||||||
|
(push 1)
|
||||||
|
(=)
|
||||||
|
(or)
|
||||||
|
(push recur)
|
||||||
|
(branch)
|
||||||
|
(return)
|
||||||
|
recur
|
||||||
|
(dup)
|
||||||
|
(push 1)
|
||||||
|
(-)
|
||||||
|
(push fib)
|
||||||
|
(call)
|
||||||
|
(over)
|
||||||
|
(push 2)
|
||||||
|
(-)
|
||||||
|
(push fib)
|
||||||
|
(call)
|
||||||
|
(+)
|
||||||
|
(nip)
|
||||||
|
(return)
|
||||||
|
cleanup
|
||||||
|
(push result)
|
||||||
|
(!)
|
||||||
|
(bye)
|
76
asm/runtime.scm
Normal file
76
asm/runtime.scm
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
;; Note that this is scheme syntax wrapping asm for a stack machine
|
||||||
|
(variable scan 0)
|
||||||
|
(variable free 0)
|
||||||
|
(variable eom 1024)
|
||||||
|
;; These need to be initialized later
|
||||||
|
(variable root 0)
|
||||||
|
(variable the-cars 0)
|
||||||
|
(variable the-cdrs 0)
|
||||||
|
(variable new-cars 0)
|
||||||
|
(variable new-cdrs 0)
|
||||||
|
|
||||||
|
|
||||||
|
(push main)
|
||||||
|
(jmp)
|
||||||
|
|
||||||
|
alloc
|
||||||
|
;; Test if free will go beyond eom
|
||||||
|
(push free)
|
||||||
|
(@)
|
||||||
|
(dup) ; ( -- free free)
|
||||||
|
(push 8)
|
||||||
|
(+)
|
||||||
|
(dup) ; ( -- free free+8 free+8)
|
||||||
|
(push eom)
|
||||||
|
(@)
|
||||||
|
(<) ; ( -- free free+8 (free+8 < eom))
|
||||||
|
(branch alloc-do-gc)
|
||||||
|
;; write free+8 to free
|
||||||
|
(push free)
|
||||||
|
(!)
|
||||||
|
;; return the old free, it is memory the program can use
|
||||||
|
(return)
|
||||||
|
alloc-do-gc
|
||||||
|
;; Empty the stack
|
||||||
|
(drop)
|
||||||
|
(drop)
|
||||||
|
;; Run garbage collection
|
||||||
|
(push gc-start)
|
||||||
|
(call)
|
||||||
|
;; Tail-call allocation
|
||||||
|
(push alloc)
|
||||||
|
(jmp)
|
||||||
|
|
||||||
|
gc-start
|
||||||
|
; Move scan & free back to 0
|
||||||
|
(push 0)
|
||||||
|
(push free)
|
||||||
|
(!)
|
||||||
|
(push 0)
|
||||||
|
(push scan)
|
||||||
|
(!)
|
||||||
|
; Push the first cons to relocate (root)
|
||||||
|
(push root)
|
||||||
|
(@)
|
||||||
|
; Call the relocation routine
|
||||||
|
(push gc-loop)
|
||||||
|
(call)
|
||||||
|
; Swap new and old cars and cdrs
|
||||||
|
(push new-cars)
|
||||||
|
(@)
|
||||||
|
(push the-cars)
|
||||||
|
(@)
|
||||||
|
(push new-cars)
|
||||||
|
(!)
|
||||||
|
(push the-cars)
|
||||||
|
(!)
|
||||||
|
(push new-cdrs)
|
||||||
|
(@)
|
||||||
|
(push the-cdrs)
|
||||||
|
(@)
|
||||||
|
(push new-cdrs)
|
||||||
|
(!)
|
||||||
|
(push the-cdrs)
|
||||||
|
(!)
|
||||||
|
; return to allocation
|
||||||
|
(return)
|
49
scmvm.scm
Executable file → Normal file
49
scmvm.scm
Executable file → Normal file
@ -1,26 +1,27 @@
|
|||||||
#! /bin/sh
|
(define-module (scmvm)
|
||||||
exec guile -L . -e main -s "$0" "$@"
|
#:use-module (scmvm vm)
|
||||||
!#
|
#:use-module (scmvm assembler)
|
||||||
|
#:use-module (scmvm debugger)
|
||||||
|
#:use-module (ice-9 ports)
|
||||||
|
#:re-export ( ;; vm
|
||||||
|
make-vm run-vm vm-load-program!
|
||||||
|
vm-memory-ref vm-memory-set!
|
||||||
|
vm-pc vm-pc-set!
|
||||||
|
;; assembler
|
||||||
|
assemble
|
||||||
|
;; debugger
|
||||||
|
make-debugger debugger-continue
|
||||||
|
debugger-vm
|
||||||
|
debugger-breakpoints debugger-breakpoints-set!
|
||||||
|
debugger-breakpoint-add! debugger-breakpoint-ref
|
||||||
|
debugger-breakpoint-enable! debugger-breakpoint-disable!)
|
||||||
|
#:export (read-all-instructions instructions-from-file))
|
||||||
|
|
||||||
(use-modules (scmvm vm)
|
(define (read-all-instructions)
|
||||||
(scmvm assembler)
|
(let ([inst (read)])
|
||||||
(srfi srfi-11)
|
(if (eof-object? inst)
|
||||||
(srfi srfi-26)
|
'()
|
||||||
(ice-9 control))
|
(cons inst (read-all-instructions)))))
|
||||||
|
|
||||||
(define (make-debugger source asm)
|
(define (instructions-from-file file)
|
||||||
())
|
(with-input-from-file file read-all-instructions))
|
||||||
|
|
||||||
(define (debug file)
|
|
||||||
(let*-values ([(source) (open-file file)]
|
|
||||||
[(asm) (call-with-output-bytevector (cut assemble-file file <>))]
|
|
||||||
[(begin-debugger resume-debugger) (make-debugger source asm)])
|
|
||||||
(% (begin-debugger)
|
|
||||||
(resume-debugger))))
|
|
||||||
|
|
||||||
(define (main . args)
|
|
||||||
(when (null? args)
|
|
||||||
(usage))
|
|
||||||
(case (car args)
|
|
||||||
[(help) (usage)]
|
|
||||||
[(debug) (apply debug (cdr args))]))
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#:use-module (rnrs io ports)
|
#:use-module (rnrs io ports)
|
||||||
#:use-module ((scheme base)
|
#:use-module ((scheme base)
|
||||||
#:select (write-u8 write-bytevector))
|
#:select (write-u8 write-bytevector))
|
||||||
#:export (assemble assemble-file))
|
#:export (assemble))
|
||||||
|
|
||||||
(define (lookup-instruction inst)
|
(define (lookup-instruction inst)
|
||||||
(define inst-obj (assq inst *instruction-set*))
|
(define inst-obj (assq inst *instruction-set*))
|
||||||
@ -36,9 +36,9 @@
|
|||||||
(write-bytevector bv))
|
(write-bytevector bv))
|
||||||
|
|
||||||
(define (assemble inst-seq port)
|
(define (assemble inst-seq port)
|
||||||
|
(define labels (find-labels inst-seq 1))
|
||||||
(with-output-to-port port
|
(with-output-to-port port
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(define labels (find-labels inst-seq 1))
|
|
||||||
(let loop ([seq inst-seq])
|
(let loop ([seq inst-seq])
|
||||||
(cond
|
(cond
|
||||||
[(null? seq) '()]
|
[(null? seq) '()]
|
||||||
@ -54,13 +54,5 @@
|
|||||||
(if (number? (cadr inst))
|
(if (number? (cadr inst))
|
||||||
(write-word (cadr inst))
|
(write-word (cadr inst))
|
||||||
(write-word (assq-ref labels (cadr inst)))))
|
(write-word (assq-ref labels (cadr inst)))))
|
||||||
(loop (cdr seq)))])))))
|
(loop (cdr seq)))]))))
|
||||||
|
labels)
|
||||||
(define (assemble-file file out)
|
|
||||||
(call-with-input-file file
|
|
||||||
(lambda (in)
|
|
||||||
(define (read-all next)
|
|
||||||
(if (eof-object? next)
|
|
||||||
'()
|
|
||||||
(cons next (read-all (read in)))))
|
|
||||||
(assemble (read-all (read in)) out))))
|
|
||||||
|
68
scmvm/debugger.scm
Normal file
68
scmvm/debugger.scm
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
(define-module (scmvm debugger)
|
||||||
|
#:use-module (scmvm assembler)
|
||||||
|
#:use-module (scmvm vm)
|
||||||
|
#:use-module (srfi srfi-9)
|
||||||
|
#:use-module (ice-9 control)
|
||||||
|
#:use-module (ice-9 binary-ports)
|
||||||
|
#:use-module (ice-9 exceptions)
|
||||||
|
#:export ((make-debugger* . make-debugger)
|
||||||
|
debugger-vm
|
||||||
|
debugger-source
|
||||||
|
debugger-breakpoints debugger-breakpoints-set!
|
||||||
|
debugger-breakpoint-add! debugger-breakpoint-ref
|
||||||
|
debugger-breakpoint-enable! debugger-breakpoint-disable!
|
||||||
|
debugger-continue))
|
||||||
|
|
||||||
|
(define-record-type <debugger>
|
||||||
|
(make-debugger vm source breakpoints continuation)
|
||||||
|
debugger?
|
||||||
|
(vm debugger-vm)
|
||||||
|
(source debugger-source)
|
||||||
|
(breakpoints debugger-breakpoints debugger-breakpoints-set!)
|
||||||
|
(continuation debugger-continuation debugger-continuation-set!))
|
||||||
|
|
||||||
|
(define (make-debugger* source)
|
||||||
|
(define-values (prgm symbols)
|
||||||
|
(call-with-values open-bytevector-output-port
|
||||||
|
(lambda (port get-bv)
|
||||||
|
(define symbols (assemble source port))
|
||||||
|
(values (get-bv) symbols))))
|
||||||
|
(define the-debugger #f)
|
||||||
|
(define (debug)
|
||||||
|
(shift k
|
||||||
|
(debugger-continuation-set! the-debugger k)
|
||||||
|
(when (not (assq-ref (debugger-breakpoints the-debugger)
|
||||||
|
(vm-pc (debugger-vm the-debugger))))
|
||||||
|
(k))))
|
||||||
|
(define vm (make-vm #:debugger debug))
|
||||||
|
(vm-load-program! vm prgm)
|
||||||
|
(set! the-debugger (make-debugger vm source '((1 . #t)) #f))
|
||||||
|
(reset (run-vm vm))
|
||||||
|
the-debugger)
|
||||||
|
|
||||||
|
(define (debugger-continue debugger)
|
||||||
|
((debugger-continuation debugger)))
|
||||||
|
|
||||||
|
(define* (debugger-breakpoint-add! debugger breakpoint #:key (enabled? #f))
|
||||||
|
(debugger-breakpoints-set!
|
||||||
|
debugger
|
||||||
|
(assq-set! (debugger-breakpoints debugger) breakpoint enabled?)))
|
||||||
|
|
||||||
|
(define (debugger-breakpoint-ref debugger breakpoint)
|
||||||
|
(assq breakpoint (debugger-breakpoints debugger)))
|
||||||
|
|
||||||
|
(define (debugger-breakpoint-enable! debugger breakpoint)
|
||||||
|
(define breakpoints (debugger-breakpoints debugger))
|
||||||
|
(if (pair? (assq breakpoints breakpoint))
|
||||||
|
(assq-set! breakpoints breakpoint #t)
|
||||||
|
(raise-exception (make-exception
|
||||||
|
(make-error)
|
||||||
|
(make-exception-with-message "Cannot enable nonexistant breakpoint")))))
|
||||||
|
|
||||||
|
(define (debugger-breakpoint-disable! debugger breakpoint)
|
||||||
|
(define breakpoints (debugger-breakpoints debugger))
|
||||||
|
(if (pair? (assq breakpoints breakpoint))
|
||||||
|
(assq-set! breakpoints breakpoint #f)
|
||||||
|
(raise-exception (make-exception
|
||||||
|
(make-error)
|
||||||
|
(make-exception-with-message "Cannot disable nonexistant breakpoint")))))
|
136
scmvm/vm.scm
136
scmvm/vm.scm
@ -5,7 +5,7 @@
|
|||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:export (make-vm run-vm vm-memory-ref vm-memory-set! vm-memory vm-load-program!
|
#:export (make-vm run-vm vm-memory-ref vm-memory-set! vm-memory vm-load-program!
|
||||||
vm-pc-ref vm-pc-set!
|
vm-pc vm-pc-set!
|
||||||
*instruction-set* instruction-type instruction-code))
|
*instruction-set* instruction-type instruction-code))
|
||||||
|
|
||||||
;;; Data Structures
|
;;; Data Structures
|
||||||
@ -156,70 +156,70 @@
|
|||||||
word))
|
word))
|
||||||
(define (fetch-and-execute)
|
(define (fetch-and-execute)
|
||||||
(define exit? #f)
|
(define exit? #f)
|
||||||
(let lp ([op (fetch-byte)])
|
(when debugger
|
||||||
(when debugger
|
(debugger))
|
||||||
(debugger))
|
(define op (fetch-byte))
|
||||||
(case (op-lookup op)
|
(case (op-lookup op)
|
||||||
[(push)
|
[(push)
|
||||||
(push data-stack (fetch-word))]
|
(push data-stack (fetch-word))]
|
||||||
[(!)
|
[(!)
|
||||||
(let ([addr (pop data-stack)]
|
(let ([addr (pop data-stack)]
|
||||||
[v (pop data-stack)])
|
[v (pop data-stack)])
|
||||||
(ram-word-set! addr v))]
|
(ram-word-set! addr v))]
|
||||||
[(@)
|
[(@)
|
||||||
(let* ([addr (pop data-stack)]
|
(let* ([addr (pop data-stack)]
|
||||||
[v (ram-word-ref addr)])
|
[v (ram-word-ref addr)])
|
||||||
(push data-stack v))]
|
(push data-stack v))]
|
||||||
[(+ - and or nand nor xor)
|
[(+ - and or nand nor xor)
|
||||||
(let ([v2 (pop data-stack)]
|
(let ([v2 (pop data-stack)]
|
||||||
[v1 (pop data-stack)])
|
[v1 (pop data-stack)])
|
||||||
(push data-stack ((binop-lookup op) v1 v2)))]
|
(push data-stack ((binop-lookup op) v1 v2)))]
|
||||||
[(= > <)
|
[(= > <)
|
||||||
(let ([v2 (pop data-stack)]
|
(let ([v2 (pop data-stack)]
|
||||||
[v1 (pop data-stack)])
|
[v1 (pop data-stack)])
|
||||||
(if ((relop-lookup op) v1 v2)
|
(if ((relop-lookup op) v1 v2)
|
||||||
(push data-stack 1)
|
(push data-stack 1)
|
||||||
(push data-stack 0)))]
|
(push data-stack 0)))]
|
||||||
[(jmp)
|
[(jmp)
|
||||||
(jump (pop data-stack))]
|
(jump (pop data-stack))]
|
||||||
[(branch)
|
[(branch)
|
||||||
(let ([addr (pop data-stack)])
|
(let ([addr (pop data-stack)])
|
||||||
(when (zero? (pop data-stack))
|
(when (zero? (pop data-stack))
|
||||||
(jump addr)))]
|
(jump addr)))]
|
||||||
[(call)
|
[(call)
|
||||||
(let ([addr (pop data-stack)])
|
(let ([addr (pop data-stack)])
|
||||||
(push ret-stack pc)
|
(push ret-stack pc)
|
||||||
(jump addr))]
|
(jump addr))]
|
||||||
[(return)
|
[(return)
|
||||||
(jump (pop ret-stack))]
|
(jump (pop ret-stack))]
|
||||||
[(>R)
|
[(>R)
|
||||||
(push ret-stack (pop data-stack))]
|
(push ret-stack (pop data-stack))]
|
||||||
[(R>)
|
[(R>)
|
||||||
(push data-stack (pop ret-stack))]
|
(push data-stack (pop ret-stack))]
|
||||||
[(drop)
|
[(drop)
|
||||||
(pop data-stack)]
|
(pop data-stack)]
|
||||||
[(nip)
|
[(nip)
|
||||||
(let ([v (pop data-stack)])
|
(let ([v (pop data-stack)])
|
||||||
(pop data-stack)
|
(pop data-stack)
|
||||||
(push data-stack v))]
|
(push data-stack v))]
|
||||||
[(dup)
|
[(dup)
|
||||||
(push data-stack (peek data-stack))]
|
(push data-stack (peek data-stack))]
|
||||||
[(swap)
|
[(swap)
|
||||||
(swap data-stack)]
|
(swap data-stack)]
|
||||||
[(rot)
|
[(rot)
|
||||||
(let* ([a (pop data-stack)]
|
(let* ([a (pop data-stack)]
|
||||||
[b (pop data-stack)]
|
[b (pop data-stack)]
|
||||||
[c (pop data-stack)])
|
[c (pop data-stack)])
|
||||||
(push data-stack a)
|
(push data-stack a)
|
||||||
(push data-stack c)
|
(push data-stack c)
|
||||||
(push data-stack b))]
|
(push data-stack b))]
|
||||||
[(over)
|
[(over)
|
||||||
(let* ([a (pop data-stack)]
|
(let* ([a (pop data-stack)]
|
||||||
[b (pop data-stack)])
|
[b (pop data-stack)])
|
||||||
(push data-stack b)
|
(push data-stack b)
|
||||||
(push data-stack a)
|
(push data-stack a)
|
||||||
(push data-stack b))]
|
(push data-stack b))]
|
||||||
[(bye) (set! exit? #t)]))
|
[(bye) (set! exit? #t)])
|
||||||
(when (not exit?)
|
(when (not exit?)
|
||||||
(fetch-and-execute)))
|
(fetch-and-execute)))
|
||||||
(lambda (x)
|
(lambda (x)
|
||||||
@ -228,7 +228,7 @@
|
|||||||
[(vm-memory) (lambda () ram)]
|
[(vm-memory) (lambda () ram)]
|
||||||
[(vm-memory-ref) ram-word-ref]
|
[(vm-memory-ref) ram-word-ref]
|
||||||
[(vm-memory-set!) ram-word-set!]
|
[(vm-memory-set!) ram-word-set!]
|
||||||
[(vm-pc-ref) (lambda () pc)]
|
[(vm-pc) (lambda () pc)]
|
||||||
[(vm-pc-set!) (lambda (v) (set! pc v))]
|
[(vm-pc-set!) (lambda (v) (set! pc v))]
|
||||||
[else (error "vm unknown dispatch")])))
|
[else (error "vm unknown dispatch")])))
|
||||||
|
|
||||||
@ -251,9 +251,9 @@
|
|||||||
ram 0
|
ram 0
|
||||||
(bytevector-length prgm))))
|
(bytevector-length prgm))))
|
||||||
|
|
||||||
(define (vm-pc-ref vm)
|
(define (vm-pc vm)
|
||||||
"Return the value of the pc"
|
"Return the value of the pc"
|
||||||
((vm 'vm-pc-ref)))
|
((vm 'vm-pc)))
|
||||||
|
|
||||||
(define (vm-pc-set! vm pc)
|
(define (vm-pc-set! vm pc)
|
||||||
"Set the value of the pc"
|
"Set the value of the pc"
|
||||||
|
Loading…
Reference in New Issue
Block a user