コード例 #1
0
def getRegisterList(tokenList: List[tokens.Token], instruction: str) -> Tuple[Union[List[str], nodes.ErrorNode], List[tokens.Token]]:
    if len(tokenList) == 0:
        return instructionsUtils.generateToFewTokensError(-1, instruction + " instruction"), []

    regs = []

    nextToken, *tokenList = tokenList
    if isinstance(nextToken, tokens.Separator) and nextToken.contents == "{":
        if len(tokenList) == 0:
            return instructionsUtils.generateToFewTokensError(nextToken.line, instruction + " instruction"), instructionsUtils.advanceToNewline(tokenList)
        nextToken, *tokenList = tokenList
        if isinstance(nextToken, tokens.Register):
            regs.append(nextToken.contents)
        else:
            return instructionsUtils.generateUnexpectedTokenError(nextToken.line, nextToken.contents, "a register"), instructionsUtils.advanceToNewline(tokenList)
    else:
        return instructionsUtils.generateUnexpectedTokenError(nextToken.line, nextToken.contents, "'{'"), instructionsUtils.advanceToNewline(tokenList)
    # add remaining registers
    while True:
        nextToken, *tokenList = tokenList
        if isinstance(nextToken, tokens.Separator) and nextToken.contents == ",":
            if len(tokenList) == 0:
                return instructionsUtils.generateToFewTokensError(nextToken.line, instruction + " instruction"), []
            nextToken, *tokenList = tokenList
            if isinstance(nextToken, tokens.Register):
                regs.append(nextToken.contents)
            else:
                return instructionsUtils.generateUnexpectedTokenError(nextToken.line, nextToken.contents, "a register"), instructionsUtils.advanceToNewline(tokenList)
        elif isinstance(nextToken, tokens.Separator) and nextToken.contents == "}":
            break
        else:
            return instructionsUtils.generateUnexpectedTokenError(nextToken.line, nextToken.contents, "',' or '}'"), instructionsUtils.advanceToNewline(tokenList)

    return sorted(list(set(regs))), tokenList
コード例 #2
0
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)
コード例 #3
0
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)
コード例 #4
0
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)
コード例 #5
0
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)
コード例 #6
0
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)
コード例 #7
0
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)
コード例 #8
0
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)
コード例 #9
0
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)
コード例 #10
0
def decodeALUInstruction(tokenList: List[tokens.Token], section: nodes.Node.Section,
                         nodeGen: Callable[[nodes.Node.Section, int, str, Union[int, str], Union[int, str, None]], nodes.Node],
                         instruction: str) -> Tuple[nodes.Node, List[tokens.Token]]:
    if len(tokenList) == 0:
        return instructionsUtils.generateToFewTokensError(-1, instruction + " instruction"), []
    arg1, *tokenList = tokenList
    if len(tokenList) < 2:
        return instructionsUtils.generateToFewTokensError(arg1.line, instruction + " instruction"), []
    seperator1, arg2, *tokenList = tokenList
    if len(tokenList) < 2:
        seperator2 = seperator1
        # arg3 does not exist
        arg3 = None
    else:
        seperator2, arg3, *tokenList = tokenList
    if not (isinstance(seperator1, tokens.Separator) and seperator1.contents == ","):
        # Wrong token, generate an error
        return instructionsUtils.generateUnexpectedTokenError(seperator1.line, seperator1.contents, "','"), instructionsUtils.advanceToNewline(tokenList)
    if not (isinstance(seperator2, tokens.Separator) and seperator2.contents == ","):
        if isinstance(seperator2, tokens.NewLine):
            tokenList = [seperator2, arg3] + tokenList
            # arg3 does not exist
            arg3 = None
        else:
            # Wrong token, generate an error
            return instructionsUtils.generateUnexpectedTokenError(seperator2.line, seperator2.contents, "',' or End of line"), instructionsUtils.advanceToNewline(tokenList)

    if not isinstance(arg1, tokens.Register):
        # Wrong token, generate an error
        return instructionsUtils.generateUnexpectedTokenError(arg1.line, arg1.contents, "a register"), instructionsUtils.advanceToNewline(tokenList)
    if arg3 is None:
        if isinstance(arg2, tokens.Register):
            return nodeGen(section, arg1.line, arg1.contents, arg2.contents, None), tokenList
        elif isinstance(arg2, tokens.ImmediateValue):
            return nodeGen(section, arg1.line, arg1.contents, arg2.value, None), tokenList
        else:
            # Wrong token, generate an error
            return instructionsUtils.generateUnexpectedTokenError(arg2.line, arg2.contents, "a register or an immediate value"), instructionsUtils.advanceToNewline(tokenList)
    else:
        if not isinstance(arg2, tokens.Register):
            # Wrong token, generate an error
            return instructionsUtils.generateUnexpectedTokenError(arg2.line, arg2.contents, "a register"), instructionsUtils.advanceToNewline(tokenList)
        if isinstance(arg3, tokens.Register):
            return nodeGen(section, arg1.line, arg1.contents, arg2.contents, arg3.contents), tokenList
        elif isinstance(arg3, tokens.ImmediateValue):
            return nodeGen(section, arg1.line, arg1.contents, arg2.contents, arg3.value), tokenList
        else:
            # Wrong token, generate an error
            return instructionsUtils.generateUnexpectedTokenError(arg3.line, arg3.contents, "a register or an immediate value"), instructionsUtils.advanceToNewline(tokenList)
コード例 #11
0
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)
コード例 #12
0
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)
コード例 #13
0
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)