ISA completo

This commit is contained in:
Giulio De Pasquale 2017-05-18 17:28:10 +02:00
parent 020a5062a2
commit 1490a6e6fc
5 changed files with 404 additions and 45 deletions

View File

@ -258,6 +258,8 @@ class VMInstruction:
def __init__(self, opcode, instr_list): def __init__(self, opcode, instr_list):
immediate_regexp = re.compile("^(0x*|[0-9]*$)") immediate_regexp = re.compile("^(0x*|[0-9]*$)")
self.opcode = next((x for x in ops if x.name == opcode), None) self.opcode = next((x for x in ops if x.name == opcode), None)
if self.opcode == None:
raise InvalidOperation(opcode)
self.args = [] self.args = []
for el in instr_list: for el in instr_list:
if not immediate_regexp.match(el): if not immediate_regexp.match(el):
@ -279,6 +281,12 @@ op_names = [["MOVI", "imm2reg"],
["ADDR", "reg2reg"], ["ADDR", "reg2reg"],
["SUBI", "imm2reg"], ["SUBI", "imm2reg"],
["SUBR", "reg2reg"], ["SUBR", "reg2reg"],
["ANDB", "byt2reg"],
["ANDW", "imm2reg"],
["ANDR", "reg2reg"],
["YORB", "byt2reg"],
["YORW", "imm2reg"],
["YORR", "reg2reg"],
["XORB", "byt2reg"], ["XORB", "byt2reg"],
["XORW", "imm2reg"], ["XORW", "imm2reg"],
["XORR", "reg2reg"], ["XORR", "reg2reg"],
@ -299,6 +307,8 @@ op_names = [["MOVI", "imm2reg"],
["JPBR", "regonly"], ["JPBR", "regonly"],
["JPEI", "immonly"], ["JPEI", "immonly"],
["JPER", "regonly"], ["JPER", "regonly"],
["JPNI", "immonly"],
["JPNR", "regonly"],
["SHIT", "single"], ["SHIT", "single"],
["NOPE", "single"], ["NOPE", "single"],
["GRMN", "single"]] ["GRMN", "single"]]

View File

@ -10,6 +10,12 @@ enum OPS_STARTING_VALUES {
ADDR, ADDR,
SUBI, SUBI,
SUBR, SUBR,
ANDB,
ANDW,
ANDR,
YORB,
YORW,
YORR,
XORB, XORB,
XORW, XORW,
XORR, XORR,
@ -30,6 +36,8 @@ enum OPS_STARTING_VALUES {
JPBR, JPBR,
JPEI, JPEI,
JPER, JPER,
JPNI,
JPNR,
SHIT, SHIT,
NOPE, NOPE,
GRMN, GRMN,
@ -60,6 +68,12 @@ INSTRUCTION SIZES
#define ADDR_SIZE REG2REG #define ADDR_SIZE REG2REG
#define SUBI_SIZE IMM2REG #define SUBI_SIZE IMM2REG
#define SUBR_SIZE REG2REG #define SUBR_SIZE REG2REG
#define ANDB_SIZE BYT2REG
#define ANDW_SIZE IMM2REG
#define ANDR_SIZE REG2REG
#define YORB_SIZE BYT2REG
#define YORW_SIZE IMM2REG
#define YORR_SIZE REG2REG
#define XORB_SIZE BYT2REG #define XORB_SIZE BYT2REG
#define XORW_SIZE IMM2REG #define XORW_SIZE IMM2REG
#define XORR_SIZE REG2REG #define XORR_SIZE REG2REG
@ -80,6 +94,8 @@ INSTRUCTION SIZES
#define JPBR_SIZE REGONLY #define JPBR_SIZE REGONLY
#define JPEI_SIZE IMMONLY #define JPEI_SIZE IMMONLY
#define JPER_SIZE REGONLY #define JPER_SIZE REGONLY
#define JPNI_SIZE IMMONLY
#define JPNR_SIZE REGONLY
#define SHIT_SIZE SINGLE #define SHIT_SIZE SINGLE
#define NOPE_SIZE SINGLE #define NOPE_SIZE SINGLE
#define GRMN_SIZE SINGLE #define GRMN_SIZE SINGLE

397
vm/vm.cpp
View File

@ -14,7 +14,7 @@ void VM::defineOpcodes(uint8_t *key) {
keysize = strlen((char *)key); keysize = strlen((char *)key);
for (i = 0; i < keysize; i++) { for (i = 0; i < keysize; i++) {
for (j = 0; j < NUM_OPS; j++) { for (j = 0; j < NUM_OPS; j++) {
OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8);
} }
} }
for (i = 0; i < NUM_OPS; i++) { for (i = 0; i < NUM_OPS; i++) {
@ -123,6 +123,7 @@ void VM::status(void) {
break; break;
} }
} }
DBG_INFO(("Flags: ZF = %d, CF = %d\n", flags.ZF, flags.CF));
DBG_SUCC(("~~~~~~~~~~\n")); DBG_SUCC(("~~~~~~~~~~\n"));
#endif #endif
return; return;
@ -277,6 +278,84 @@ bool VM::execSUBR(void) {
regs[dst] -= regs[src]; regs[dst] -= regs[src];
return true; return true;
} }
bool VM::execANDB(void) {
/*
ANDB 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(("ANDB %s, 0x%x\n", getRegName(dst), src));
regs[dst] &= src;
return true;
}
bool VM::execANDW(void) {
/*
ANDW 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::execANDR(void) {
/*
ANDR 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(("ANDR %s, 0x%x\n", getRegName(dst), src));
regs[dst] &= regs[src];
return true;
}
bool VM::execYORB(void) {
/*
YORB 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(("YORB %s, 0x%x\n", getRegName(dst), src));
regs[dst] |= src;
return true;
}
bool VM::execYORW(void) {
/*
YORW 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::execYORR(void) {
/*
YORR 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::execXORB(void) { bool VM::execXORB(void) {
/* /*
XORB R0, 0x2 -> R0 ^= 0x02 or R0 ^= [BYTE] 0x02 (low byte) XORB R0, 0x2 -> R0 ^= 0x02 or R0 ^= [BYTE] 0x02 (low byte)
@ -342,7 +421,19 @@ bool VM::execMULI(void) {
regs[dst] *= src; regs[dst] *= src;
return true; return true;
} }
bool VM::execMULR(void) { return true; } bool VM::execMULR(void) {
/*
MULR 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(("MULR %s, 0x%x\n", getRegName(dst), src));
regs[dst] *= regs[src];
return true;
}
bool VM::execDIVI(void) { bool VM::execDIVI(void) {
/* /*
DIVI R0, 0x2 | R0 /= 2 DIVI R0, 0x2 | R0 /= 2
@ -356,20 +447,224 @@ bool VM::execDIVI(void) {
regs[dst] /= src; regs[dst] /= src;
return true; return true;
} }
bool VM::execDIVR(void) { return true; } bool VM::execDIVR(void) {
bool VM::execPUSH(void) { return true; } /*
bool VM::execPOOP(void) { return true; } DIVR R0, R1 -> R0 /= R1
bool VM::execCMPI(void) { return true; } */
bool VM::execCMPR(void) { return true; } uint8_t dst;
bool VM::execJMPI(void) { return true; } uint8_t src;
bool VM::execJMPR(void) { return true; }
bool VM::execJPAI(void) { return true; } dst = as.code[regs[IP] + 1] >> 4;
bool VM::execJPAR(void) { return true; } src = as.code[regs[IP] + 1] & 0b00001111;
bool VM::execJPBI(void) { return true; } DBG_INFO(("ADDR %s, 0x%x\n", getRegName(dst), src));
bool VM::execJPBR(void) { return true; } regs[dst] /= regs[src];
bool VM::execJPEI(void) { return true; } return true;
bool VM::execJPER(void) { return true; } }
bool VM::execGRMN(void) { return true; } bool VM::execPUSH(void) {
// TODO: STACK < 0
uint8_t src;
src = as.code[regs[IP] + 1];
DBG_INFO(("PUSH %s\n", getRegName(src)));
memcpy(&as.stack[regs[SP]], &regs[src], sizeof(uint16_t));
regs[SP] += sizeof(uint16_t);
return true;
}
bool VM::execPOOP(void) {
// TODO: STACK < 0
uint8_t dst;
dst = as.code[regs[IP] + 1];
DBG_INFO(("POOP %s\n", getRegName(dst)));
regs[SP] -= sizeof(uint16_t);
memcpy(&regs[dst], &as.stack[regs[SP]], sizeof(uint16_t));
return true;
}
bool VM::execCMPI(void) {
/*
CMPI R0, 0x2 -> Compare immediate with register
*/
uint8_t reg;
uint16_t imm;
reg = as.code[regs[IP] + 1];
imm = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("CMPI %s, 0x%x\n", getRegName(reg), imm));
if (regs[reg] == imm) {
flags.ZF = 1;
} else {
flags.ZF = 0;
}
if (regs[reg] > imm) {
flags.CF = 1;
} else {
flags.CF = 0;
}
return true;
}
bool VM::execCMPR(void) {
/*
CMPR R0, R1 -> Compares 2 registers
*/
uint8_t r1;
uint8_t r2;
r1 = as.code[regs[IP] + 1] >> 4;
r2 = as.code[regs[IP] + 1] & 0b00001111;
DBG_INFO(("CMPR %s, %s\n", getRegName(r1), getRegName(r2)));
if (regs[r1] == regs[r2]) {
flags.ZF = 1;
} else {
flags.ZF = 0;
}
if (regs[r1] > regs[r2]) {
flags.CF = 1;
} else {
flags.CF = 0;
}
return true;
}
bool VM::execJMPI(void) {
/*
JMPI 0x2000 -> IP = 0x2000
*/
uint16_t imm;
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JMPI 0x%x\n", imm));
regs[IP] = imm;
return true;
}
bool VM::execJMPR(void) {
/*
JMPR R0 -> IP = R0
*/
uint8_t reg;
reg = as.code[regs[IP] + 1];
DBG_INFO(("JMPR %s = 0x%x\n", getRegName(reg), regs[reg]));
regs[IP] = regs[reg];
return true;
}
bool VM::execJPAI(void) {
/*
JPAI 0x2000 -> Jump to 0x2000 if above
*/
uint16_t imm;
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPAI 0x%x\n", imm));
if (flags.CF == 1) {
regs[IP] = imm;
return true;
}
return false;
}
bool VM::execJPAR(void) {
/*
JPAR R0 -> Jump to [R0] if above
*/
uint8_t reg;
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPAR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.CF == 1) {
regs[IP] = reg;
return true;
}
return false;
}
bool VM::execJPBI(void) {
/*
JPBI 0x2000 -> Jump to 0x2000 if below
*/
uint16_t imm;
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPBI 0x%x\n", imm));
if (flags.CF == 0) {
regs[IP] = imm;
return true;
}
return false;
}
bool VM::execJPBR(void) {
/*
JPBR R0 -> Jump to [R0] if below
*/
uint8_t reg;
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPBR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.CF == 0) {
regs[IP] = reg;
return true;
}
return false;
}
bool VM::execJPEI(void) {
/*
JPEI 0x2000 -> Jump to 0x2000 if equal
*/
uint16_t imm;
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPEI 0x%x\n", imm));
if (flags.ZF == 1) {
regs[IP] = imm;
return true;
}
return false;
}
bool VM::execJPER(void) {
/*
JPNR R0 -> Jump to [R0] if equal
*/
uint8_t reg;
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPER %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.ZF == 1) {
regs[IP] = reg;
return true;
}
return false;
}
bool VM::execJPNI(void) {
/*
JPEI 0x2000 -> Jump to 0x2000 if not equal
*/
uint16_t imm;
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPNI 0x%x\n", imm));
if (flags.ZF == 0) {
regs[IP] = imm;
return true;
}
return false;
}
bool VM::execJPNR(void) {
/*
JPER R0 -> Jump to [R0] if not equal
*/
uint8_t reg;
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPNR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.ZF == 0) {
regs[IP] = reg;
return true;
}
return false;
}
bool VM::execGRMN(void) {
uint8_t i;
for (i = 0; i < NUM_REGS; i++) {
regs[i] = 0x4747;
}
return true;
}
void VM::run(void) { void VM::run(void) {
uint8_t opcode; uint8_t opcode;
bool finished = false; bool finished = false;
@ -399,6 +694,24 @@ void VM::run(void) {
} else if (opcode == OPS[SUBR]) { } else if (opcode == OPS[SUBR]) {
execSUBR(); execSUBR();
regs[IP] += SUBR_SIZE; regs[IP] += SUBR_SIZE;
} else if (opcode == OPS[ANDB]) {
execANDB();
regs[IP] += ANDB_SIZE;
} else if (opcode == OPS[ANDW]) {
execANDW();
regs[IP] += ANDW_SIZE;
} else if (opcode == OPS[ANDR]) {
execANDR();
regs[IP] += ANDR_SIZE;
} else if (opcode == OPS[YORB]) {
execYORB();
regs[IP] += YORB_SIZE;
} else if (opcode == OPS[YORW]) {
execYORW();
regs[IP] += YORW_SIZE;
} else if (opcode == OPS[YORR]) {
execYORR();
regs[IP] += YORR_SIZE;
} else if (opcode == OPS[XORB]) { } else if (opcode == OPS[XORB]) {
execXORB(); execXORB();
regs[IP] += XORB_SIZE; regs[IP] += XORB_SIZE;
@ -434,28 +747,40 @@ void VM::run(void) {
regs[IP] += CMPR_SIZE; regs[IP] += CMPR_SIZE;
} else if (opcode == OPS[JMPI]) { } else if (opcode == OPS[JMPI]) {
execJMPI(); execJMPI();
regs[IP] += JMPI_SIZE;
} else if (opcode == OPS[JMPR]) { } else if (opcode == OPS[JMPR]) {
execJMPR(); execJMPR();
regs[IP] += JMPR_SIZE; } else if (opcode == OPS[JPAI]) {
}else if (opcode == OPS[JPAI]) { if (!execJPAI()) {
execJPAI(); regs[IP] += JPAI_SIZE;
regs[IP] += JPAI_SIZE; }
}else if (opcode == OPS[JPAR]) { } else if (opcode == OPS[JPAR]) {
execJPAR(); if (!execJPAR()) {
regs[IP] += JPAR_SIZE; regs[IP] += JPAR_SIZE;
}else if (opcode == OPS[JPBI]) { }
execJPBI(); } else if (opcode == OPS[JPBI]) {
regs[IP] += JPBI_SIZE; if (!execJPBI()) {
}else if (opcode == OPS[JPBR]) { regs[IP] += JPBI_SIZE;
execJPBR(); }
regs[IP] += JPBR_SIZE; } else if (opcode == OPS[JPBR]) {
}else if (opcode == OPS[JPEI]) { if (!execJPBR()) {
execJPEI(); regs[IP] += JPBR_SIZE;
regs[IP] += JPEI_SIZE; }
}else if (opcode == OPS[JPER]) { } else if (opcode == OPS[JPEI]) {
execJPER(); if (!execJPEI()) {
regs[IP] += JPER_SIZE; regs[IP] += JPEI_SIZE;
}
} else if (opcode == OPS[JPER]) {
if (!execJPER()) {
regs[IP] += JPER_SIZE;
}
} else if (opcode == OPS[JPNI]) {
if (!execJPNI()) {
regs[IP] += JPNI_SIZE;
}
} else if (opcode == OPS[JPNR]) {
if (!execJPNR()) {
regs[IP] += JPNR_SIZE;
}
} else if (opcode == OPS[GRMN]) { } else if (opcode == OPS[GRMN]) {
execGRMN(); execGRMN();
regs[IP] += GRMN_SIZE; regs[IP] += GRMN_SIZE;

19
vm/vm.h
View File

@ -4,6 +4,10 @@
#include <stdint.h> #include <stdint.h>
enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP, NUM_REGS }; enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP, NUM_REGS };
typedef struct flags {
uint8_t ZF : 1;
uint8_t CF : 1;
} flags_t;
class VM { class VM {
private: private:
@ -12,12 +16,9 @@ private:
//////////////////////// ////////////////////////
uint16_t regs[0xb]; uint16_t regs[0xb];
struct flags { flags_t flags;
uint8_t zf : 1;
uint8_t cf : 1;
};
VMAddrSpace as;
VMAddrSpace as;
//////////////////////// ////////////////////////
// FUNCTIONS // FUNCTIONS
/////////////////////// ///////////////////////
@ -39,6 +40,12 @@ private:
bool execADDR(void); bool execADDR(void);
bool execSUBI(void); bool execSUBI(void);
bool execSUBR(void); bool execSUBR(void);
bool execANDB(void);
bool execANDW(void);
bool execANDR(void);
bool execYORB(void);
bool execYORW(void);
bool execYORR(void);
bool execXORB(void); bool execXORB(void);
bool execXORW(void); bool execXORW(void);
bool execXORR(void); bool execXORR(void);
@ -59,6 +66,8 @@ private:
bool execJPBR(void); bool execJPBR(void);
bool execJPEI(void); bool execJPEI(void);
bool execJPER(void); bool execJPER(void);
bool execJPNI(void);
bool execJPNR(void);
bool execGRMN(void); bool execGRMN(void);
public: public:

View File

@ -47,10 +47,9 @@ bool VMAddrSpace::allocate(void) {
return false; return false;
} }
memset(code, 0xff, memset(code, 0xff, codesize); // auto halt in case the assembly is not correct
stacksize); // auto halt in case the assembly is not correct
memset(stack, 0x0, stacksize); memset(stack, 0x0, stacksize);
memset(data, 0x0, stacksize); memset(data, 0x0, datasize);
DBG_SUCC(("Done!\n")); DBG_SUCC(("Done!\n"));
return true; return true;
} }