Polishing. Alcune implementazioni
This commit is contained in:
		
							parent
							
								
									8eab267645
								
							
						
					
					
						commit
						020a5062a2
					
				| @ -59,7 +59,7 @@ class VMAssembler: | ||||
|         self.define_ops(key) | ||||
| 
 | ||||
|     def parse(self, instruction): | ||||
|         action = getattr(self, "op_{}".format(instruction.opcode.name)) | ||||
|         action = getattr(self, "{}".format(instruction.opcode.method)) | ||||
|         action(instruction) | ||||
| 
 | ||||
|     def process_code_line(self, line): | ||||
| @ -125,36 +125,66 @@ class VMAssembler: | ||||
|         self.assembled_code += opcode.uint8() + imm.uint16() + reg.uint8() | ||||
|         return | ||||
| 
 | ||||
|     def imm(self, instruction): | ||||
|     def byt2reg(self, instruction): | ||||
|         """ | ||||
|         Intel syntax -> REG, [BYTE]IMM | ||||
|         """ | ||||
|         opcode = instruction.opcode | ||||
|         reg = instruction.args[0] | ||||
|         imm = instruction.args[1] | ||||
|         if reg.name == "ip": | ||||
|             raise IPOverwrite(instruction) | ||||
|         if not imm.isimm(): | ||||
|             raise ExpectedImmediate(imm) | ||||
|         if not reg.isreg(): | ||||
|             raise ExpectedRegister(reg) | ||||
|         if not opcode.uint8() or not reg.uint8() or not imm.uint8(): | ||||
|             raise InvalidValue(instruction) | ||||
|         self.assembled_code += opcode.uint8() + reg.uint8() + imm.uint8() | ||||
|         return | ||||
| 
 | ||||
|     def op_movi(self, instruction): | ||||
|         self.imm2reg(instruction) | ||||
|     def regonly(self, instruction): | ||||
|         """ | ||||
|         Instruction with only an argument: a register | ||||
|         """ | ||||
|         opcode = instruction.opcode | ||||
|         reg = instruction.args[0] | ||||
|         if reg.name == "ip": | ||||
|             raise IPOverwrite(instruction) | ||||
|         if not reg.isreg(): | ||||
|             raise ExpectedRegister(reg) | ||||
|         if not opcode.uint8() or not reg.uint8(): | ||||
|             raise InvalidValue(instruction) | ||||
|         self.assembled_code += opcode.uint8() + reg.uint8() | ||||
|         return | ||||
| 
 | ||||
|     def op_movr(self, instruction): | ||||
|         self.reg2reg(instruction) | ||||
|     def immonly(self, instruction): | ||||
|         """ | ||||
|         Instruction with only an argument: an immediate | ||||
|         """ | ||||
|         opcode = instruction.opcode | ||||
|         imm = instruction.args[0] | ||||
|         if not imm.isimm(): | ||||
|             raise ExpectedImmediate(imm) | ||||
|         if not opcode.uint8() or not imm.uint16(): | ||||
|             raise InvalidValue(instruction) | ||||
|         self.assembled_code += opcode.uint8() + imm.uint16() | ||||
|         return | ||||
| 
 | ||||
|     def op_load(self, instruction): | ||||
|         self.imm2reg(instruction) | ||||
| 
 | ||||
|     def op_stor(self, instruction): | ||||
|         self.reg2imm(instruction) | ||||
| 
 | ||||
|     def op_addi(self, instruction): | ||||
|         self.imm2reg(instruction) | ||||
| 
 | ||||
|     def op_addr(self, instruction): | ||||
|         self.reg2reg(instruction) | ||||
|     def single(self, instruction): | ||||
|         """ | ||||
|         Instruction with no arguments | ||||
|         """ | ||||
|         opcode = instruction.opcode | ||||
|         self.assembled_code += opcode.uint8() | ||||
|         return | ||||
| 
 | ||||
|     def define_ops(self, key): | ||||
|         key_ba = bytearray(key, 'utf-8') | ||||
|         olds = copy.deepcopy(ops) | ||||
|         for b in key_ba: | ||||
|             for op_com in ops: | ||||
|                 if b % 2: | ||||
|                 op_com.set_value(rol(b ^ op_com.value, b % 8, 8)) | ||||
|                 else: | ||||
|                     op_com.set_value(rol(b ^ op_com.value, (b + 1) % 8, 8)) | ||||
|         for i in ops: | ||||
|             for j in ops: | ||||
|                 j.set_value(rol(j.value, i.value % 8, 8)) | ||||
| @ -167,9 +197,10 @@ class VMComponent: | ||||
|     Represents a register, operation or an immediate the VM recognizes | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, name, value): | ||||
|     def __init__(self, name, value, method=None): | ||||
|         self.name = name.casefold() | ||||
|         self.value = value | ||||
|         self.method = method | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return "{}".format(self.name) | ||||
| @ -206,7 +237,7 @@ class VMComponent: | ||||
|         return True | ||||
| 
 | ||||
|     def isop(self): | ||||
|         if self.name not in [x.casefold() for x in op_names]: | ||||
|         if self.name not in [x[0].casefold() for x in op_names]: | ||||
|             return False | ||||
|         return True | ||||
| 
 | ||||
| @ -240,38 +271,42 @@ class VMInstruction: | ||||
|     def __repr__(self): | ||||
|         return "{} {}".format(self.opcode.name, ", ".join([x.name for x in self.args])) | ||||
| 
 | ||||
| op_names = ["MOVI", | ||||
|             "MOVR", | ||||
|             "LOAD", | ||||
|             "STOR", | ||||
|             "ADDI", | ||||
|             "ADDR", | ||||
|             "SUBI", | ||||
|             "SUBR", | ||||
|             "XORB", | ||||
|             "XORW", | ||||
|             "XORR", | ||||
|             "NOTR", | ||||
|             "MULI", | ||||
|             "MULR", | ||||
|             "DIVI", | ||||
|             "DIVR", | ||||
|             "PUSH", | ||||
|             "POOP", | ||||
|             "CMPI", | ||||
|             "CMPR", | ||||
|             "JUMP", | ||||
|             "JMPA", | ||||
|             "JMPB", | ||||
|             "JMPE", | ||||
|             "SHIT", | ||||
|             "NOPE", | ||||
|             "GRMN"] | ||||
| op_names = [["MOVI", "imm2reg"], | ||||
|             ["MOVR", "reg2reg"], | ||||
|             ["LOAD", "imm2reg"], | ||||
|             ["STOR", "reg2imm"], | ||||
|             ["ADDI", "imm2reg"], | ||||
|             ["ADDR", "reg2reg"], | ||||
|             ["SUBI", "imm2reg"], | ||||
|             ["SUBR", "reg2reg"], | ||||
|             ["XORB", "byt2reg"], | ||||
|             ["XORW", "imm2reg"], | ||||
|             ["XORR", "reg2reg"], | ||||
|             ["NOTR", "regonly"], | ||||
|             ["MULI", "imm2reg"], | ||||
|             ["MULR", "reg2reg"], | ||||
|             ["DIVI", "imm2reg"], | ||||
|             ["DIVR", "reg2reg"], | ||||
|             ["PUSH", "regonly"], | ||||
|             ["POOP", "regonly"], | ||||
|             ["CMPI", "imm2reg"], | ||||
|             ["CMPR", "reg2reg"], | ||||
|             ["JMPI", "immonly"], | ||||
|             ["JMPR", "regonly"], | ||||
|             ["JPAI", "immonly"], | ||||
|             ["JPAR", "regonly"], | ||||
|             ["JPBI", "immonly"], | ||||
|             ["JPBR", "regonly"], | ||||
|             ["JPEI", "immonly"], | ||||
|             ["JPER", "regonly"], | ||||
|             ["SHIT", "single"], | ||||
|             ["NOPE", "single"], | ||||
|             ["GRMN", "single"]] | ||||
| 
 | ||||
| reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] | ||||
| section_names = ["DATA:", "CODE:", "STACK:"] | ||||
| section_flags = {s.casefold(): i + 1 for i, s in enumerate(section_names)} | ||||
| ops = [VMComponent(s.casefold(), i) for i, s in enumerate(op_names)] | ||||
| ops = [VMComponent(le[0], i, le[1]) for i, le in enumerate(op_names)] | ||||
| regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)] | ||||
| 
 | ||||
| 
 | ||||
| @ -22,10 +22,14 @@ enum OPS_STARTING_VALUES { | ||||
|   POOP, | ||||
|   CMPI, | ||||
|   CMPR, | ||||
|   JUMP, | ||||
|   JMPA, | ||||
|   JMPB, | ||||
|   JMPE, | ||||
|   JMPI, | ||||
|   JMPR, | ||||
|   JPAI, | ||||
|   JPAR, | ||||
|   JPBI, | ||||
|   JPBR, | ||||
|   JPEI, | ||||
|   JPER, | ||||
|   SHIT, | ||||
|   NOPE, | ||||
|   GRMN, | ||||
| @ -41,7 +45,8 @@ INSTRUCTION SIZE TYPES | ||||
| #define IMM2REG 4 | ||||
| #define REG2IMM 4 | ||||
| #define BYT2REG 3 | ||||
| #define UNARY 2 | ||||
| #define REGONLY 2 | ||||
| #define IMMONLY 3 | ||||
| #define SINGLE 1 | ||||
| 
 | ||||
| /*
 | ||||
| @ -58,19 +63,23 @@ INSTRUCTION SIZES | ||||
| #define XORB_SIZE BYT2REG | ||||
| #define XORW_SIZE IMM2REG | ||||
| #define XORR_SIZE REG2REG | ||||
| #define NOTR_SIZE UNARY | ||||
| #define NOTR_SIZE REGONLY | ||||
| #define MULI_SIZE IMM2REG | ||||
| #define MULR_SIZE REG2REG | ||||
| #define DIVI_SIZE IMM2REG | ||||
| #define DIVR_SIZE REG2REG | ||||
| #define PUSH_SIZE UNARY | ||||
| #define POOP_SIZE UNARY | ||||
| #define PUSH_SIZE REGONLY | ||||
| #define POOP_SIZE REGONLY | ||||
| #define CMPI_SIZE IMM2REG | ||||
| #define CMPR_SIZE REG2REG | ||||
| #define JUMP_SIZE UNARY | ||||
| #define JMPA_SIZE UNARY | ||||
| #define JMPB_SIZE UNARY | ||||
| #define JMPE_SIZE UNARY | ||||
| #define JMPI_SIZE IMMONLY | ||||
| #define JMPR_SIZE REGONLY | ||||
| #define JPAI_SIZE IMMONLY | ||||
| #define JPAR_SIZE REGONLY | ||||
| #define JPBI_SIZE IMMONLY | ||||
| #define JPBR_SIZE REGONLY | ||||
| #define JPEI_SIZE IMMONLY | ||||
| #define JPER_SIZE REGONLY | ||||
| #define SHIT_SIZE SINGLE | ||||
| #define NOPE_SIZE SINGLE | ||||
| #define GRMN_SIZE SINGLE | ||||
| @ -14,11 +14,7 @@ void VM::defineOpcodes(uint8_t *key) { | ||||
|   keysize = strlen((char *)key); | ||||
|   for (i = 0; i < keysize; i++) { | ||||
|     for (j = 0; j < NUM_OPS; j++) { | ||||
|       if (key[i] % 2) { | ||||
|         OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); | ||||
|       } else { | ||||
|         OPS[j] = rol(key[i] ^ OPS[j], (key[i] + 1) % 8, 8); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   for (i = 0; i < NUM_OPS; i++) { | ||||
| @ -185,7 +181,7 @@ bool VM::execMOVI(void) { | ||||
| 
 | ||||
| bool VM::execMOVR(void) { | ||||
|   /*
 | ||||
|   MOVR R1, R0 | R1 = R0 | ||||
|   MOVR R1, R0 -> R1 = R0 | ||||
|   --------------------- | ||||
|   R1, R0 = 0x10 <- DST / SRC are nibbles! | ||||
|   */ | ||||
| @ -203,7 +199,7 @@ bool VM::execMOVR(void) { | ||||
| 
 | ||||
| bool VM::execLOAD(void) { | ||||
|   /*
 | ||||
|   LOAD R0, 0x1000 | R0 = data[0x1000] | ||||
|   LOAD R0, 0x1000 -> R0 = data[0x1000] | ||||
|   */ | ||||
|   uint8_t dst; | ||||
|   uint16_t src; | ||||
| @ -216,7 +212,7 @@ bool VM::execLOAD(void) { | ||||
| 
 | ||||
| bool VM::execSTOR(void) { | ||||
|   /*
 | ||||
|   STOR 0x1000, R0 | data[0x1000] = R0 | ||||
|   STOR 0x1000, R0 -> data[0x1000] = R0 | ||||
|   */ | ||||
|   uint16_t dst; | ||||
|   uint8_t src; | ||||
| @ -229,7 +225,7 @@ bool VM::execSTOR(void) { | ||||
| 
 | ||||
| bool VM::execADDI(void) { | ||||
|   /*
 | ||||
|   ADDI R0, 0x2 | R0 += 2 | ||||
|   ADDI R0, 0x2 -> R0 += 2 | ||||
|   */ | ||||
|   uint8_t dst; | ||||
|   uint16_t src; | ||||
| @ -242,6 +238,9 @@ bool VM::execADDI(void) { | ||||
| } | ||||
| 
 | ||||
| bool VM::execADDR(void) { | ||||
|   /*
 | ||||
|   ADDR R0, R1 -> R0 += R1 | ||||
|   */ | ||||
|   uint8_t dst; | ||||
|   uint8_t src; | ||||
| 
 | ||||
| @ -252,24 +251,124 @@ bool VM::execADDR(void) { | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool VM::execSUBI(void) { return true; } | ||||
| bool VM::execSUBR(void) { return true; } | ||||
| bool VM::execXORB(void) { return true; } | ||||
| bool VM::execXORW(void) { return true; } | ||||
| bool VM::execXORR(void) { return true; } | ||||
| bool VM::execNOTR(void) { return true; } | ||||
| bool VM::execMULI(void) { 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) { 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::execJUMP(void) { return true; } | ||||
| bool VM::execJMPA(void) { return true; } | ||||
| bool VM::execJMPB(void) { return true; } | ||||
| bool VM::execJMPE(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; | ||||
| @ -333,22 +432,35 @@ void VM::run(void) { | ||||
|     } else if (opcode == OPS[CMPR]) { | ||||
|       execCMPR(); | ||||
|       regs[IP] += CMPR_SIZE; | ||||
|     } else if (opcode == OPS[JUMP]) { | ||||
|       execJUMP(); | ||||
|       regs[IP] += JUMP_SIZE; | ||||
|     } else if (opcode == OPS[JMPA]) { | ||||
|       execJMPA(); | ||||
|       regs[IP] += JMPA_SIZE; | ||||
|     } else if (opcode == OPS[JMPB]) { | ||||
|       execJMPB(); | ||||
|       regs[IP] += JMPB_SIZE; | ||||
|     } else if (opcode == OPS[JMPE]) { | ||||
|       execJMPE(); | ||||
|       regs[IP] += JMPE_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; | ||||
| @ -51,10 +51,14 @@ private: | ||||
|   bool execPOOP(void); | ||||
|   bool execCMPI(void); | ||||
|   bool execCMPR(void); | ||||
|   bool execJUMP(void); | ||||
|   bool execJMPA(void); | ||||
|   bool execJMPB(void); | ||||
|   bool execJMPE(void); | ||||
|   bool execJMPI(void); | ||||
|   bool execJMPR(void); | ||||
|   bool execJPAI(void); | ||||
|   bool execJPAR(void); | ||||
|   bool execJPBI(void); | ||||
|   bool execJPBR(void); | ||||
|   bool execJPEI(void); | ||||
|   bool execJPER(void); | ||||
|   bool execGRMN(void); | ||||
| 
 | ||||
| public: | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user