295 lines
6.3 KiB
Julia
295 lines
6.3 KiB
Julia
function interpret(text::String)
|
|
ip, accum, isready, ram = 0x1, 0x0, true, zeros(UInt8, 32)
|
|
NOP() = (ip = mod1(ip + 1, 32))
|
|
LDA() = (accum = ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
|
STA() = (ram[ram[ip] & 0b00011111 + 1] = accum; ip = mod1(ip + 1, 32))
|
|
ADD() = (accum += ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
|
SUB() = (accum -= ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
|
BRZ() = (ip = (accum == 0) ? ram[ip] & 0b00011111 + 1 : mod1(ip + 1, 32))
|
|
JMP() = (ip = ram[ip] & 0b00011111 + 1)
|
|
STP() = (println("Program completed with accumulator value $(accum).\n"); isready = false)
|
|
step = [NOP, LDA, STA, ADD, SUB, BRZ, JMP, STP]
|
|
assemblywords = Dict(s => i - 1 for (i, s) in pairs(string.(step)))
|
|
labels = Dict{String, Int}()
|
|
arglabels = Dict{Int, Tuple{Int, String}}()
|
|
for (i, line) in pairs(strip.(split(text, "\n")))
|
|
i > 32 && break
|
|
line = replace(line, r";.*$" => "") # remove comment
|
|
if occursin(":", line)
|
|
label, line = split(line, ":", limit = 2)
|
|
haskey(labels, label) && error("Duplicate label at line $i")
|
|
labels[strip(label)] = i - 1
|
|
end
|
|
if isempty(line)
|
|
ram[i] = 0
|
|
elseif (m = match(r"(\w\w\w)\s+([a-zA-Z]\w*)", line)) != nothing
|
|
arglabels[i] = (UInt8((assemblywords[m.captures[1]] << 5)), m.captures[2])
|
|
elseif (m = match(r"(\w\w\w)\s+(\d\d*)", line)) != nothing
|
|
ram[i] = UInt8((assemblywords[m.captures[1]] << 5) | parse(UInt8, m.captures[2]))
|
|
elseif (m = match(r"([a-zA-Z]\w*)", line)) != nothing
|
|
ram[i] = UInt8(assemblywords[m.match] << 5)
|
|
elseif (m = match(r"\d\d*", line)) != nothing
|
|
ram[i] = parse(UInt8, m.match)
|
|
else
|
|
error("Compilation error at line $i: error parsing <$line>")
|
|
end
|
|
end
|
|
for (i, t) in arglabels
|
|
ram[i] = t[1] | labels[t[2]]
|
|
end
|
|
while isready
|
|
step[ram[ip] >> 5 + 1]()
|
|
end
|
|
return accum
|
|
end
|
|
|
|
const testprograms = [
|
|
"""
|
|
LDA 3
|
|
ADD 4
|
|
STP
|
|
2
|
|
2
|
|
""",
|
|
"""
|
|
LDA 12
|
|
ADD 10
|
|
STA 12
|
|
LDA 11
|
|
SUB 13
|
|
STA 11
|
|
BRZ 8
|
|
JMP 0
|
|
LDA 12
|
|
STP
|
|
8
|
|
7
|
|
0
|
|
1
|
|
""",
|
|
"""
|
|
LDA 14
|
|
STA 15
|
|
ADD 13
|
|
STA 14
|
|
LDA 15
|
|
STA 13
|
|
LDA 16
|
|
SUB 17
|
|
BRZ 11
|
|
STA 16
|
|
JMP 0
|
|
LDA 14
|
|
STP
|
|
1
|
|
1
|
|
0
|
|
8
|
|
1
|
|
""",
|
|
"""
|
|
LDA 13
|
|
ADD 15
|
|
STA 5
|
|
ADD 16
|
|
STA 7
|
|
NOP
|
|
STA 14
|
|
NOP
|
|
BRZ 11
|
|
STA 15
|
|
JMP 0
|
|
LDA 14
|
|
STP
|
|
LDA 0
|
|
0
|
|
28
|
|
1
|
|
|
|
|
|
|
|
6
|
|
0
|
|
2
|
|
26
|
|
5
|
|
20
|
|
3
|
|
30
|
|
1
|
|
22
|
|
4
|
|
24
|
|
""",
|
|
"""
|
|
0
|
|
0
|
|
STP
|
|
NOP
|
|
LDA 3
|
|
SUB 29
|
|
BRZ 18
|
|
LDA 3
|
|
STA 29
|
|
BRZ 14
|
|
LDA 1
|
|
ADD 31
|
|
STA 1
|
|
JMP 2
|
|
LDA 0
|
|
ADD 31
|
|
STA 0
|
|
JMP 2
|
|
LDA 3
|
|
STA 29
|
|
LDA 0
|
|
ADD 30
|
|
ADD 3
|
|
STA 0
|
|
LDA 1
|
|
ADD 30
|
|
ADD 3
|
|
STA 1
|
|
JMP 2
|
|
0
|
|
1
|
|
3
|
|
""",
|
|
"""\
|
|
LDA x
|
|
ADD y ; accumulator = x + y
|
|
STP
|
|
x: 2
|
|
y: 2
|
|
""",
|
|
"""\
|
|
loop: LDA prodt
|
|
ADD x
|
|
STA prodt
|
|
LDA y
|
|
SUB one
|
|
STA y
|
|
BRZ done
|
|
JMP loop
|
|
done: LDA prodt ; to display it
|
|
STP
|
|
x: 8
|
|
y: 7
|
|
prodt: 0
|
|
one: 1
|
|
""",
|
|
"""\
|
|
loop: LDA n
|
|
STA temp
|
|
ADD m
|
|
STA n
|
|
LDA temp
|
|
STA m
|
|
LDA count
|
|
SUB one
|
|
BRZ done
|
|
STA count
|
|
JMP loop
|
|
done: LDA n ; to display it
|
|
STP
|
|
m: 1
|
|
n: 1
|
|
temp: 0
|
|
count: 8 ; valid range: 1-11
|
|
one: 1
|
|
""",
|
|
"""\
|
|
start: LDA load
|
|
ADD car ; head of list
|
|
STA ldcar
|
|
ADD one
|
|
STA ldcdr ; next CONS cell
|
|
ldcar: NOP
|
|
STA value
|
|
ldcdr: NOP
|
|
BRZ done ; 0 stands for NIL
|
|
STA car
|
|
JMP start
|
|
done: LDA value ; CAR of last CONS
|
|
STP
|
|
load: LDA 0
|
|
value: 0
|
|
car: 28
|
|
one: 1
|
|
; order of CONS cells
|
|
; in memory
|
|
; does not matter
|
|
6
|
|
0 ; 0 stands for NIL
|
|
2 ; (CADR ls)
|
|
26 ; (CDDR ls) -- etc.
|
|
5
|
|
20
|
|
3
|
|
30
|
|
1 ; value of (CAR ls)
|
|
22 ; points to (CDR ls)
|
|
4
|
|
24
|
|
""",
|
|
"""\
|
|
p: 0 ; NOP in first round
|
|
c: 0
|
|
start: STP ; wait for p's move
|
|
pmove: NOP
|
|
LDA pmove
|
|
SUB cmove
|
|
BRZ same
|
|
LDA pmove
|
|
STA cmove ; tit for tat
|
|
BRZ cdeft
|
|
LDA c ; p defected, c did not
|
|
ADD three
|
|
STA c
|
|
JMP start
|
|
cdeft: LDA p
|
|
ADD three
|
|
STA p
|
|
JMP start
|
|
same: LDA pmove
|
|
STA cmove ; tit for tat
|
|
LDA p
|
|
ADD one
|
|
ADD pmove
|
|
STA p
|
|
LDA c
|
|
ADD one
|
|
ADD pmove
|
|
STA c
|
|
JMP start
|
|
cmove: 0 ; co-operate initially
|
|
one: 1
|
|
three: 3
|
|
""",
|
|
"""\
|
|
LDA 3
|
|
SUB 4
|
|
STP 0
|
|
0
|
|
255
|
|
""",
|
|
"""\
|
|
LDA 3
|
|
SUB 4
|
|
STP 0
|
|
0
|
|
1
|
|
""",
|
|
"""\
|
|
LDA 3
|
|
ADD 4
|
|
STP 0
|
|
1
|
|
255
|
|
""",
|
|
]
|
|
|
|
for t in testprograms
|
|
interpret(t)
|
|
end
|