def run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a, err = state.getReg(arg2) if isinstance(arg3, str): if err is None: b, err = state.getReg(arg3) else: b, _ = state.getReg(arg3) if b > 32: return state, programState.RunError(f"Shift value is out of range: value must be below 33 but is {b}", programState.RunError.ErrorType.Error) else: b = arg3 out = a >> b out32 = out & 0xFFFF_FFFF if ((a >> 31) & 1) == 1: # sign-extend out32 |= (0xFFFF_FFFF << (32 - b)) & 0xFFFF_FFFF if b == 0: c = state.status.C # The C flag is unaffected if the shift value is 0 - ARM docs else: c = bool((a >> (b-1)) & 1) # Get last bit shifted out n = bool((out32 >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, c, False)) return state, err
def branchToLabel(state: programState.ProgramState, label: str) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # Save return address in LR state.setReg("LR", state.getReg("PC")) address: Union[int, programState.RunError] = state.getLabelAddress(label) if isinstance(address, programState.RunError): return state, programState.RunError(f"Unknown startup label: {label}", programState.RunError.ErrorType.Error) else: # Subtract 4 because we will add 4 to the address later in the run loop and we need to start at address and not address+4 state.setReg("PC", address - 4) state.hasReturned = False return state, None
def pop(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if len(regs) == 0: return state, None # head, *tail = registers address = state.getReg("SP") # check address is in 0...stacksize if address > (state.getLabelAddress("__STACKSIZE")) or address < 0: return state, programState.RunError("All stack entries have been pop'ed already", programState.RunError.ErrorType.Error) for reg in regs: err = state.loadRegister(address, 32, False, reg) address += 4 if err is not None: return state, err state.setReg("SP", address) return state, None
def push(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if len(regs) == 0: return state, None # head, *tail = registers address = state.getReg("SP") # check address is in 0...stacksize if address > (state.getLabelAddress("__STACKSIZE")) or address < 0: return state, programState.RunError("Stack overflow", programState.RunError.ErrorType.Error) for reg in regs: address -= 4 err = state.storeRegister(address, reg, 32) if err is not None: return state, err state.setReg("SP", address) return state, None
def run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a = state.getReg(arg2) if isinstance(arg3, str): b = state.getReg(arg3) if b > 31: return state, programState.RunError(f"Shift value is out of range: value must be below 32 but is {b}", programState.RunError.ErrorType.Error) else: b = arg3 out = a << b out32 = out & 0xFFFF_FFFF if b == 0: c = state.status.C # The C flag is unaffected if the shift value is 0 - ARM docs else: c = bool((out >> 32) & 1) # Get the last bit shifted out n = bool((out32 >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, c, False)) return state, None