示例#1
0
    def SFSTOR(self, hardware=False):
        """
        This is a more complicated instruction. This instruction will compare the source value
        with the value located at the address contained in $A. If the resulting flags matches the
        source value is then copied at $A. Of importance, source register can't be $A.

        2 possibilities:
        SFSTOR <FLAGS> imm
        SFSTOR <FLAGS> reg
        :return: The flags are affected by this instruction and can be used to check if the value has been copied
        """
        sourceValue = 0
        destinationPointer = 0
        condition = self.ci.flags
        sfstorInstruction = self.ci

        # This will be saved back in the register at the end of the operation
        destinationPointer = self.eu.getRegisterValue(registerCode=REGISTER_A)

        if self.ci.sourceImmediate is None:
            sourceValue = self.eu.getRegisterValue(
                registerCode=self.ci.sourceRegister)
        else:
            sourceValue = self.ci.sourceImmediate

        # Now first step is to read the data
        widthAndDestination = 0b01000000  # width = 4, destination = reg A
        memrInstruction = Instruction(binaryInstruction=(0b00000001 << 8 * 5) |
                                      (widthAndDestination << 8 * 4)
                                      | destinationPointer,
                                      form=formDescription["InsWidthImmReg"])

        self.executeInstruction(memrInstruction)
        # Second step is to compare the data
        cmpInstruction = Instruction(binaryInstruction=(0b01101000 << 8 * 5) |
                                     (sourceValue << 8 * 1) | REGISTER_A,
                                     form=formDescription["InsImmReg"])
        # This will cause a modification of the live Flags register
        self.executeInstruction(cmpInstruction)

        # Need to make $A be the initial $A again
        self.eu.setRegisterValue(REGISTER_A, destinationPointer)

        # Flags after cmp instruction
        cmpFlags = self.eu.FLAGS

        # if this succeeds, we can move forward with the memory write
        # As strange as the next conditional looks, the second part is for
        # unconditional set detection.
        if ((condition & self.eu.FLAGS) > 0) or (condition == self.eu.FLAGS):
            memwInstruction = Instruction(
                binaryInstruction=(0b00000000 << 8 * 5) |
                (widthAndDestination << 8 * 4) | sourceValue,
                form=formDescription["InsWidthImmReg"])
            self.executeInstruction(memwInstruction)

        self.ci = sfstorInstruction
        # Need to return the current FLAGS as these would be overwritten upon return of this method.
        return cmpFlags
示例#2
0
 def test_extractValueFromBinaryField(self):
     """
     Validates good working of the _extractValueFromBinaryField method for Instruction
     _extractValueFromBinaryField(self, mask, field)
     """
     ins = Instruction(0b10010000 << 8 * 1,
                       formDescription["InsRegReg"])
     self.assertEqual(0b10, ins._extractValueFromBinaryField(0b00011000, 0b11110111))
     self.assertEqual(0b10, ins._extractValueFromBinaryField(0b00000011, 0b11111110))
     self.assertEqual(0b00, ins._extractValueFromBinaryField(0b00000000, 0b11111110))
示例#3
0
 def test_extractValueFromBinaryField(self):
     """
     Validates good working of the _extractValueFromBinaryField method for Instruction
     _extractValueFromBinaryField(self, mask, field)
     """
     ins = Instruction(0b10010000 << 8 * 1, formDescription["InsRegReg"])
     self.assertEqual(
         0b10, ins._extractValueFromBinaryField(0b00011000, 0b11110111))
     self.assertEqual(
         0b10, ins._extractValueFromBinaryField(0b00000011, 0b11111110))
     self.assertEqual(
         0b00, ins._extractValueFromBinaryField(0b00000000, 0b11111110))
示例#4
0
    def INT(self, hardware=False):
        """
        This method is a bit more complex. If interrupt are deactivated, simply return. Otherwise
        the correct interrupt handler address needs to be fetched from the interrupt vector. Also
        the return address needs to be pushed on the stack. Interrupt handler number is given
        either in a register or as an immediate value.
        2 possibilities:
        INT sReg
        int sImm
        :param: bool, optional, hardware, This indicates if the interrupt has been hardware generated
        :return:
        """

        sourceValue = 0

        # Interrupts are deactivated by the execution unit when handling a hardware interrupt
        # Since the hardware interrupt reuse this code, a check needs to happen here in order
        # to allow interrupt execution if generated in hardware.
        if hardware or self.eu.IS != 0b0:
            intInstruction = self.ci

            if hardware:
                # If this is an hardware generated interrupt, we NEED to save the flags
                flags = self.eu.FLAGS
                pushInstruction = Instruction(
                    binaryInstruction=(0b10000001 << 8 * 4) | flags,
                    form=formDescription["InsImm"])
                self.executeInstruction(pushInstruction, hardware=True)

            # Bring the correct instruction!!!
            self.ci = intInstruction
            if self.ci.sourceImmediate is None:
                sourceValue = self.eu.getRegisterValue(self.ci.sourceRegister)
            else:
                sourceValue = self.ci.sourceImmediate
            # At this moment, sourceValue hold the vector number
            # we need sourceValue * 4 since the system uses 32 bits pointers
            sourceValue *= 4

            # Here, we read the vector data into source value
            sourceValue = self.eu.mioc.memoryReadAtAddressForLength(
                self.eu.IVR + sourceValue, 4)

            # Now int can be managed like a call
            callInstruction = Instruction(
                binaryInstruction=(0b10000010 << 8 * 4) | sourceValue,
                form=formDescription["InsImm"])

            self.executeInstruction(callInstruction, hardware=True)
            self.ci = intInstruction
        return 0
示例#5
0
    def _fetchInstructionAtAddressUsingForm(self, address=MEMORY_START_AT, form=None):
        """
        This will fetch the complete instruction information and build an instruction instance
        using the extracted data. The instruction instance is returned to calling method
        :param address: Address of the instruction that needs to be fetched
        :param form: The form of the instruction that requires fetching
        :return: An instance of the Instruction class
        """
        instruction = None

        # First, we get the memory bits that we need!
        memorySlice = self._memoryArray.extractMemory(address, form["length"])

        # Now, build a big number (as in real big) with the extracted memory
        binaryInstruction = 0
        for mc in memorySlice:
            binaryInstruction <<= 8
            binaryInstruction |= mc.executeValue()  # Using executeValue makes sure we have execute permission

        # binaryInstruction is now  a big number representing the instruction
        # Time to create the instruction using this big number!
        # Parsing of the details of the instruction will happen in the Instruction class
        instruction = Instruction(binaryInstruction, form)

        return instruction
示例#6
0
    def HIRET(self, hardware=False):
        """
        This instruction is used to return from a hardware interrupt. It will reactivate the interrupts
        on the core, restore the flags and will then return.
        :param hardware: bool, optional, hardware, This indicates if the instruction executed was hardware generated
        :return: 0, this method does not affect the flags register
        """
        currentInstruction = self.ci

        oldAValue = self.eu.A
        # First save the return address
        popInstruction = Instruction(binaryInstruction=(0b01110100 << 8)
                                     | REGISTER_A,
                                     form=formDescription["InsReg"])
        self.executeInstruction(popInstruction, hardware=True)
        returnAddress = self.eu.A
        self.executeInstruction(popInstruction, hardware=True)
        flagsToBeRestored = self.eu.A

        self.eu.A = oldAValue
        self.eu.I = returnAddress

        self.ci = currentInstruction

        # This absolutely needs to happen last since the core plays with registers. Would that happen
        # before, there would be a big risk for the core to be in an inconsistent state.
        self.eu.interruptSignalLock.acquire()
        self.eu.IS = 0b1
        self.eu.interruptSignalLock.release()

        # Flags are restored in the return value other wise it will be overwritten
        return flagsToBeRestored
示例#7
0
    def _parseCodeLine(self, line: list=None):
        """
        This will parse an extracted line of code and build an instruction from that code line
        Parsing a line of code requires many steps.

            1- Find the possible codes for the mnemonic from OperationDescription
            2- Based on the possible codes and parts of the lines, find the correct form
            3- Based on the form, build the instruction
            4- Return the instruction
                If the instruction returned has a string as instruction mnemonic, this means that the
                instruction simply represent a label in the code. It will be removed from the final
                program.

        :param line:
        :return:
        """
        lineInstruction = None

        buildInstruction = Instruction(skipValidation=True)  # This is used as model in early instruction building
        finalCode = 0x00
        form = None
        possibleCodes = None

        self._evaluateAndExtractInfoFromLine(line, buildInstruction)

        if type(buildInstruction.instructionCode) is not str:
            # Instruction is real not just memory address or comment
            possibleCodes = self._findPossibleCodesForInstruction(buildInstruction)
            instructionCode, instructionForm = self._getInstructionCodeAndFormUsingPossibleCodes(buildInstruction,
                                                                                                 possibleCodes)
            if instructionForm is None or instructionCode is None:
                raise ValueError("Assembler general error")
            else:
                buildInstruction.instructionCode = instructionCode
                buildInstruction.instructionLength = formDescription[instructionForm]["length"]
                lineInstruction = self._generateBinaryInstructionFromInstruction(buildInstruction,
                                                                                 formDescription[instructionForm])
        else:
            if COMMENT_INDICATORS in buildInstruction.instructionCode:
                # Simply ignore a comment line
                buildInstruction = None
                lineInstruction = None
            elif DATA_ALPHA_INDICATOR in buildInstruction.instructionCode:
                # This is a bunch of alpha data
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0  # Calling code expect this to be non STR for non mem ref
            elif DATA_NUMERIC_INDICATOR in buildInstruction.instructionCode:
                # This is a numeric data field
                lineInstruction = struct.pack(">I", buildInstruction.sourceImmediate)
                buildInstruction.instructionCode = 0  # Calling code expect this to be non STR for non mem ref
            elif DATA_MEMORY_REFERENCE in buildInstruction.instructionCode:
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0
            else:
                lineInstruction = None

        return buildInstruction, lineInstruction
示例#8
0
    def _parseCodeLine(self, line: list=None):
        """
        This will parse an extracted line of code and build an instruction from that code line
        Parsing a line of code requires many steps.

            1- Find the possible codes for the mnemonic from OperationDescription
            2- Based on the possible codes and parts of the lines, find the correct form
            3- Based on the form, build the instruction
            4- Return the instruction
                If the instruction returned has a string as instruction mnemonic, this means that the
                instruction simply represent a label in the code. It will be removed from the final
                program.

        :param line:
        :return:
        """
        lineInstruction = None

        buildInstruction = Instruction(skipValidation=True)  # This is used as model in early instruction building
        finalCode = 0x00
        form = None
        possibleCodes = None

        self._evaluateAndExtractInfoFromLine(line, buildInstruction)

        if type(buildInstruction.instructionCode) is not str:
            # Instruction is real not just memory address or comment
            possibleCodes = self._findPossibleCodesForInstruction(buildInstruction)
            instructionCode, instructionForm = self._getInstructionCodeAndFormUsingPossibleCodes(buildInstruction,
                                                                                                 possibleCodes)
            if instructionForm is None or instructionCode is None:
                raise ValueError("Assembler general error")
            else:
                buildInstruction.instructionCode = instructionCode
                buildInstruction.instructionLength = formDescription[instructionForm]["length"]
                lineInstruction = self._generateBinaryInstructionFromInstruction(buildInstruction,
                                                                                 formDescription[instructionForm])
        else:
            if COMMENT_INDICATORS in buildInstruction.instructionCode:
                # Simply ignore a comment line
                buildInstruction = None
                lineInstruction = None
            elif DATA_ALPHA_INDICATOR in buildInstruction.instructionCode:
                # This is a bunch of alpha data
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0  # Calling code expect this to be non STR for non mem ref
            elif DATA_NUMERIC_INDICATOR in buildInstruction.instructionCode:
                # This is a numeric data field
                lineInstruction = struct.pack(">I", buildInstruction.sourceImmediate)
                buildInstruction.instructionCode = 0  # Calling code expect this to be non STR for non mem ref
            elif DATA_MEMORY_REFERENCE in buildInstruction.instructionCode:
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0
            else:
                lineInstruction = None

        return buildInstruction, lineInstruction
示例#9
0
    def _handleHardwareInterrupt(self):
        """
        This will handle an hardwareInterrupt. It will deactivate the interrupts on a given core and
        attempt at jumping into the code handling the latest successfully signaled interrupt.
        :return: Nothing
        """

        self.interruptSignalLock.acquire()

        self.IS = 0  # Interrupts are now deactivated across the core

        intInstruction = Instruction(binaryInstruction=(0b10000011 << 8 * 4)
                                     | self._interruptSignal,
                                     form=formDescription["InsImm"])
        self.lu.executeInstruction(instruction=intInstruction, hardware=True)

        self._interruptSignal = None  # Interrupt has been handled, we need to reset this

        self.interruptSignalLock.release()
示例#10
0
    def _parseCodeLine(self, line: list=None, rawLine: str=None):
        """
        This will parse an extracted line of code and build an instruction from that code line
        Parsing a line of code requires many steps.

            1- Find the possible codes for the mnemonic from OperationDescription
            2- Based on the possible codes and parts of the lines, find the correct form
            3- Based on the form, build the instruction
            4- Return the instruction
                If the instruction returned has a string as instruction mnemonic, this means that the
                instruction simply represent a label in the code. It will be removed from the final
                program.

        :param line: line split into individual arguments
        :param rawLine: raw line as we originally read it from the file, used to preserve spaces in .dataAlpha fields
        :return: The instruction object with all info about arguments, and the line's binary instruction
        """

        lineInstruction = None
        buildInstruction = Instruction(skipValidation=True)  # This is used as a model in early instruction building
        finalCode = 0x00
        form = None
        possibleCodes = None

        # We evaluate the line and extract any bits of relevant info to build the appropriate instruction
        self._evaluateAndExtractInfoFromLine(line, buildInstruction, rawLine)

        if type(buildInstruction.instructionCode) is not str:
            # We assume it's an instruction (integer), since memory references or comments would be strings
            # Parser will verify all possible codes, and generate the appropriate instruction based on its form
            possibleCodes = self._findPossibleCodesForInstruction(buildInstruction)
            instructionCode, instructionForm = self._getInstructionCodeAndFormUsingPossibleCodes(buildInstruction,
                                                                                                 possibleCodes)
            if instructionForm is None or instructionCode is None:
                raise ValueError("Assembler general error")
            else:
                # Code is valid, fetch the instruction's form based on the arguments, then generate the instruction
                buildInstruction.instructionCode = instructionCode
                buildInstruction.instructionLength = formDescription[instructionForm]["length"]
                lineInstruction = self._generateBinaryInstructionFromInstruction(buildInstruction,
                                                                                 formDescription[instructionForm])
        else:
            # In this case, there were no instructions. Thus, we look at other possibilities
            if COMMENT_INDICATORS in buildInstruction.instructionCode:
                # Simply ignore a comment line
                buildInstruction = None
                lineInstruction = None

            #  In these next cases, we can treat them as "data" variables with no real instructions.
            #  We store the data as the instruction's source immediate value, and set instruction code to 0
            elif DATA_ALPHA_INDICATOR in buildInstruction.instructionCode:
                # This is a bunch of alpha data (String)
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0

            elif DATA_NUMERIC_INDICATOR in buildInstruction.instructionCode:
                # This is a numeric data field (Integer)
                lineInstruction = struct.pack(">I", buildInstruction.sourceImmediate)
                buildInstruction.instructionCode = 0

            elif DATA_MEMORY_REFERENCE in buildInstruction.instructionCode:
                # This is a data memory reference (dataMemref)
                lineInstruction = buildInstruction.sourceImmediate
                buildInstruction.instructionCode = 0

            else:
                # Having exhausted all options, we assume there was nothing else on this line.
                lineInstruction = None

        return buildInstruction, lineInstruction
示例#11
0
    def test_init(self):
        """
        Validates good working of the __init__ method for Instruction
        __init__(self, binaryInstruction=0b000000, form=None)
        """
        ins = Instruction(0b11111111, formDescription["Ins"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 1)
        self.assertEqual(ins.operationMnemonic, "NOP")

        ins = Instruction(0b01110000 << 8 * 1, formDescription["InsReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNotNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 2)
        self.assertEqual(ins.operationMnemonic, "NOT")

        ins = Instruction(0b10000000 << 8 * 4, formDescription["InsImm"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNotNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 5)
        self.assertEqual(ins.operationMnemonic, "SNT")

        ins = Instruction(0b01100000 << 8 * 5, formDescription["InsImmReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNotNone(ins.destinationRegister)
        self.assertIsNotNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 6)
        self.assertEqual(ins.operationMnemonic, "MOV")

        ins = Instruction(0b00000000 << 8 * 5,
                          formDescription["InsWidthImmReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNotNone(ins.destinationRegister)
        self.assertIsNotNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNotNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 6)
        self.assertEqual(ins.operationMnemonic, "MEMW")

        ins = Instruction(0b00010000 << 16 * 1,
                          formDescription["InsWidthRegReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNotNone(ins.sourceRegister)
        self.assertIsNotNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNotNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 3)
        self.assertEqual(ins.operationMnemonic, "MEMR")

        ins = Instruction(0b00100000 << 8 * 5,
                          formDescription["InsWidthRegImm"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNotNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNotNone(ins.destinationImmediate)
        self.assertIsNotNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 6)
        self.assertEqual(ins.operationMnemonic, "MEMW")

        ins = Instruction(0b00110000 << 8 * 9,
                          formDescription["InsWidthImmImm"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNotNone(ins.sourceImmediate)
        self.assertIsNotNone(ins.destinationImmediate)
        self.assertIsNotNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 10)
        self.assertEqual(ins.operationMnemonic, "MEMW")

        ins = Instruction(0b01000000 << 8 * 5, formDescription["InsFlagImm"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNotNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNotNone(ins.flags)
        self.assertEqual(ins.instructionLength, 6)
        self.assertEqual(ins.operationMnemonic, "JMPR")

        ins = Instruction(0b01010000 << 8 * 1, formDescription["InsFlagReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNotNone(ins.sourceRegister)
        self.assertIsNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNotNone(ins.flags)
        self.assertEqual(ins.instructionLength, 2)
        self.assertEqual(ins.operationMnemonic, "JMPR")

        ins = Instruction(0b10010000 << 8 * 1, formDescription["InsRegReg"])
        self.assertIsNotNone(ins.instructionCode)
        self.assertIsNotNone(ins.sourceRegister)
        self.assertIsNotNone(ins.destinationRegister)
        self.assertIsNone(ins.sourceImmediate)
        self.assertIsNone(ins.destinationImmediate)
        self.assertIsNone(ins.width)
        self.assertIsNone(ins.flags)
        self.assertEqual(ins.instructionLength, 2)
        self.assertEqual(ins.operationMnemonic, "XOR")

        self.assertIsNotNone(Instruction(skipValidation=True))