def decodeMOV(tokenList: List[tokens.Token], section: nodes.Node.Section, invert: bool) -> Tuple[nodes.Node, List[tokens.Token]]: if len(tokenList) == 0: return generateToFewTokensError( -1, f"{'MOVN' if invert else 'MOV'} instruction"), [] dest, *tokenList = tokenList if len(tokenList) < 2: return generateToFewTokensError( dest.line, f"{'MOVN' if invert else 'MOV'} instruction"), [] if not isinstance(dest, tokens.Register): # Wrong token, generate an error return generateUnexpectedTokenError( dest.line, dest.contents, "a register"), advanceToNewline(tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == ",": src, *tokenList = tokenList if isinstance(src, tokens.Register): 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 return nodes.InstructionNode(section, dest.line, movReg), tokenList elif isinstance(src, tokens.ImmediateValue): # check 8 bits if src.value > 0xFF: return generateImmediateOutOfRangeError( src.line, src.value, 0xFF), tokenList 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 return nodes.InstructionNode(section, dest.line, movImmed), tokenList else: # Wrong token, generate an error return generateUnexpectedTokenError( src.line, src.contents, "a register or an immediate value"), advanceToNewline( tokenList) else: # Wrong token, generate an error return generateUnexpectedTokenError(separator.line, separator.contents, "','"), advanceToNewline(tokenList)
def decodePOP( tokenList: List[tokens.Token], section: nodes.Node.Section) -> Tuple[nodes.Node, List[tokens.Token]]: line = tokenList[0].line regs, tokenList = getRegisterList(tokenList, "POP") if isinstance(regs, nodes.ErrorNode): return regs, tokenList regs = list(reversed(regs)) 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 return nodes.InstructionNode(section, line, pop), tokenList
def decodePUSH( tokenList: List[tokens.Token], section: nodes.Node.Section) -> Tuple[nodes.Node, List[tokens.Token]]: line = tokenList[0].line regs, tokenList = getRegisterList(tokenList, "PUSH") if isinstance(regs, nodes.ErrorNode): return regs, tokenList 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 return nodes.InstructionNode(section, line, push), tokenList
def decodeTST(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is not None: return instructionsUtils.generateUnexpectedTokenError(line, (", " + arg3) if isinstance(arg3, str) else (', #' + str(arg3)), "End of line") if isinstance(arg2, int): arg2 = arg2 & 0XFFFFFFFF # check 8 bits if arg2 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg2, 0xFF) 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 n = bool((out >> 31) & 1) z = out == 0 # state.setReg(arg1, out) state.setALUState(programState.StatusRegister(n, z, False, False)) return state, None return nodes.InstructionNode(section, line, run)
def decodeROR(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: return instructionsUtils.generateUnexpectedTokenError(line, "End of line", "a register") 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 return nodes.InstructionNode(section, line, run)
def decodeBIC(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: # move arg2 to arg3 and copy arg1 to arg2 arg3 = arg2 arg2 = arg1 if isinstance(arg3, int): arg3 = arg3 & 0XFFFFFFFF if arg3 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0xFF) 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 return nodes.InstructionNode(section, line, run)
def decodeBLX(tokenList: List[tokens.Token], section: nodes.Node.Section, link: bool) -> Tuple[nodes.Node, List[tokens.Token]]: if len(tokenList) == 0: return generateToFewTokensError(-1, "BL instruction"), [] label, *tokenList = tokenList if isinstance(label, tokens.Register): 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 return nodes.InstructionNode(section, label.line, branchTo), tokenList else: # Wrong token, generate an error return generateUnexpectedTokenError( label.line, label.contents, "a label"), advanceToNewline(tokenList)
def decodeBranch( tokenList: List[tokens.Token], section: nodes.Node.Section, condition: Callable[[programState.StatusRegister], bool] ) -> Tuple[nodes.Node, List[tokens.Token]]: if len(tokenList) == 0: return generateToFewTokensError(-1, "Branch instruction"), [] label, *tokenList = tokenList if isinstance(label, tokens.Label): 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 return nodes.InstructionNode(section, label.line, branchTo), tokenList else: # Wrong token, generate an error return generateUnexpectedTokenError( label.line, label.contents, "a label"), advanceToNewline(tokenList)
def decodeCMN(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is not None: return instructionsUtils.generateUnexpectedTokenError(line, (", " + arg3) if isinstance(arg3, str) else (', #' + str(arg3)), "End of line") if isinstance(arg2, int): arg2 = arg2 & 0XFFFFFFFF # check 8 bits if arg2 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg2, 0xFF) 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 return nodes.InstructionNode(section, line, run)
def decodeLSR(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: return instructionsUtils.generateUnexpectedTokenError(line, "End of line", "a register") if isinstance(arg3, int): arg3 = arg3 & 0XFFFFFFFF if arg3 > 32: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 33) 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 > 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 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, None return nodes.InstructionNode(section, line, run)
def decodeADC(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: # move arg2 to arg3 and copy arg1 to arg2 arg3 = arg2 arg2 = arg1 if isinstance(arg3, int): arg3 = arg3 & 0XFFFFFFFF if arg1.upper() == arg2.upper(): if arg1.upper() == "SP": # check 7 bits if arg3 > 0b0111_1111: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0b0111_1111) else: # multiple by 4 arg3 *= 4 else: # check 8 bits if arg3 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0xFF) else: if arg2.upper() == "SP": # arg1 can't be SP when arg2 is because arg1.upper() == arg2.upper() returned False # check 8 bits if arg3 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0xFF) else: # multiple by 4 arg3 *= 4 # check 3 bits if arg3 > 0b0111: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0b0111) 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 # 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, None return nodes.InstructionNode(section, line, run)
def decodeSUB(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: # move arg2 to arg3 and copy arg1 to arg2 arg3 = arg2 arg2 = arg1 if isinstance(arg3, int): arg3 = arg3 & 0XFFFFFFFF if arg1.upper() == arg2.upper(): if arg1.upper() == "SP": # check 7 bits if arg3 > 0b0111_1111: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0b0111_1111) else: # multiple by 4 arg3 *= 4 else: # check 8 bits if arg3 > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0xFF) else: # check 3 bits if arg3 > 0b0111: return instructionsUtils.generateImmediateOutOfRangeError(line, arg3, 0b0111) 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 return nodes.InstructionNode(section, line, run)
def decodeMUL(section: nodes.Node.Section, line: int, arg1: str, arg2: Union[int, str], arg3: Union[int, str, None]) -> nodes.Node: if arg3 is None: return instructionsUtils.generateUnexpectedTokenError(line, "End of line", "a register") if isinstance(arg3, int): return instructionsUtils.generateUnexpectedTokenError(line, f'#{arg3}', "a register") 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 return nodes.InstructionNode(section, line, run)
def decodeSTR(tokenList: List[tokens.Token], section: nodes.Node.Section, bitSize: int) -> Tuple[nodes.Node, List[tokens.Token]]: if len(tokenList) == 0: return instructionsUtils.generateToFewTokensError( -1, "STR instruction"), [] src, *tokenList = tokenList if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( src.line, "STR instruction"), [] if not isinstance(src, tokens.Register): # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( src.line, src.contents, "a register or an immediate value" ), instructionsUtils.advanceToNewline(tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == ",": separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == "[": if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( src.line, "STR instruction"), [] dest1, *tokenList = tokenList if not isinstance(dest1, tokens.Register): # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( dest1.line, dest1.contents, "a register"), instructionsUtils.advanceToNewline( tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == "]": def strOneReg( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[ programState.RunError, None]]: adr, err = state.getReg(dest1.contents) newState: Union[ None, programState.RunError] = state.storeRegister( adr, src.contents, bitSize) return state, err if newState is None else newState return nodes.InstructionNode(section, src.line, strOneReg), tokenList elif isinstance(separator, tokens.Separator) and separator.contents == ",": if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( src.line, "STR instruction"), [] dest2, separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents != "]": return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "']'"), instructionsUtils.advanceToNewline(tokenList) if isinstance(dest2, tokens.Register): 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 return nodes.InstructionNode(section, src.line, strDualReg), tokenList elif isinstance(dest2, tokens.ImmediateValue): dest2: tokens.ImmediateValue = dest2 value: int = dest2.value # check bit length - 5 bits or 8 for full word relative to SP or PC dest1Text = dest1.contents.upper() if dest1Text == "SP" or dest1Text == "PC": if bitSize == 32: if value > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError( dest2.line, value, 0xFF), tokenList else: value = 4 + (value * 4) else: return nodes.ErrorNode( f"\033[31m" # red color f"File \"$fileName$\", line {dest2.line}\n" f"\tSyntax error: Cannot only store a full word relative to PC or LR" f"\033[0m\n"), tokenList else: if value > 0b0001_1111: return instructionsUtils.generateImmediateOutOfRangeError( dest2.line, value, 0b0111_1111), tokenList else: # multiple by 4 if bitSize == 32: value *= 4 elif bitSize == 16: value *= 2 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 return nodes.InstructionNode(section, src.line, strRegImmed), tokenList else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( dest2.line, dest2.contents, "a register or an immediate value" ), instructionsUtils.advanceToNewline(tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "']' or ','"), instructionsUtils.advanceToNewline( tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "'['"), instructionsUtils.advanceToNewline(tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "','"), instructionsUtils.advanceToNewline(tokenList)
def decodeLDR(tokenList: List[tokens.Token], section: nodes.Node.Section, bitSize: int, sign_extend: bool) -> Tuple[nodes.Node, List[tokens.Token]]: if len(tokenList) == 0: return instructionsUtils.generateToFewTokensError( -1, "LDR instruction"), [] dest, *tokenList = tokenList if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( dest.line, "LDR instruction"), [] if not isinstance(dest, tokens.Register): # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( dest.line, dest.contents, "a register or an immediate value" ), instructionsUtils.advanceToNewline(tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == ",": separator, *tokenList = tokenList if isinstance( separator, tokens.LoadImmediateValue ) and not sign_extend: # sign extend is not supported for this syntax value: int = separator.value & 0xFFFFFFFF def ldrImmed( state: programState.ProgramState ) -> Tuple[programState.ProgramState, Union[programState.RunError, None]]: state.setReg(dest.contents, value) return state, None return nodes.InstructionNode(section, dest.line, ldrImmed), tokenList elif isinstance( separator, tokens.LoadLabel ) and not sign_extend: # sign extend is not supported for this syntax label: tokens.LoadLabel = separator 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 return nodes.InstructionNode(section, dest.line, ldrLabel), tokenList elif isinstance(separator, tokens.Separator) and separator.contents == "[": if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( dest.line, "LDR instruction"), [] src1, *tokenList = tokenList if not isinstance(src1, tokens.Register): # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( src1.line, src1.contents, "a register"), instructionsUtils.advanceToNewline( tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == "]": 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 return nodes.InstructionNode(section, dest.line, ldrOneReg), tokenList elif isinstance(separator, tokens.Separator) and separator.contents == ",": if len(tokenList) < 2: return instructionsUtils.generateToFewTokensError( dest.line, "LDR instruction"), [] src2, separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents != "]": return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "']'"), instructionsUtils.advanceToNewline(tokenList) if isinstance(src2, tokens.Register): 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 return nodes.InstructionNode(section, dest.line, ldrDualReg), tokenList elif isinstance(src2, tokens.ImmediateValue): src2: tokens.ImmediateValue = src2 value: int = src2.value # check bit length - 5 bits or 8 for full word relative to SP or PC src1Text = src1.contents.upper() if src1Text == "SP" or src1Text == "PC": if bitSize == 32: if value > 0xFF: return instructionsUtils.generateImmediateOutOfRangeError( src2.line, value, 0xFF), tokenList else: value = 4 + (value * 4) else: return nodes.ErrorNode( f"\033[31m" # red color f"File \"$fileName$\", line {src2.line}\n" f"\tSyntax error: Cannot only load a full word relative to PC or LR" f"\033[0m\n"), tokenList else: if value > 0b0001_1111: return instructionsUtils.generateImmediateOutOfRangeError( src2.line, value, 0b0111_1111), tokenList else: # multiple by 4 if bitSize == 32: value *= 4 elif bitSize == 16: value *= 2 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 return nodes.InstructionNode(section, dest.line, ldrRegImmed), tokenList else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( src2.line, src2.contents, "a register or an immediate value" ), instructionsUtils.advanceToNewline(tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "']' or ','"), instructionsUtils.advanceToNewline( tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "'['"), instructionsUtils.advanceToNewline(tokenList) else: # Wrong token, generate an error return instructionsUtils.generateUnexpectedTokenError( separator.line, separator.contents, "','"), instructionsUtils.advanceToNewline(tokenList)
def decodeExtend(tokenList: List[tokens.Token], section: nodes.Node.Section, signed: bool, halfWord: bool) -> Tuple[nodes.Node, List[tokens.Token]]: if halfWord: if signed: instrName = "SXTH" else: instrName = "UXTH" else: if signed: instrName = "SXTB" else: instrName = "UXTB" if len(tokenList) == 0: return generateToFewTokensError(-1, f"{instrName} instruction"), [] dest, *tokenList = tokenList if len(tokenList) < 2: return generateToFewTokensError(dest.line, f"{instrName} instruction"), [] if not isinstance(dest, tokens.Register): # Wrong token, generate an error return generateUnexpectedTokenError( dest.line, dest.contents, "a register"), advanceToNewline(tokenList) separator, *tokenList = tokenList if isinstance(separator, tokens.Separator) and separator.contents == ",": src, *tokenList = tokenList if isinstance(src, tokens.Register): 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 return nodes.InstructionNode(section, dest.line, movReg), tokenList else: # Wrong token, generate an error return generateUnexpectedTokenError( src.line, src.contents, "a register"), advanceToNewline(tokenList) else: # Wrong token, generate an error return generateUnexpectedTokenError(separator.line, separator.contents, "','"), advanceToNewline(tokenList)