You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.2 KiB
165 lines
4.2 KiB
// 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 <http://www.gnu.org/licenses/>. |
|
// |
|
|
|
#include <vector> |
|
#include <iostream> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
|
|
#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<int> 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; |
|
}
|
|
|