from emulator import impl from emulator.operations import zero_extend32, sign_extend32 from decode import decode_instruction, decode_variables def delay_slot_state(cpu, ins): if instruction_properties.has_delay_slot(ins): assert cpu.is_delay_slot == False cpu.is_delay_slot = True else: cpu.is_delay_slot = False def step(cpu, mem): # 3 Fetch the instruction bytes from the address in memory, as # indicated by the current program counter, 2 bytes need to be # fetched for each instruction. address = zero_extend32(sign_extend32(cpu.pc)) assert address & 0b1 == 0, address instruction = mem.read16(address) # 4 Calculate the default values of PC’ and PR’. PC’ is set to the # value of PC”, PR’ is set to the value of PR”. cpu.pc1 = cpu.pc2 cpu.pr1 = cpu.pr2 # 5 Calculate the default values of PC” and PR” assuming continued # sequential execution without procedure call or mode switch: PC” # is PC’+2, while PR” is unchanged. cpu.pc2 = cpu.pc1 + 2 cpu.pr2 = cpu.pr2 # 6 Decode and execute the instruction. This includes checks for # synchronous events, such as exceptions and panics, and # initiation of handling if required. Synchronous events are not # accepted between a delayed branch and a delay slot. They are # detected either before the delayed branch or after the delay # slot. ins = decode_instruction(instruction) variables = decode_variables(instruction, ins) func = impl.lookup[(ins.instruction, ins.operands)] func(cpu, mem, *variables) delay_slot_state(cpu, ins) # 7 Set the current program counter (PC) to the value of the next # program counter (PC’) and PR to the value of PR’. cpu.pc = cpu.pc1 cpu.pr = cpu.pr1