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"); };