-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvm.rkt
110 lines (86 loc) · 2.81 KB
/
vm.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#lang racket/base
(provide (struct-out vm)
register-get
register-set
register-set*
memory-get
memory-set
vm-eprint)
(require racket/format ; ~r
racket/string ; string-join
racket/list ; range
"bytes.rkt"
"decoded.rkt")
;; Wrapper for registers / memory / PC
(define-struct vm (rf mem decoded) #:transparent)
;; Internal helper for testing
;; (listof pair?) listof pair? -> vm?
(define (vm-create #:registers register-values #:memory memory-cells)
(make-vm (make-immutable-hash register-values)
(make-immutable-hash memory-cells)
empty-decoded))
;; get the value of [register] from [machine]
;; NOTE: It is assumed register will be in the range [0, 32)
(define (register-get machine register)
(hash-ref (vm-rf machine) register))
(module+ test
(require rackunit)
(test-equal?
"Get register"
(register-get (vm-create #:registers (list (cons 1 1)) #:memory empty)
1)
1))
;; Set [register] to [value] and return updated [machine]
(define (register-set machine register value)
(cond
[(equal? register 0) machine]
[else (struct-copy
vm machine
[rf (hash-set (vm-rf machine) register value)])]))
(module+ test
(require rackunit)
(test-equal?
"Set standard register"
(register-set (vm-create #:registers (list (cons 1 1)) #:memory empty)
1 2)
(vm-create #:registers (list (cons 1 2)) #:memory empty))
(test-equal?
"Set zero register (doesn't change value)"
(register-set (vm-create #:registers (list (cons 0 0)) #:memory empty)
0 1)
(vm-create #:registers (list (cons 0 0)) #:memory empty)))
;; Set pairs of register-values in the registerfile
(define (register-set* machine . pairs)
(foldl (lambda (p m) (register-set m (car p) (cdr p)))
machine
pairs))
;; the value at [address] in the [machine]'s memory
(define (memory-get machine address)
(hash-ref (vm-mem machine) address))
;; set [address] in the [machine]'s memory to [value]
(define (memory-set machine address value)
(struct-copy
vm machine
[mem (hash-set (vm-mem machine) address value)]))
;; Print out the contents of the registers to stderr
(define (vm-eprint machine)
(define (format-register r)
(~r r
#:sign #f
#:base 10
#:min-width 2
#:pad-string "0"))
(define (format-bytes machine r)
(~r (bytes->integer (register-get machine r) #:signed? #f)
#:sign #f
#:base 16
#:min-width 8
#:pad-string "0"))
(eprintf
"~A~n"
(string-join
(for/list ([i (range 1 32)])
(format "$~a = 0x~a ~a"
(format-register i)
(format-bytes machine i)
(if (zero? (modulo i 4)) "\n" ""))) "")))