diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..b4b0025f1 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,36 +1,63 @@ +# cpu.py + """CPU functionality.""" import sys +import os class CPU: """Main CPU class.""" def __init__(self): - """Construct a new CPU.""" - pass - - def load(self): + # Set RAM + self.ram = [0] * 256 + # Create registers: R0 - R6 empty + self.reg = [0] * 8 + # R7 set to 0xF4 + self.reg[7] = 0xF4 + + # Set program counter to 0 + self.pc = 0 + # Set flags to 0 + self.fl = 0 + # Memory Address Register, holds the memory address we're reading or writing + self.mar = 0 + # #Memory Data Register, holds the value to write or the value just read + self.mdr = 0 + # Points to the register that contains address of stack pointer + self.sp = 7 + + def load(self, file_name): """Load a program into memory.""" address = 0 - - # For now, we've just hardcoded a program: - - program = [ - # From print8.ls8 - 0b10000010, # LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, # PRN R0 - 0b00000000, - 0b00000001, # HLT - ] + program = [] + self.reg[self.sp] = len(self.ram) - 1 + + input_text = os.path.join(os.path.dirname(__file__), f"examples/{file_name}") + + try: + with open(input_text) as my_file: + for line in my_file: + comment_split = line.split('#') + possible_binary_number = comment_split[0] + + try: + x = int(possible_binary_number, 2) + # print("{:08b}: {:d}".format(x, x)) + program.append(x) + except: + print(f"Failed to cast {possible_binary_number} to an int") + continue + except: + print(f"File: {file_name} not found...") for instruction in program: self.ram[address] = instruction address += 1 + def alu(self, op, reg_a, reg_b): """ALU operations.""" @@ -40,6 +67,12 @@ def alu(self, op, reg_a, reg_b): else: raise Exception("Unsupported ALU operation") + def ram_read(self, mar): + return self.ram[mar] + + def ram_write(self, mar, mdr): + self.ram[mar] = mdr + def trace(self): """ Handy function to print out the CPU state. You might want to call this @@ -62,4 +95,63 @@ def trace(self): def run(self): """Run the CPU.""" - pass + + running = True + ldi = 0b10000010 + prn = 0b01000111 + hlt = 0b00000001 + mul = 0b10100010 + push = 0b01000101 + pop = 0b01000110 + call = 0b01010000 + ret = 0b00010001 + + while running: + # print(self.pc) + command_to_execute = self.ram_read(self.pc) + op_a = self.ram_read(self.pc + 1) + op_b = self.ram_read(self.pc + 2) + + if command_to_execute == ldi: + print("LDI executed") + self.reg[op_a] = self.pc + 2 + self.pc += (command_to_execute >> 6) + 1 + elif command_to_execute == prn: + print("Print executed") + print(self.reg[op_a]) + self.pc += (command_to_execute >> 6) + 1 + elif command_to_execute == mul: + print("Mult executed") + print(op_a, op_b) + self.reg[op_a] *= self.reg[op_b] + self.pc += (command_to_execute >> 6) + 1 + elif command_to_execute == hlt: + print("Halt executed") + running = False + elif command_to_execute == push: + self.reg[self.sp] -= 1 + register_to_get_value_in = self.ram[self.pc + 1] + value_in_register = self.reg[register_to_get_value_in] + self.ram[self.reg[self.sp]] = value_in_register + print(f"Pushing: {value_in_register}") + self.pc += (command_to_execute >> 6) + 1 + elif command_to_execute == pop: + register_to_pop_value_in = self.ram[self.pc + 1] + self.reg[register_to_pop_value_in] = self.ram[self.reg[self.sp]] + self.reg[self.sp] += 1 + print(f"Popping: {self.reg[register_to_pop_value_in]}") + self.pc += (command_to_execute >> 6) + 1 + elif command_to_execute == call: + self.reg[self.sp] -= 1 + address_of_next_instruction = self.pc + 2 + self.ram[self.reg[self.sp]] = address_of_next_instruction + register_to_get_address_from = self.ram[self.pc + 1] + self.pc = self.reg[register_to_get_address_from] + elif command_to_execute == ret: + self.pc = self.ram[self.reg[self.sp]] + self.reg[self.sp] += 1 + else: + print(f"Unkown command: {command_to_execute}") + self.pc += (command_to_execute >> 6) + 1 + + self.trace() diff --git a/ls8/ls8.py b/ls8/ls8.py index 74128d36b..61ebaaf2c 100755 --- a/ls8/ls8.py +++ b/ls8/ls8.py @@ -6,6 +6,5 @@ from cpu import * cpu = CPU() - -cpu.load() -cpu.run() \ No newline at end of file +cpu.load("call.ls8") #fileNameFromCommandLine +cpu.run()