18 changed files with 9311 additions and 8167 deletions
-
1.gitignore
-
43Makefile
-
5RECIPES
-
65builtins.c
-
323lex.yy.c
-
14651parser.output
-
1404parser.tab.c
-
119parser.tab.h
-
59parser.y
-
671programs/chip8.sol
-
12programs/interp.sol
-
15runtime.c
-
4ser.c
-
16sol.h
-
6solrun.c
-
54state.c
-
28tests/lang_elseif.sol
-
2tokenizer.lex
@ -0,0 +1,5 @@ |
|||
WASM/asm.js: |
|||
make CC=emcc CFLAGS=-DNO_READLINE NO_HELP=1 |
|||
|
|||
clang for profiling: |
|||
make CC=clang CFLAGS="-fprofile-instr-generate -fcoverage-mapping" |
14651
parser.output
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1404
parser.tab.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,671 @@ |
|||
chr2hex_t = {} |
|||
hex2chr_t = {} |
|||
|
|||
for i in range(10) do |
|||
c = chr(ord('0') + i) |
|||
chr2hex_t[c] = i |
|||
hex2chr_t[i] = c |
|||
end |
|||
|
|||
for i in [10, 11, 12, 13, 14, 15] do |
|||
c = chr(ord('A') + i - 10) |
|||
chr2hex_t[c] = i |
|||
hex2chr_t[i] = c |
|||
end |
|||
|
|||
func new_reg() |
|||
return { |
|||
V = [0] * 16, |
|||
I = 0, |
|||
IP = 512, |
|||
ST = 0, |
|||
DT = 0, |
|||
} |
|||
end |
|||
|
|||
func new_mem() |
|||
return [ |
|||
240, 144, 144, 144, 240, -- 0 |
|||
32, 96, 32, 32, 112, -- 1 |
|||
240, 16, 240, 128, 240, -- 2 |
|||
240, 16, 240, 16, 240, -- 3 |
|||
144, 144, 240, 16, 16, -- 4 |
|||
240, 128, 240, 16, 240, -- 5 |
|||
240, 128, 240, 144, 240, -- 6 |
|||
240, 16, 32, 64, 64, -- 7 |
|||
240, 144, 240, 144, 240, -- 8 |
|||
240, 144, 240, 16, 240, -- 9 |
|||
240, 144, 240, 144, 144, -- A |
|||
224, 144, 224, 144, 224, -- B |
|||
240, 128, 128, 128, 240, -- C |
|||
224, 144, 144, 144, 224, -- D |
|||
240, 128, 240, 128, 240, -- E |
|||
240, 128, 240, 128, 128, -- F |
|||
] + [0] * 4016 |
|||
end |
|||
|
|||
func mem_int(mem, i, bytes) |
|||
r = 0 |
|||
while (bytes > 0) && (i < 4096) do |
|||
r = (r << 8) | mem[i] |
|||
i += 1 |
|||
bytes -= 1 |
|||
end |
|||
return r |
|||
end |
|||
|
|||
func load_buffer(mem, addr, s) |
|||
if None == addr then addr = 512 end |
|||
idx = 0 |
|||
while (idx < s:size()) && (addr < 4096) do |
|||
mem[addr] = s:get(buffer.type.byte, idx) |
|||
addr += 1 |
|||
idx += 1 |
|||
end |
|||
end |
|||
|
|||
func load_stream(mem, addr, str) |
|||
load_buffer(mem, addr, str:read_buffer(io.ALL)) |
|||
end |
|||
|
|||
func get_bit(v, i) |
|||
return (v >> i) & 1 |
|||
end |
|||
|
|||
func new_disp(w, h) |
|||
if w == None then w = 64 end |
|||
if h == None then h = 32 end |
|||
return { |
|||
fb = [0] * (64 * 32), |
|||
w = w, |
|||
h = h, |
|||
} |
|||
end |
|||
|
|||
func disp_blit(b, x, y, v) |
|||
idx = y * (b.w) + x |
|||
changed = 0 |
|||
for bit in range(8) do |
|||
if (idx >= 0) && (idx < (b.w) * (b.h)) then |
|||
oldb = b.fb[idx] |
|||
b.fb[idx] ^= if v & 128 then 1 else 0 end |
|||
changed = changed || ((!oldb) && (b.fb[idx])) |
|||
idx += 1 |
|||
v = v << 1 |
|||
end |
|||
end |
|||
return changed |
|||
end |
|||
|
|||
func print_sprite(m, i, n) |
|||
if None == n then n = 15 end |
|||
fake_fb = new_disp(8, n) |
|||
for idx in range(n) do |
|||
disp_blit(fake_fb, 0, idx, m[i + idx]) |
|||
end |
|||
print(disp_render(fake_fb)) |
|||
end |
|||
|
|||
NL = chr(10) |
|||
CSI = chr(27) + '[' |
|||
|
|||
func clear_screen() |
|||
io.stdout:write(CSI+'H'+CSI+'2J') |
|||
end |
|||
|
|||
func disp_render(d) |
|||
s = '' |
|||
for row in range(d.h) do |
|||
s = s + disp_render_row(d, row) + NL |
|||
end |
|||
return s |
|||
end |
|||
|
|||
func disp_render_row(d, r) |
|||
t = '' |
|||
for col in range(d.w) do |
|||
idx = r * (d.w) + col |
|||
if d.fb[idx] then |
|||
t += '*' |
|||
else |
|||
t += ' ' |
|||
end |
|||
end |
|||
return t |
|||
end |
|||
|
|||
func unused_syscall(state, n) |
|||
state:log("unknown syscall " + tostring(n)) |
|||
end |
|||
|
|||
func clear_disp(state, n) |
|||
state.disp = new_disp() |
|||
end |
|||
|
|||
func ret(state, n) |
|||
state:jump(state:pop()) |
|||
end |
|||
|
|||
func new_sys() |
|||
sys = [unused_syscall] * 4096 |
|||
sys[224] = clear_disp |
|||
sys[238] = ret |
|||
return sys |
|||
end |
|||
|
|||
func new_state() |
|||
return { |
|||
reg = new_reg(), |
|||
mem = new_mem(), |
|||
disp = new_disp(), |
|||
sys = new_sys(), |
|||
jumped = false, |
|||
trace = false, |
|||
jump = func(self, ip) |
|||
self.reg.IP = ip |
|||
self.jumped = true |
|||
end, |
|||
skip = func(self) |
|||
self.reg.IP += 2 |
|||
end, |
|||
stack = [], |
|||
push = func(self, v) |
|||
self.stack:insert(#(self.stack), v) |
|||
if (#self.stack) > 16 then |
|||
self:log("stack overflow: " + tostring(self.stack)) |
|||
end |
|||
end, |
|||
pop = func(self) |
|||
if (#self.stack) == 0 then |
|||
self:log("stack underflow") |
|||
return 0 |
|||
end |
|||
return self.stack:remove((#self.stack) - 1) |
|||
end, |
|||
keys = [0] * 16, |
|||
buffer = [], |
|||
log = func(self, msg) |
|||
self.buffer:insert(#(self.buffer), msg) |
|||
end, |
|||
breaks = [], |
|||
-- wchan = None |
|||
} |
|||
end |
|||
|
|||
func new_insn(n) |
|||
return { |
|||
nib = [(n >> 12) & 15, (n >> 8) & 15, (n >> 4) & 15, n & 15], |
|||
byte = {high = (n >> 8) & 255, low = n & 255}, |
|||
addr = n & 4095, |
|||
n = n, |
|||
} |
|||
end |
|||
|
|||
func rand(n=0) |
|||
n = ((n * 17) + 1569752) % 3707765549 |
|||
n = (n << 1) | (((n >> 3) & 1) ^ ((n >> 6) & 1)) |
|||
n = (n << 1) | (((n >> 8) & 1) ^ ((n >> 5) & 1)) |
|||
n = ((n * 7) + 67293512) % 3747882443 |
|||
n = (n << 1) | (((n >> 7) & 1) ^ ((n >> 2) & 1)) |
|||
n = (n << 1) | (((n >> 4) & 1) ^ ((n >> 3) & 1)) |
|||
return n |
|||
end |
|||
|
|||
func seed(n) |
|||
rand.closure.n = n |
|||
end |
|||
|
|||
func bad_op(state, ins) |
|||
state:log("bad insn: " + tostring(ins.n) + " " + tostring(ins.nib)) |
|||
end |
|||
|
|||
insns = { |
|||
[0] = func insn0(state, ins) |
|||
state.sys[ins.addr](state, ins.addr) |
|||
end, |
|||
[1] = func insn1(state, ins) |
|||
state:jump(ins.addr) |
|||
end, |
|||
[2] = func insn2(state, ins) |
|||
state:push(state.reg.IP + 2) |
|||
state:jump(ins.addr) |
|||
end, |
|||
[3] = func insn3(state, ins) |
|||
if state.reg.V[ins.nib[1]] == ins.byte.low then |
|||
state:skip() |
|||
end |
|||
end, |
|||
[4] = func insn4(state, ins) |
|||
if state.reg.V[ins.nib[1]] != ins.byte.low then |
|||
state: |