# CSPT10 Computer Architecture IV ## CALL/RET ``` import sys PRINT_HI = 1 HALT = 2 PRINT_NUM = 3 SAVE = 4 # save a value to a register PRINT_REGISTER = 5 # prints the value of a register ADD = 6 # adds values from two registers x, y and stores it in register x PUSH = 7 POP = 8 CALL = 9 RET = 10 PRINT_SUBROUTINE_INSTRUCTION = 11 def loadMemory(): memory = [ PRINT_HI, # prints hi SAVE, # saves 7 into register 2 7, 2, CALL, # jump to the address stored in register 2 2, HALT, # stop the program PRINT_SUBROUTINE_INSTRUCTION, SAVE, 500, 0, RET # jump back to address stored in the top of the stack (7, which is HALT) ] spaceForStack = 128 - len(memory) memory += [0] * spaceForStack return memory memory = loadMemory() SP = 7 # register number for stack pointer pc = 0 # program counter - points to the instruction we're currently executing running = True registers = [0] * 8 registers[SP] = 127 while running: commandToExecute = memory[pc] if commandToExecute == PRINT_HI: print("hi") pc += 1 elif commandToExecute == HALT: running = False elif commandToExecute == PRINT_NUM: numToPrint = memory[pc + 1] print(numToPrint) pc += 2 elif commandToExecute == PRINT_REGISTER: reg = memory[pc + 1] print(registers[reg]) pc += 2 elif commandToExecute == SAVE: numToSave = memory[pc + 1] registerToSaveItIn = memory[pc + 2] registers[registerToSaveItIn] = numToSave pc += 3 elif commandToExecute == ADD: regA = memory[pc + 1] regB = memory[pc + 2] sumOfRegisters = registers[regA] + registers[regB] registers[regA] = sumOfRegisters pc += 3 elif commandToExecute == PUSH: registers[SP] -= 1 registerToGetValueIn = memory[pc + 1] valueInRegister = registers[registerToGetValueIn] memory[registers[SP]] = valueInRegister pc += 2 elif commandToExecute == POP: registerToPopValueIn = memory[pc + 1] registers[registerToPopValueIn] = memory[registers[SP]] registers[SP] += 1 pc += 2 elif commandToExecute == CALL: # store address of the next instruction onto the stack registers[SP] -= 1 addressOfNextInstruction = pc + 2 memory[registers[SP]] = addressOfNextInstruction # jump to the address stored in the given register registerToGetAddressFrom = memory[pc + 1] addressToJumpTo = registers[registerToGetAddressFrom] pc = addressToJumpTo elif commandToExecute == RET: # pop the topmost value in the stack addressToReturnTo = memory[registers[SP]] memory[registers[SP]] += 1 # set the pc to that value pc = addressToReturnTo elif commandToExecute == PRINT_SUBROUTINE_INSTRUCTION: print("i'm in a subroutine") pc += 1 else: print("ehh idk what to do") sys.exit(1) print(registers) ``` ## Guided Project Pt III ``` """CPU functionality.""" import sys HLT = 0b00000001 LDI = 0b10000010 PRN = 0b01000111 MULT = 0b10100010 PUSH = 0b01000101 POP = 0b01000110 SP = 7 class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" self.pc = 0 self.halted = False self.ram = [0] * 256 self.reg = [0] * 8 self.reg[7] = 0xF4 def load(self, filename): """Load a program into memory.""" address = 0 with open(filename) as fp: for line in fp: comment_split = line.split("#") num = comment_split[0].strip() if num == '': # ignore blanks continue val = int(num, 2) self.ram_write(val, address) address += 1 # Stores value in specified address in ram def ram_write(self, value, address): self.ram[address] = value # Returns value in ram stored in address def ram_read(self, address): return self.ram[address] def alu(self, op, reg_a, reg_b): """ALU operations.""" if op == "ADD": self.reg[reg_a] += self.reg[reg_b] #elif op == "SUB": etc else: raise Exception("Unsupported ALU operation") def trace(self): """ Handy function to print out the CPU state. You might want to call this from run() if you need help debugging. """ print(f"TRACE: %02X | %02X %02X %02X |" % ( self.pc, #self.fl, #self.ie, self.ram_read(self.pc), self.ram_read(self.pc + 1), self.ram_read(self.pc + 2) ), end='') for i in range(8): print(" %02X" % self.reg[i], end='') print() def run(self): """Run the CPU.""" while not self.halted: # self.trace() instruction_to_execute = self.ram[self.pc] operand_a = self.ram[self.pc + 1] operand_b = self.ram[self.pc + 2] self.execute_instruction(instruction_to_execute, operand_a, operand_b) def execute_instruction(self, instruction, operand_a, operand_b): if instruction == HLT: self.halted = True self.pc += 1 elif instruction == PRN: print(self.reg[operand_a]) self.pc += 2 elif instruction == LDI: self.reg[operand_a] = operand_b self.pc += 3 elif instruction == MULT: self.reg[operand_a] *= self.reg[operand_b] self.pc += 3 elif instruction == PUSH: # decrement the stack pointer self.reg[SP] -= 1 # write the value stored in register onto the stack valueFromRegister = self.reg[operand_a] self.ram_write(valueFromRegister, self.reg[SP]) self.pc += 2 elif instruction == POP: # save the value on top of the stack onto the register given topmostValue = self.ram_read(self.reg[SP]) self.reg[operand_a] = topmostValue # increment the stack pointer self.reg[SP] += 1 self.pc += 2 else: print("Idk this instruction. Exiting") sys.exit(1) ```