Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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
Пример #7
0
    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
Пример #8
0
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
Пример #9
0
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
Пример #10
0
 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
Пример #11
0
        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
Пример #12
0
 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
Пример #13
0
            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
Пример #14
0
    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
Пример #15
0
    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
Пример #16
0
 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
Пример #17
0
 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
Пример #18
0
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
Пример #19
0
 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
Пример #20
0
    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
Пример #21
0
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
Пример #22
0
    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
Пример #23
0
    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
Пример #24
0
    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
Пример #25
0
        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
Пример #26
0
    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
Пример #27
0
 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
Пример #28
0
 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