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, 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 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 generateStacktrace(state: programState.ProgramState, error: programState.RunError, fileName: str, lines: List[str]) -> str: # Get return addresses from the stack sp: int = state.getReg("SP") stackSize = state.getLabelAddress("__STACKSIZE") stack: List[nodes.Node] = state.memory[sp >> 2:stackSize >> 2] callbacks = list( map( lambda n: generateStacktraceElement(state, n.value, fileName, lines ), filter( lambda x: isinstance(x, nodes.DataNode) and x.source == "LR", stack))) # Generate the error res = f"\033[31m" # Red color res += "Traceback (most recent call first):\n" res += generateStacktraceElement(state, state.getReg("PC"), fileName, lines) + '\n' if not state.hasReturned: res += generateStacktraceElement(state, state.getReg("LR"), fileName, lines) + '\n' if len(callbacks) > 0: res += reduce(lambda a, b: a + "\n" + b, callbacks) + '\n' res += error.message + '\n' return res + f"\033[0m" # Normal color
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: print(generateStacktrace(state, err, fileName, lines)) 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"): 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 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 = 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 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 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 strDualReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr1, err = state.getReg(dest1.contents) if err is None: adr2, err = state.getReg(dest2.contents) else: adr2, _ = state.getReg(dest2.contents) newState: Union[ None, programState.RunError] = state.storeRegister( adr1 + adr2, src.contents, bitSize) return state, err if newState is None else newState
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 ldrDualReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr1, loadErr = state.getReg(src1.contents) if loadErr is None: adr2, loadErr = state.getReg(src2.contents) else: adr2, _ = state.getReg(src2.contents) err: Union[None, programState.RunError] = state.loadRegister( adr1 + adr2, bitSize, sign_extend, dest.contents) return state, loadErr if err is None else err
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 = state.getReg(arg1) if isinstance(arg2, str): b = state.getReg(arg2) else: b = arg2 & 0XFFFFFFFF 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 run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a, err = state.getReg(arg2) if err is None: b, err = state.getReg(arg3) else: 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, err
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 strRegImmed( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr, err = state.getReg(dest1.contents) newState: Union[ None, programState.RunError] = state.storeRegister( adr + value, src.contents, bitSize) return state, err if newState is None else newState
def runProgram(state: programState.ProgramState, fileName: str, lines: List[str]) -> programState.ProgramState: while True: state, res = executeInstruction( state.getInstructionFromMem(state.getReg("PC")), state, fileName, lines) if not res: break return state
def ldrRegImmed( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr, loadErr = state.getReg(src1.contents) err: Union[None, programState.RunError] = state.loadRegister( adr + value, bitSize, sign_extend, dest.contents) return state, loadErr if err is None else 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 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, 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 run(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: a = state.getReg(arg1) if isinstance(arg2, str): b = state.getReg(arg2) else: b = arg2 & 0XFFFFFFFF 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, 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 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 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 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 ldrDualReg(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: adr1 = state.getReg(src1.contents) adr2 = state.getReg(src2.contents) err: Union[None, programState.RunError] = state.loadRegister(adr1 + adr2, bitSize, sign_extend, dest.contents) return state, err
def strDualReg(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: adr1 = state.getReg(dest1.contents) adr2 = state.getReg(dest2.contents) newState: Union[None, programState.RunError] = state.storeRegister(adr1 + adr2, src.contents, bitSize) return state, newState