gipu/cpp/vm.cpp

185 lines
3.5 KiB
C++
Raw Normal View History

2017-05-14 13:06:17 +01:00
#include "vm.h"
2017-05-13 18:36:46 +01:00
#include "debug.h"
2017-05-14 13:06:17 +01:00
#include "vmas.h"
#include <string.h>
2017-05-13 18:36:46 +01:00
2017-05-14 21:10:58 +01:00
/*
CONSTRUCTORS
*/
2017-05-14 13:06:17 +01:00
VM::VM() {
DBG_INFO(("Creating VM without code.\n"));
2017-05-14 21:10:58 +01:00
as.allocate();
2017-05-14 13:06:17 +01:00
init_regs();
2017-05-13 18:36:46 +01:00
}
2017-05-14 13:06:17 +01:00
VM::VM(uint8_t *code, uint32_t codesize) {
DBG_INFO(("Creating VM with code.\n"));
2017-05-14 21:10:58 +01:00
if (as.allocate()) {
as.insCode(code, codesize);
}
2017-05-14 13:06:17 +01:00
init_regs();
2017-05-13 18:36:46 +01:00
}
2017-05-14 13:06:17 +01:00
void VM::init_regs(void) {
uint8_t i;
for (i = R0; i <= SP; i++) {
this->regs[i] = 0;
}
return;
}
void VM::status(void) {
uint8_t i;
DBG_INFO(("VM Status:\n"));
DBG_INFO(("~~~~~~~~~~\n"));
for (i = R0; i <= SP; i++) {
switch (i) {
case R0:
DBG_INFO(("R0:\t0x%x\n", this->regs[i]));
break;
case R1:
DBG_INFO(("R1:\t0x%x\n", this->regs[i]));
break;
case R2:
DBG_INFO(("R2:\t0x%x\n", this->regs[i]));
break;
case R3:
DBG_INFO(("R3:\t0x%x\n", this->regs[i]));
break;
case S0:
DBG_INFO(("S0:\t0x%x\n", this->regs[i]));
break;
case S1:
DBG_INFO(("S1:\t0x%x\n", this->regs[i]));
break;
case S2:
DBG_INFO(("S2:\t0x%x\n", this->regs[i]));
break;
case S3:
DBG_INFO(("S3:\t0x%x\n", this->regs[i]));
break;
case IP:
DBG_INFO(("IP:\t0x%x\n", this->regs[i]));
break;
case BP:
DBG_INFO(("BP:\t0x%x\n", this->regs[i]));
break;
case SP:
DBG_INFO(("SP:\t0x%x\n", this->regs[i]));
break;
}
}
DBG_INFO(("~~~~~~~~~~\n"));
return;
}
2017-05-14 21:10:58 +01:00
/*
INSTRUCTIONS IMPLEMENTATIONS
*/
void VM::exec_movi(void) {
/*
MOVI R0, 0x2400 | R0 = 0x2400
*/
uint8_t dst;
uint16_t imm;
dst = as.code[regs[IP] + 1];
imm = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("MOVI 0x%x 0x%x\n", dst, imm));
regs[dst] = imm;
return;
}
void VM::exec_movr(void) {
/*
MOVR R1, R0 | R1 = R0
---------------------
R1, R0 = 0x10 <- DST / SRC are nibbles!
*/
uint8_t dst, src;
dst = as.code[regs[IP] + 1] >> 4;
src = as.code[regs[IP] + 1] & 0b00001111;
DBG_INFO(("MOVR 0x%x 0x%x\n", dst, src));
regs[dst] = regs[src];
return;
}
void VM::exec_getm(void) {
/*
GETM R0, 0x1000 | R0 = data[0x1000]
*/
uint8_t dst;
uint16_t src;
dst = as.code[regs[IP] + 1];
src = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("GETM 0x%x 0x%x\n", dst, src));
regs[dst] = *((uint16_t *)&as.data[src]);
return;
}
void VM::exec_putm(void) {
/*
PUTM 0x1000, R0 | data[0x1000] = R0
*/
uint16_t dst;
uint8_t src;
dst = *((uint16_t *)&as.code[regs[IP] + 1]);
src = as.code[regs[IP] + 3];
DBG_INFO(("PUTM 0x%x 0x%x\n", dst, src));
*((uint16_t *)&as.data[dst]) = regs[src];
return;
}
void VM::exec_addi(void) {
/*
ADDI R0, 0x2 | R0 += 2
*/
uint8_t dst;
uint16_t src;
dst = as.code[regs[IP] + 1];
src = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("ADDI 0x%x 0x%x\n", dst, src));
regs[dst] += src;
return;
}
void VM::run(void) {
uint8_t opcode;
bool finished = false;
while (!finished) {
opcode = (uint8_t)as.code[regs[IP]];
switch (opcode) {
case MOVI:
exec_movi();
regs[IP] += MOVI_SIZE;
break;
case MOVR:
exec_movr();
regs[IP] += MOVR_SIZE;
break;
case GETM:
exec_getm();
regs[IP] += GETM_SIZE;
break;
case PUTM:
exec_putm();
regs[IP] += PUTM_SIZE;
break;
case ADDI:
exec_addi();
regs[IP] += ADDI_SIZE;
break;
case HALT:
DBG_INFO(("HALT\n"));
finished = true;
break;
default:
DBG_INFO(("WAT: 0x%x\n", opcode));
return;
break;
}
}
return;
}