summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile10
-rwxr-xr-xasm.py40
-rw-r--r--cpu.ha130
-rwxr-xr-xdisasm.py29
-rwxr-xr-xmnems.py45
-rw-r--r--opc_impl.ha134
-rw-r--r--r1b.txt14
8 files changed, 327 insertions, 78 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cba89c7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+opcodes.ha
+*.py[cod]
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..23120d0
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+.POSIX:
+.SUFFIXES:
+
+run: opcodes.ha
+ hare run
+
+opcodes.ha: mnems.py
+ ./mnems.py >opcodes.ha
+
+.PHONY: run
diff --git a/asm.py b/asm.py
index 26eaf8f..3d61543 100755
--- a/asm.py
+++ b/asm.py
@@ -1,39 +1,6 @@
#!/usr/bin/env python3
-mnems = """
-nop
-rot
-nrt
-dup
-swp
-ovr
-drp
-tck
-nip
-equ
-neq
-add
-sub
-mul
-div
-neg
-slt
-ult
-sle
-ule
-lod
-sto
-psh
-pop
-""".split()
-mnems.extend(['???']*(64-len(mnems)))
-def opws(kw):
- for k in range(16):
- mnems.append(kw + str(k))
-opws("mark") # who is mark
-opws("loc")
-opws("ret")
-opws("lit")
+from mnems import mnems
# print(mnems)
import sys
@@ -81,7 +48,7 @@ def assemble_line(args, lineno):
opc2 = mnems.index(i2)
emit_instrs(opc1, opc2)
case ["l", val]:
- emit_lit(int(val))
+ emit_lit(int(val,16))
case [':', label]:
if label in labels:
@@ -145,9 +112,6 @@ def jump_instr(target, origin):
rel = target - origin + 2048
return (rel&0b111111111111)|0b0100000000000000
-
-
-
import sys
def main():
for ix, line in enumerate(sys.stdin):
diff --git a/cpu.ha b/cpu.ha
new file mode 100644
index 0000000..3ffea05
--- /dev/null
+++ b/cpu.ha
@@ -0,0 +1,130 @@
+use endian;
+use io;
+use os;
+use fs;
+use fmt;
+
+type stack_overflow = !void;
+type stack_underflow = !void;
+
+type cpu = struct {
+ sp: u8,
+ rp: u8,
+ pc: u16,
+ mem: []u8,
+ halted: bool,
+};
+
+fn cpu_new() cpu = cpu {
+ sp = 0,
+ rp = 0,
+ pc = 0x0200,
+ mem = alloc([0...], 65536): []u8,
+ halted = false,
+};
+
+fn rmem(mem: []u8, addr: u16) u16 =
+ endian::begetu16(mem[addr..addr+2]);
+fn wmem(mem: []u8, addr: u16, w: u16) void =
+ endian::beputu16(mem[addr..addr+2], w);
+
+// stacks grow up, for a change
+fn push(cpu: *cpu, val: u16) void = {
+ wmem(cpu.mem, 0 + cpu.sp, val);
+ cpu.sp += 2;
+};
+fn pop(cpu: *cpu) u16 = {
+ cpu.sp -= 2;
+ return rmem(cpu.mem, 0 + cpu.sp);
+};
+fn peek(cpu: *cpu, n: u16 = 0) u16 =
+ rmem(cpu.mem, 0 + cpu.sp - 2 + n);
+
+
+fn rpush(cpu: *cpu, val: u16) void = {
+ wmem(cpu.mem, 0x100 + cpu.rp:u16, val);
+ cpu.rp += 2;
+};
+fn rpop(cpu: *cpu) u16 = {
+ cpu.rp -= 2;
+ return rmem(cpu.mem, 0x100 + cpu.rp:u16);
+};
+
+
+
+def MASK_CALL: u16 = 0b1000000000000000;
+def MASK_LIT : u16 = 0b0110000000000000;
+def MASK_JMP : u16 = 0b0100000000000000;
+fn maskeq(x: u16, m: u16) bool =
+ // still must be called in the right order
+ (x&m) == m;
+
+fn do_word(cpu: *cpu, word: u16) void = {
+ if (maskeq(word, MASK_CALL)) {
+ const addr = word & 0b0111111111111111;
+ const addr = addr << 1;
+ do_call(cpu, addr);
+ } else if (maskeq(word, MASK_LIT)) {
+ const lval = word & 0b0001111111111111;
+ push(cpu, lval);
+ } else if (maskeq(word, MASK_JMP)) {
+ const is_cond = (word & 0b0001000000000000) != 0;
+ const rel: u16 = word & 0b0000111111111111;
+ const rel: i16 = rel:i16 - 2048i16;
+ const target: i16 = rel + cpu.pc:i16 - 2i16;
+ const target: u16 = target:u16;
+ if (is_cond)
+ do_0branch(cpu, target)
+ else
+ do_jmp(cpu, target);
+ } else {
+ const opc1: u8 = ((word & 0b0011111110000000) >> 7):u8;
+ const opc2: u8 = (word & 0b0000000001111111):u8;
+ do_opc(cpu, opc1);
+ do_opc(cpu, opc2);
+ };
+};
+
+fn do_call(cpu: *cpu, addr: u16) void = {
+ rpush(cpu, cpu.pc);
+ cpu.pc = addr;
+};
+
+fn do_jmp(cpu: *cpu, addr: u16) void = {
+ cpu.pc = addr;
+};
+
+fn do_0branch(cpu: *cpu, addr: u16) void = {
+ const val = pop(cpu);
+ if (val == 0) {
+ cpu.pc = addr;
+ };
+};
+
+fn mainloop(cpu: *cpu) void = {
+ for (! cpu.halted) {
+ const word = rmem(cpu.mem, cpu.pc);
+ cpu.pc += 2;
+ do_word(cpu, word);
+ };
+};
+
+export fn main() void = {
+ const cpu = cpu_new();
+ const fp = match (os::open("sys0.r1b")) {
+ case let i: io::file => yield i;
+ case let e: fs::error => fmt::fatalf("MISSING BOOT SECTOR: {}",
+ fs::strerror(e));
+ };
+
+ match (io::readall(fp, cpu.mem[0x0200..0x0300])) {
+ case let e: io::error => fmt::fatalf("BOOT SECTOR READ ERROR: {}", io::strerror(e));
+ case => yield;
+ };
+
+ mainloop(&cpu);
+};
+
+
+
+
diff --git a/disasm.py b/disasm.py
index 3ba5c2f..693393b 100755
--- a/disasm.py
+++ b/disasm.py
@@ -1,33 +1,8 @@
#!/usr/bin/env python3
import sys
-mnems = """
-nop
-rot
-nrt
-dup
-swp
-ovr
-drp
-tck
-nip
-equ
-neq
-add
-sub
-mul
-div
-neg
-slt
-ult
-sle
-ule
-lod
-sto
-psh
-pop
-""".split()
-mnems.extend(['???']*(64-len(mnems)))
+from mnems import mnems
+
def opws(kw):
for k in range(16):
mnems.append(kw + str(k))
diff --git a/mnems.py b/mnems.py
new file mode 100755
index 0000000..db00fbc
--- /dev/null
+++ b/mnems.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+mnems = """
+nop
+rot
+nrt
+dup
+swp
+ovr
+drp
+tck
+nip
+equ
+neq
+add
+sub
+mul
+div
+neg
+slt
+ult
+sle
+ule
+lod
+sto
+psh
+pop
+hlt
+put
+""".split()
+mnems.extend(['???']*(64-len(mnems)))
+def opws(kw):
+ for k in range(16):
+ mnems.append(kw + str(k))
+opws("mark") # who is mark
+opws("loc")
+opws("ret")
+opws("lit")
+
+if __name__ == "__main__":
+ print("type op = enum u8 {")
+ for opc,mnem in enumerate(mnems):
+ if mnem != "???":
+ print(f"\t{mnem.upper()} = {opc},")
+ print("};")
diff --git a/opc_impl.ha b/opc_impl.ha
new file mode 100644
index 0000000..f85be5f
--- /dev/null
+++ b/opc_impl.ha
@@ -0,0 +1,134 @@
+use fmt;
+
+fn do_opc(cpu: *cpu, opc: u8) void =
+ if (0 <= opc && opc < op::MARK0) do_opr(cpu, opc)
+ else if (op::MARK0 <= opc && opc <= op::MARK15)
+ // who is mark
+ do_op_mark(cpu, opc-op::MARK0)
+ else if (op::LOC0 <= opc && opc <= op::LOC15)
+ do_op_loc(cpu, opc-op::LOC0)
+ else if (op::RET0 <= opc && opc <= op::RET15)
+ do_op_ret(cpu, opc-op::RET0)
+ else if (op::LIT0 <= opc && opc <= op::LIT15)
+ do_op_lit(cpu, opc-op::LIT0)
+ else abort("what???");
+
+fn do_op_mark(cpu: *cpu, p: u8) void =
+ cpu.rp += p*2;
+
+fn do_op_loc(cpu: *cpu, p: u8) void =
+ push(cpu, 0x100 + cpu.rp:u16 - (p-1)*2);
+
+fn do_op_ret(cpu: *cpu, p: u8) void = {
+ cpu.rp -= p*2;
+ const rval = rpop(cpu);
+ cpu.pc = rval;
+};
+
+fn do_op_lit(cpu: *cpu, p: u8) void = {
+ push(cpu, p: u16);
+};
+
+fn do_opr(cpu: *cpu, op: u8) void = switch (op) {
+ case op::NOP => yield;
+ case op::ROT =>
+ const a = pop(cpu);
+ const b = pop(cpu);
+ const c = pop(cpu);
+ push(cpu, b);
+ push(cpu, a);
+ push(cpu, c);
+ case op::NRT =>
+ const a = pop(cpu);
+ const b = pop(cpu);
+ const c = pop(cpu);
+ push(cpu, a);
+ push(cpu, c);
+ push(cpu, b);
+ case op::DUP =>
+ push(cpu, peek(cpu));
+ case op::SWP =>
+ const a = pop(cpu);
+ const b = pop(cpu);
+ push(cpu, a);
+ push(cpu, b);
+ case op::OVR =>
+ const x = peek(cpu, 1);
+ push(cpu, x);
+ case op::DRP =>
+ pop(cpu);
+ case op::TCK =>
+ const y = pop(cpu);
+ const x = pop(cpu);
+ push(cpu, y);
+ push(cpu, x);
+ push(cpu, y);
+ case op::NIP =>
+ const y = pop(cpu);
+ pop(cpu);
+ push(cpu, y);
+ case op::EQU =>
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, if (x == y) 1 else 0);
+ case op::NEQ =>
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, if (x != y) 1 else 0);
+ case op::ADD =>
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, x + y);
+ case op::SUB =>
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, x - y);
+ case op::MUL =>
+ // TODO: better handling mul div
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, x * y);
+ case op::DIV =>
+ const x = pop(cpu);
+ const y = pop(cpu);
+ push(cpu, x / y);
+ case op::NEG =>
+ push(cpu, - pop(cpu));
+ case op::SLT =>
+ const x = pop(cpu): i16;
+ const y = pop(cpu): i16;
+ push(cpu, if (y < x) 1 else 0);
+ case op::SLE =>
+ const x = pop(cpu): i16;
+ const y = pop(cpu): i16;
+ push(cpu, if (y <= x) 1 else 0);
+ case op::ULT =>
+ const x = pop(cpu): u16;
+ const y = pop(cpu): u16;
+ push(cpu, if (y < x) 1 else 0);
+ case op::ULE =>
+ const x = pop(cpu): u16;
+ const y = pop(cpu): u16;
+ push(cpu, if (y <= x) 1 else 0);
+ case op::LOD =>
+ // TODO lod and sto for bytes
+ const addr = pop(cpu);
+ push(cpu, rmem(cpu.mem, addr));
+ case op::STO =>
+ const addr = pop(cpu);
+ const val = pop(cpu);
+ wmem(cpu.mem, addr, val);
+ case op::PSH =>
+ rpush(cpu, pop(cpu));
+ case op::POP =>
+ push(cpu, rpop(cpu));
+ case op::HLT =>
+ cpu.halted = true;
+ case op::PUT =>
+ fmt::printfln("{:_04x}",pop(cpu))!;
+ case => abort("wrong opr");
+};
+
+
+
+
diff --git a/r1b.txt b/r1b.txt
index 7baa9c8..cc7fe36 100644
--- a/r1b.txt
+++ b/r1b.txt
@@ -24,15 +24,6 @@ sto (da-)
push
pop
-
-
-what abotu either
-
-1[addr:15] : call
-0
-01 literal
-
-
want:
calls (15 bits)
j, cj, relative addr, 8 bits
@@ -53,6 +44,7 @@ regular op (7 bits)
OPW:7: 1 T:2 arg:4
OPR:7: 0 opcode:6
+that is,
00 - 3f regular opcodes (64 of them)
4x mark x
5x loc x
@@ -64,7 +56,3 @@ J: 0 1 0 cond? raddr:12
L: 0 1 1 value:13
C: 1 addr:15
-
-
-
-