// This file is part of uVM. // // uVM is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // uVM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with uVM. If not, see . // #include #include #include #include #include "../include/cpu.h" #include "../include/logging.h" CPU::CPU(unsigned int stack_size) { // If someone says stack_size 0 they are in for a surprise stack = (int*)malloc(stack_size * sizeof(int)); } CPU::~CPU() { if(stack != NULL) { free(stack); } } // Load loads the code into CPU memory...and always returns true bool CPU::load(std::vector c) { code = c; return true; } // Run is the main loop of the entire CPU. It handles each opcode individually. // // At the end of each run the stack pointer and instruction pointer are reset to get the CPU // ready to load the next program. void CPU::run() { while(code[ip] != CPU::opcode::HALT && ip != code.size()) { switch(code[ip]) { case CPU::opcode::IPUSH: { LogMemWithArg(ip, CPU::opcode_map[code[ip]], code[ip + 1]); stack[++sp] = code[++ip]; ip++; break; } case CPU::opcode::ISAVE0: { LogMem(ip, CPU::opcode_map[code[ip]]); t0 = stack[sp--]; ip++; break; } case CPU::opcode::ISAVE1: { LogMem(ip, CPU::opcode_map[code[ip]]); t1 = stack[sp--]; ip++; break; } case CPU::opcode::ISAVE2: { LogMem(ip, CPU::opcode_map[code[ip]]); t2 = stack[sp--]; ip++; break; } case CPU::opcode::ILOAD0: { LogMem(ip, CPU::opcode_map[code[ip]]); stack[++sp] = t0; ip++; break; } case CPU::opcode::ILOAD1: { LogMem(ip, CPU::opcode_map[code[ip]]); stack[++sp] = t1; ip++; break; } case CPU::opcode::ILOAD2: { LogMem(ip, CPU::opcode_map[code[ip]]); stack[++sp] = t2; ip++; break; } case CPU::opcode::IADD: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; stack[sp] = a + b; ip++; break; } case CPU::opcode::IDIV: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; stack[sp] = a / b; ip++; break; } case CPU::opcode::IREM: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; stack[sp] = a % b; ip++; break; } case CPU::opcode::CMP: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; cf = a == b; ip++; break; } case CPU::opcode::JC: { LogMemWithArg(ip, CPU::opcode_map[code[ip]], code[ip + 1]); if(cf) { ip = code[ip + 1]; } else { ip += 2; } break; } case CPU::opcode::ISUB: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; stack[sp] = a - b; ip++; break; } case CPU::opcode::IMUL: { LogMem(ip, CPU::opcode_map[code[ip]]); int a = stack[sp--]; int b = stack[sp--]; stack[sp] = a * b; ip++; break; } case CPU::opcode::JMP: { LogMemWithArg(ip, CPU::opcode_map[code[ip]], code[ip + 1]); ip = code[ip + 1]; break; } case CPU::opcode::PRINT: { LogMem(ip, CPU::opcode_map[code[ip]]); printf("%d\n", stack[sp]); sp--; ip++; break; } } } sp = -1; ip = 0; }