SHLI, SHLR, SHRI, SHRL, DIVR
This commit is contained in:
		
							parent
							
								
									3c453485b1
								
							
						
					
					
						commit
						0dfd9bdb57
					
				@ -49,6 +49,7 @@ class InvalidValue(AssemblerException):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMAssembler:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, key, data):
 | 
			
		||||
        self.data = data
 | 
			
		||||
        self.assembled_code = bytearray()
 | 
			
		||||
@ -79,13 +80,15 @@ class VMAssembler:
 | 
			
		||||
 | 
			
		||||
        # putting main in first position in order to assemble it first
 | 
			
		||||
        for i, f in enumerate(self.functions):
 | 
			
		||||
             if f.name == "main" and i is not 0:
 | 
			
		||||
                 self.functions[0], self.functions[i] = self.functions[i], self.functions[0]
 | 
			
		||||
                 break
 | 
			
		||||
            if f.name == "main" and i is not 0:
 | 
			
		||||
                self.functions[0], self.functions[
 | 
			
		||||
                    i] = self.functions[i], self.functions[0]
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        # calculating functions offsets
 | 
			
		||||
        for i in range(1, len(self.functions)):
 | 
			
		||||
            prev_fun_tot_size = self.functions[i-1].size + self.functions[i-1].offset
 | 
			
		||||
            prev_fun_tot_size = self.functions[
 | 
			
		||||
                i - 1].size + self.functions[i - 1].offset
 | 
			
		||||
            cur_fun_size = self.functions[i].size
 | 
			
		||||
            self.functions[i].set_offset(prev_fun_tot_size)
 | 
			
		||||
        return
 | 
			
		||||
@ -209,7 +212,8 @@ class VMAssembler:
 | 
			
		||||
            # the symbal has not been resolved
 | 
			
		||||
            if dst.name == dst.value:
 | 
			
		||||
                # check whether it is a function
 | 
			
		||||
                val = next((x.offset for x in self.functions if x.name == dst.name), None)
 | 
			
		||||
                val = next(
 | 
			
		||||
                    (x.offset for x in self.functions if x.name == dst.name), None)
 | 
			
		||||
                # check whether it is a label
 | 
			
		||||
                if val == None:
 | 
			
		||||
                    for f in self.functions:
 | 
			
		||||
@ -254,7 +258,9 @@ class VMAssembler:
 | 
			
		||||
        for o, n in zip(olds, ops):
 | 
			
		||||
            print("{} : {}->{}".format(o.name, hex(o.value), hex(n.value)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMFunction:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name, code):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.size = 0
 | 
			
		||||
@ -269,11 +275,12 @@ class VMFunction:
 | 
			
		||||
            label = label_re.match(line)
 | 
			
		||||
            if label:
 | 
			
		||||
                label_name = label.group(1)
 | 
			
		||||
                self.instructions.append(VMInstruction(code[i+1], label_name))
 | 
			
		||||
                self.instructions.append(
 | 
			
		||||
                    VMInstruction(code[i + 1], label_name))
 | 
			
		||||
                i += 2
 | 
			
		||||
            elif ins:
 | 
			
		||||
                self.instructions.append(VMInstruction(line))
 | 
			
		||||
                i+= 1
 | 
			
		||||
                i += 1
 | 
			
		||||
            else:
 | 
			
		||||
                raise InvalidOperation(line)
 | 
			
		||||
        self.calc_size()
 | 
			
		||||
@ -297,6 +304,7 @@ class VMFunction:
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return "{}: size {}, offset {}".format(self.name, hex(self.size), hex(self.offset))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMInstruction:
 | 
			
		||||
    """
 | 
			
		||||
    Represents an instruction the VM recognizes.
 | 
			
		||||
@ -305,7 +313,7 @@ class VMInstruction:
 | 
			
		||||
        opcode  args
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, line, label = None):
 | 
			
		||||
    def __init__(self, line, label=None):
 | 
			
		||||
        self.opcode = None
 | 
			
		||||
        self.args = []
 | 
			
		||||
        self.size = 1
 | 
			
		||||
@ -314,7 +322,7 @@ class VMInstruction:
 | 
			
		||||
        ins = instruction_re.match(line)
 | 
			
		||||
        symcall = symcall_re.match(line)
 | 
			
		||||
 | 
			
		||||
        opcode =  ins.group(1)
 | 
			
		||||
        opcode = ins.group(1)
 | 
			
		||||
        self.opcode = next((x for x in ops if x.name == opcode), None)
 | 
			
		||||
        if self.opcode == None:
 | 
			
		||||
            raise InvalidOperation(opcode)
 | 
			
		||||
@ -344,7 +352,7 @@ class VMComponent:
 | 
			
		||||
    Represents a register, operation or an immediate the VM recognizes
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, name, value, method = None):
 | 
			
		||||
    def __init__(self, name, value, method=None):
 | 
			
		||||
        self.name = name.casefold()
 | 
			
		||||
        self.value = value
 | 
			
		||||
        self.method = method
 | 
			
		||||
@ -420,6 +428,10 @@ op_names = [["MOVI", "imm2reg"],
 | 
			
		||||
            ["MULR", "reg2reg"],
 | 
			
		||||
            ["DIVI", "imm2reg"],
 | 
			
		||||
            ["DIVR", "reg2reg"],
 | 
			
		||||
            ["SHLI", "imm2reg"],
 | 
			
		||||
            ["SHLR", "reg2reg"],
 | 
			
		||||
            ["SHRI", "imm2reg"],
 | 
			
		||||
            ["SHRR", "reg2reg"],
 | 
			
		||||
            ["PUSH", "regonly"],
 | 
			
		||||
            ["POOP", "regonly"],
 | 
			
		||||
            ["CMPI", "imm2reg"],
 | 
			
		||||
@ -442,7 +454,8 @@ op_names = [["MOVI", "imm2reg"],
 | 
			
		||||
reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"]
 | 
			
		||||
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)]
 | 
			
		||||
instruction_re = re.compile("^([\w]{4})(?:\ +(?:([\w]+)\ *(?:,[\ ]*([\w]+))*))?$") # 1: opcode 2+: args
 | 
			
		||||
instruction_re = re.compile(
 | 
			
		||||
    "^([\w]{4})(?:\ +(?:([\w]+)\ *(?:,[\ ]*([\w]+))*))?$")  # 1: opcode 2+: args
 | 
			
		||||
function_re = re.compile("(?:def\ )([a-zA-Z]*)\:")
 | 
			
		||||
immediate_re = re.compile("(?:0x)?[0-9a-fA-F]+$")
 | 
			
		||||
alpha_re = re.compile("^[a-zA-Z]*$")
 | 
			
		||||
@ -450,6 +463,7 @@ register_re = re.compile("(^[rRsS][0-4]$)|([iIrRsS][pP]$)")
 | 
			
		||||
label_re = re.compile("^([a-zA-Z]+)\:$")
 | 
			
		||||
symcall_re = re.compile("^([jJ][pPmM][pPaAbBeEnN][iIrR])\ +([\w]*)$")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    if len(sys.argv) < 4:
 | 
			
		||||
        print("Usage: {} opcodes_key file_to_assemble output".format(
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,10 @@ enum OPS_STARTING_VALUES {
 | 
			
		||||
  MULR,
 | 
			
		||||
  DIVI,
 | 
			
		||||
  DIVR,
 | 
			
		||||
  SHLI,
 | 
			
		||||
  SHLR,
 | 
			
		||||
  SHRI,
 | 
			
		||||
  SHRR,
 | 
			
		||||
  PUSH,
 | 
			
		||||
  POOP,
 | 
			
		||||
  CMPI,
 | 
			
		||||
@ -83,6 +87,10 @@ INSTRUCTION SIZES
 | 
			
		||||
#define MULR_SIZE REG2REG
 | 
			
		||||
#define DIVI_SIZE IMM2REG
 | 
			
		||||
#define DIVR_SIZE REG2REG
 | 
			
		||||
#define SHLI_SIZE IMM2REG
 | 
			
		||||
#define SHLR_SIZE REG2REG
 | 
			
		||||
#define SHRI_SIZE IMM2REG
 | 
			
		||||
#define SHRR_SIZE REG2REG
 | 
			
		||||
#define PUSH_SIZE REGONLY
 | 
			
		||||
#define POOP_SIZE REGONLY
 | 
			
		||||
#define CMPI_SIZE IMM2REG
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								vm/vm.cpp
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								vm/vm.cpp
									
									
									
									
									
								
							@ -459,10 +459,62 @@ bool VM::execDIVR(void) {
 | 
			
		||||
 | 
			
		||||
  dst = as.code[regs[IP] + 1] >> 4;
 | 
			
		||||
  src = as.code[regs[IP] + 1] & 0b00001111;
 | 
			
		||||
  DBG_INFO(("ADDR %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  DBG_INFO(("DIVR %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  regs[dst] /= regs[src];
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
bool VM::execSHLI(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(("SHLI %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  regs[dst] = regs[dst] << src;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
bool VM::execSHLR(void) {
 | 
			
		||||
  /*
 | 
			
		||||
  SHLR 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(("SHLR %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  regs[dst] = regs[dst] << regs[src];
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
bool VM::execSHRI(void) {
 | 
			
		||||
  /*
 | 
			
		||||
  SHRI 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(("SHRI %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  regs[dst] = regs[dst] >> src;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
bool VM::execSHRR(void) {
 | 
			
		||||
  /*
 | 
			
		||||
  SHRR 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(("SHRR %s, 0x%x\n", getRegName(dst), src));
 | 
			
		||||
  regs[dst] = regs[dst] >> regs[src];
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
bool VM::execPUSH(void) {
 | 
			
		||||
  // TODO: STACK < 0
 | 
			
		||||
  uint8_t src;
 | 
			
		||||
@ -755,6 +807,21 @@ void VM::run(void) {
 | 
			
		||||
    } else if (opcode == OPS[DIVI]) {
 | 
			
		||||
      execDIVI();
 | 
			
		||||
      regs[IP] += DIVI_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[DIVR]) {
 | 
			
		||||
      execDIVR();
 | 
			
		||||
      regs[IP] += DIVR_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[SHLI]) {
 | 
			
		||||
      execSHLI();
 | 
			
		||||
      regs[IP] += SHLI_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[SHLR]) {
 | 
			
		||||
      execSHLR();
 | 
			
		||||
      regs[IP] += SHLR_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[SHRI]) {
 | 
			
		||||
      execSHRI();
 | 
			
		||||
      regs[IP] += SHRI_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[SHRR]) {
 | 
			
		||||
      execSHRR();
 | 
			
		||||
      regs[IP] += SHRR_SIZE;
 | 
			
		||||
    } else if (opcode == OPS[PUSH]) {
 | 
			
		||||
      execPUSH();
 | 
			
		||||
      regs[IP] += PUSH_SIZE;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user