diff options
Diffstat (limited to 'opc_impl.ha')
-rw-r--r-- | opc_impl.ha | 134 |
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"); +}; + + + + |