//template <OpLayout L> void apply(Op op, std::function<void(void*, void*, u8)> f) { switch (op.getLayout()) { case OpLayout::NONE: f(NULL, NULL, 0); break; case OpLayout::R: f(&r[instr.r], NULL, 8); //TODO: register thingy is 8 but index is 1? break; case OpLayout::M: f(&mem[instr.a], NULL, 8); //TODO: or 8? //KK TODO: f(&mem[instr.a], NULL, 4); //TODO: or 8? //f(&instr.a, NULL, 4); break; case OpLayout::C: f((u64*)&instr.c, NULL, 4); break; case OpLayout::RR: f(&r[instr.rr.r1], &r[instr.rr.r2], 8); break; case OpLayout::RM: f(&r[instr.rm.r], &mem[instr.rm.a], 8); break; case OpLayout::MR: f(&r[instr.mr.a], &mem[instr.mr.r], 8); break; case OpLayout::RC: f(&r[instr.rc.r], &instr.rc.c, 4); break; case OpLayout::MC: f(&mem[instr.mc.a], &instr.mc.c, 4); break; default: err("Bad layout"); break; } }
void run() { while (true) { //usleep(2); //usleep(50000); //0.05 seconds /*debug_machine_print(*this); getch(true); cout << endl;*/ instr_ptr++; //cout << instr_ptr << endl; if (!mem[instr_ptr]) err("Bad instruction"); instr.uint64 = mem[instr_ptr]; Op op = Op(instr.o); OpLayout layout = op.getLayout(); OpType type = op.getType(); switch (type) { case OpType::NOP: continue; break; case OpType::HALT: return; break; case OpType::MOV: { apply(op, [&](void* a, void* b, u8 size) { memcpy(a, b, size); //*a = *b; }); break; } case OpType::PUSH: { apply(op, [&](void* val, void* unused, u8 size) { memcpy(&mem[stack_ptr++], val, size); }); break; } case OpType::POP: { apply(op, [&](void* val, void* unused, u8 size) { assert(layout == OpLayout::R); //memcpy(&r[*(u16*)val], &mem[stack_ptr--], size); memcpy(val, &mem[(stack_ptr--)-1], size); }); break; } case OpType::INT: { assert(layout == OpLayout::C); u8 cmd = instr.c; switch (cmd) { case 0: usleep(r[0]); break; case 1: cout << (char)r[0]; break; case 2: r[0] = getch(false); break; default: err("interrupt not implemented"); cout << cmd; break; } break; } case OpType::JMP: { apply(op, [&](void* val, void* unused, u8 size) { //KK TODO assert(layout == OpLayout::M); assert(layout == OpLayout::C || layout == OpLayout::R); instr_ptr = *((u16*)val); }); break; } case OpType::CMP: { apply(op, [&](void* a, void* b, u8 size) { cmp_result = asm_cmp(a, b, size); }); break; } case OpType::JE: { apply(op, [&](void* val, void* unused, u8 size) { assert(layout == OpLayout::C); if (cmp_result == 4) err("jump without previous cmp"); if (cmp_result == 0) instr_ptr = *((u16*)val); }); break; } case OpType::SUB: { assert(layout == OpLayout::RC); //temporary only for fib apply(op, [&](void* a, void* b, u8 size) { assert(size == 4); *(u64*)a =(u64) *(u32*)a - *(u32*)b; }); break; } case OpType::ADD: { assert(layout == OpLayout::RR); //temporary only for fib apply(op, [&](void* a, void* b, u8 size) { assert(size == 8); *(u64*)a =(u64) *(u64*)a + *(u64*)b; }); break; } default: op.print(); err("Command not implemented"); break; } } }