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 run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a = state.getReg(arg2) if isinstance(arg3, str): b = state.getReg(arg3) else: b = arg3 # subtract one more if carry is set if state.status.C: b += 1 minusB = ((~b)+1) & 0xFFFFFFFF out = a + minusB out32 = out & 0xFFFFFFFF bit31 = (out32 >> 31) & 1 signA = (a >> 31) & 1 signB = (minusB >> 31) & 1 v = signA == signB and signB != bit31 c = bool((out >> 32) & 1) n = bool((out >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, c, v)) return state, None
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) else: b = arg3 & 0XFFFFFFFF minusB = ((~b)+1) & 0xFFFFFFFF out = a + minusB out32 = out & 0xFFFFFFFF bit31 = (out32 >> 31) & 1 signA = (a >> 31) & 1 signB = (minusB >> 31) & 1 v = signA == signB and signB != bit31 c = bool((out >> 32) & 1) n = bool((out >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, c, v)) return state, err
def executeInstruction( node: nodes.InstructionNode, state: programState.ProgramState, fileName: str, lines: List[str]) -> Tuple[programState.ProgramState, bool]: if isinstance(node, nodes.InstructionNode): # Execute the instruction state, err = node.function(state) # Exception handling if err is not None: if isinstance(err, programState.RunError): if err.errorType == programState.RunError.ErrorType.Error: print(generateStacktrace(state, err, fileName, lines)) return state, False elif err.errorType == programState.RunError.ErrorType.Warning: if node not in warningNodes: print(generateStacktrace(state, err, fileName, lines)) warningNodes.append(node) elif isinstance(err, programState.StopProgram): return state, False # Set a flag in the ProgramState when a subroutine returned. This way the stacktrace generator knows to not print a stacktrace element for the link register pc, _ = state.getReg("PC") if pc == state.getReg("LR")[0]: state.hasReturned = True # increment the program counter state.setReg("PC", pc + 4) return state, True else: if isinstance(node, programState.RunError): print(generateStacktrace(state, node, fileName, lines)) return state, False
def movReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: value, err = state.getReg(src.contents) if halfWord: if signed: if (value & 0b1000_0000_0000_0000 ) == 0b1000_0000_0000_0000: value |= 0xFFFF_0000 # Set upper half-word when sign bit is set else: value &= 0xFFFF else: value &= 0xFFFF else: if signed: if (value & 0b1000_0000) == 0b1000_0000: value |= 0xFFFF_FF00 # Set upper three bytes when sign bit is set else: value &= 0xFF else: value &= 0xFF state.setReg(dest.contents, value) return state, err
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) else: b = arg3 & 0XFFFFFFFF # subtract one more if carry is set if state.status.C: b += 1 out = a + b out32 = out & 0xFFFFFFFF bit31 = (out32 >> 31) & 1 signA = (a >> 31) & 1 signB = (b >> 31) & 1 v = signA == signB and signB != bit31 c = bool((out >> 32) & 1) n = bool((out >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, c, v)) return state, err
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) else: b = arg3 & 0XFFFFFFFF bMod32 = b & 31 out = (a >> bMod32) | (a << (32 - bMod32)) 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((a >> (bMod32-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 subroutine_print_int(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # print char r0 = state.getReg("R0") print(int(r0), end='\n') # mov PC, LR lr = state.getReg("LR") state.setReg("PC", lr) return state, None
def movReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: value, err = state.getReg(src.contents) if invert: value = value ^ 0xFFFF_FFFF state.setReg(dest.contents, value) return state, err
def movImmed( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if invert: value = src.value ^ 0xFFFF_FFFF else: value = src.value state.setReg(dest.contents, value) return state, None
def ldrLabel( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: val: Union[int, programState.RunError] = state.getLabelAddress( label.label) if isinstance(val, programState.RunError): return state, val else: state.setReg(dest.contents, val) return state, None
def subroutine_print_int( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # print char r0, err = state.getReg("R0") print(int(r0), end='\n') # mov PC, LR lr, _ = state.getReg("LR") state.setReg("PC", lr) state.lowRegDirtyFlags = [True, True, True, True] 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 branchTo( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if link: # Save return address in LR state.setReg("LR", state.getReg("PC")[0]) address, err = state.getReg(label.contents) # 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, err
def run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a = state.getReg(arg2) b = state.getReg(arg3) out32 = (a * b) & 0xFFFFFFFF n = bool((out32 >> 31) & 1) z = out32 == 0 state.setReg(arg1, out32) state.setALUState(programState.StatusRegister(n, z, state.status.C, state.status.V)) return state, None
def branchTo( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: if condition(state.status): address: Union[int, programState.RunError] = state.getLabelAddress( label.contents) if isinstance(address, programState.RunError): return state, address 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) 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) else: b = arg3 & 0XFFFFFFFF out = a & (b ^ 0xFFFF_FFFF) # out = a & ! b n = bool((out >> 31) & 1) z = out == 0 state.setReg(arg1, out) state.setALUState(programState.StatusRegister(n, z, False, 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 branchTo( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: # Save return address in LR pc, _ = state.getReg("PC") state.setReg("LR", pc) address: Union[int, programState.RunError] = state.getLabelAddress( label.contents) if isinstance(address, programState.RunError): return state, address 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 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
def ldrImmed( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: state.setReg(dest.contents, value) return state, None