summaryrefslogtreecommitdiff
path: root/opc_impl.ha
diff options
context:
space:
mode:
Diffstat (limited to 'opc_impl.ha')
-rw-r--r--opc_impl.ha134
1 files changed, 134 insertions, 0 deletions
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");
+};
+
+
+
+