#include "vm.h" #include "debug.h" #include "opcodes.h" #include "vmas.h" #include unsigned rol(unsigned x, int L, int N) { unsigned lsbs = x & ((1 >> L) - 1); return (x << L) | (lsbs >> (N - L)); } void VM::defineOpcodes(uint8_t *key) { uint32_t i, j, keysize; keysize = strlen((char *)key); for (i = 0; i < keysize; i++) { for (j = 0; j < NUM_OPS; j++) { OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); } } for (i = 0; i < NUM_OPS; i++) { for (j = 0; j < NUM_OPS; j++) { OPS[j] = rol(OPS[j], OPS[i] % 8, 8); } } #ifdef DBG //#TODO ASSEGNARE I NOMI AGLI OPCODES DBG_INFO(("~~~~~~~~~~\nOPCODES:\n")); for (i = 0; i < NUM_OPS; i++) { DBG_INFO(("0x%x: 0x%x\n", i, OPS[i])); } DBG_INFO(("~~~~~~~~~~\n")); #endif return; } /* DBG UTILS */ uint8_t *VM::getRegName(uint8_t regvalue) { uint8_t *buf = new uint8_t[2]; #ifdef DBG switch (regvalue) { case R0: memcpy(buf, "R0", 2); break; case R1: memcpy(buf, "R1", 2); break; case R2: memcpy(buf, "R2", 2); break; case R3: memcpy(buf, "R3", 2); break; case S0: memcpy(buf, "S0", 2); break; case S1: memcpy(buf, "S1", 2); break; case S2: memcpy(buf, "S2", 2); break; case S3: memcpy(buf, "S3", 2); break; case IP: memcpy(buf, "IP", 2); break; case BP: memcpy(buf, "BP", 2); break; case SP: memcpy(buf, "SP", 2); break; default: memcpy(buf, "??", 2); break; } #endif return buf; } void VM::status(void) { #ifdef DBG uint8_t i; DBG_SUCC(("VM Status:\n")); DBG_SUCC(("~~~~~~~~~~\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_SUCC(("~~~~~~~~~~\n")); #endif return; } /* CONSTRUCTORS */ VM::VM(uint8_t *key) { DBG_SUCC(("Creating VM without code.\n")); as.allocate(); initVariables(); defineOpcodes(key); } VM::VM(uint8_t *key, uint8_t *code, uint32_t codesize) { DBG_SUCC(("Creating VM with code.\n")); if (as.allocate()) { as.insCode(code, codesize); } initVariables(); defineOpcodes(key); } void VM::initVariables(void) { uint32_t i; for (i = R0; i < NUM_REGS; i++) { this->regs[i] = 0; } for (i = 0; i < NUM_OPS; i++) { OPS[i] = i; } return; } /* INSTRUCTIONS IMPLEMENTATIONS */ bool VM::execMOVI(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 %s, 0x%x\n", getRegName(dst), imm)); if (dst == IP) { DBG_ERROR(("Can't MOVI to IP!\n")); return false; } regs[dst] = imm; return true; } bool VM::execMOVR(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 %s, %s\n", getRegName(dst), getRegName(src))); if (dst == IP || src == IP) { DBG_ERROR(("Can't MOVR IP!\n")); return false; } regs[dst] = regs[src]; return true; } bool VM::execLOAD(void) { /* LOAD 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(("LOAD %s, 0x%x\n", getRegName(dst), src)); regs[dst] = *((uint16_t *)&as.data[src]); return true; } bool VM::execSTOR(void) { /* STOR 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(("STOR 0x%x, %s\n", dst, getRegName(src))); *((uint16_t *)&as.data[dst]) = regs[src]; return true; } bool VM::execADDI(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 %s, 0x%x\n", getRegName(dst), src)); regs[dst] += src; return true; } bool VM::execADDR(void) { /* ADDR R0, R1 -> R0 += R1 */ uint8_t dst; uint8_t src; dst = as.code[regs[IP] + 1] >> 4; src = as.code[regs[IP] + 1] & 0b00001111; DBG_INFO(("ADDR %s, 0x%x\n", getRegName(dst), src)); regs[dst] += regs[src]; return true; } bool VM::execSUBI(void) { /* SUBI 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(("SUBI %s, 0x%x\n", getRegName(dst), src)); regs[dst] -= src; return true; } bool VM::execSUBR(void) { /* SUBR R0, R1 -> R0 -= R1 */ uint8_t dst; uint8_t src; dst = as.code[regs[IP] + 1] >> 4; src = as.code[regs[IP] + 1] & 0b00001111; DBG_INFO(("SUBR %s, 0x%x\n", getRegName(dst), src)); regs[dst] -= regs[src]; return true; } bool VM::execXORB(void) { /* XORB R0, 0x2 -> R0 ^= 0x02 or R0 ^= [BYTE] 0x02 (low byte) */ uint8_t dst; uint8_t src; dst = as.code[regs[IP] + 1]; src = as.code[regs[IP] + 2]; DBG_INFO(("XORB %s, 0x%x\n", getRegName(dst), src)); regs[dst] ^= src; return true; } bool VM::execXORW(void) { /* XORW R0, 0x2 -> R0 ^= 0x0002 or R0, ^= [WORD] 0x2 */ uint8_t dst; uint16_t src; dst = as.code[regs[IP] + 1]; src = *((uint16_t *)&as.code[regs[IP] + 2]); DBG_INFO(("XORW %s, 0x%x\n", getRegName(dst), src)); regs[dst] ^= src; return true; } bool VM::execXORR(void) { /* XORR R0, R1 -> R0 ^= R1 */ uint8_t dst; uint8_t src; dst = as.code[regs[IP] + 1] >> 4; src = as.code[regs[IP] + 1] & 0b00001111; DBG_INFO(("XORR %s, 0x%x\n", getRegName(dst), src)); regs[dst] ^= regs[src]; return true; } bool VM::execNOTR(void) { /* NOTR R0, R1 -> R0 = ~R1 */ uint8_t dst; uint8_t src; dst = as.code[regs[IP] + 1] >> 4; src = as.code[regs[IP] + 1] & 0b00001111; DBG_INFO(("NOTR %s, 0x%x\n", getRegName(dst), src)); regs[dst] = ~regs[src]; return true; } bool VM::execMULI(void) { /* MULI 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(("SUBI %s, 0x%x\n", getRegName(dst), src)); regs[dst] *= src; return true; } bool VM::execMULR(void) { return true; } bool VM::execDIVI(void) { /* DIVI 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(("DIVI %s, 0x%x\n", getRegName(dst), src)); regs[dst] /= src; return true; } bool VM::execDIVR(void) { return true; } bool VM::execPUSH(void) { return true; } bool VM::execPOOP(void) { return true; } bool VM::execCMPI(void) { return true; } bool VM::execCMPR(void) { return true; } bool VM::execJMPI(void) { return true; } bool VM::execJMPR(void) { return true; } bool VM::execJPAI(void) { return true; } bool VM::execJPAR(void) { return true; } bool VM::execJPBI(void) { return true; } bool VM::execJPBR(void) { return true; } bool VM::execJPEI(void) { return true; } bool VM::execJPER(void) { return true; } bool VM::execGRMN(void) { return true; } void VM::run(void) { uint8_t opcode; bool finished = false; while (!finished) { opcode = (uint8_t)as.code[regs[IP]]; if (opcode == OPS[MOVI]) { execMOVI(); regs[IP] += MOVI_SIZE; } else if (opcode == OPS[MOVR]) { execMOVR(); regs[IP] += MOVR_SIZE; } else if (opcode == OPS[LOAD]) { execLOAD(); regs[IP] += LOAD_SIZE; } else if (opcode == OPS[STOR]) { execSTOR(); regs[IP] += STOR_SIZE; } else if (opcode == OPS[ADDI]) { execADDI(); regs[IP] += ADDI_SIZE; } else if (opcode == OPS[ADDR]) { execADDR(); regs[IP] += ADDR_SIZE; } else if (opcode == OPS[SUBI]) { execSUBI(); regs[IP] += SUBI_SIZE; } else if (opcode == OPS[SUBR]) { execSUBR(); regs[IP] += SUBR_SIZE; } else if (opcode == OPS[XORB]) { execXORB(); regs[IP] += XORB_SIZE; } else if (opcode == OPS[XORW]) { execXORW(); regs[IP] += XORW_SIZE; } else if (opcode == OPS[XORR]) { execXORR(); regs[IP] += XORR_SIZE; } else if (opcode == OPS[NOTR]) { execNOTR(); regs[IP] += NOTR_SIZE; } else if (opcode == OPS[MULI]) { execMULI(); regs[IP] += MULI_SIZE; } else if (opcode == OPS[MULR]) { execMULR(); regs[IP] += MULR_SIZE; } else if (opcode == OPS[DIVI]) { execDIVI(); regs[IP] += DIVI_SIZE; } else if (opcode == OPS[PUSH]) { execPUSH(); regs[IP] += PUSH_SIZE; } else if (opcode == OPS[POOP]) { execPOOP(); regs[IP] += POOP_SIZE; } else if (opcode == OPS[CMPI]) { execCMPI(); regs[IP] += CMPI_SIZE; } else if (opcode == OPS[CMPR]) { execCMPR(); regs[IP] += CMPR_SIZE; } else if (opcode == OPS[JMPI]) { execJMPI(); regs[IP] += JMPI_SIZE; } else if (opcode == OPS[JMPR]) { execJMPR(); regs[IP] += JMPR_SIZE; }else if (opcode == OPS[JPAI]) { execJPAI(); regs[IP] += JPAI_SIZE; }else if (opcode == OPS[JPAR]) { execJPAR(); regs[IP] += JPAR_SIZE; }else if (opcode == OPS[JPBI]) { execJPBI(); regs[IP] += JPBI_SIZE; }else if (opcode == OPS[JPBR]) { execJPBR(); regs[IP] += JPBR_SIZE; }else if (opcode == OPS[JPEI]) { execJPEI(); regs[IP] += JPEI_SIZE; }else if (opcode == OPS[JPER]) { execJPER(); regs[IP] += JPER_SIZE; } else if (opcode == OPS[GRMN]) { execGRMN(); regs[IP] += GRMN_SIZE; } else if (opcode == OPS[SHIT]) { DBG_INFO(("Halting.\n")); finished = true; } else if (opcode == OPS[NOPE]) { regs[IP] += NOPE_SIZE; } else { DBG_ERROR(("WAT\n")); finished = true; } } return; }