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(arg1) if isinstance(arg2, str): if err is None: b, err = state.getReg(arg2) else: 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 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 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 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 ldrOneReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr, loadErr = state.getReg(src1.contents) err: Union[None, programState.RunError] = state.loadRegister( adr, bitSize, sign_extend, dest.contents) return state, loadErr if err is None else 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 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 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 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 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 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 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 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 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 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, 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 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 # 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 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 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, 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 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
def ldrRegImmed(state: programState.ProgramState) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: adr = state.getReg(src1.contents) err: Union[None, programState.RunError] = state.loadRegister(adr + value, bitSize, sign_extend, dest.contents) return state, err
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 generateStacktraceElement(state: programState.ProgramState, address: int, fileName: str, lines: List[str]) -> str: instr: nodes.InstructionNode = state.getInstructionFromMem(address) if isinstance(instr, nodes.SystemCall): return f"\tInternal function: {instr.name}" return f"\tFile \"{fileName}\", line {instr.line}:\n\t\t{lines[instr.line-1].strip()}"
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