예제 #1
0
 def __init__(self, instruction, value=None):
     self.type = OperandType.UNKNOWN
     self.operand_string = ""
     self.instruction = instruction
     self.requires_resolution = False
     self.value = value if value else NoneValue(None)
     self.left = NoneValue(None)
     self.right = NoneValue(None)
     self.operation = ""
예제 #2
0
 def __init__(self,
              op_code=NoneValue(),
              address=NoneValue(),
              post_byte=NoneValue(),
              additional=NoneValue(),
              size=0):
     self.op_code = op_code
     self.address = address
     self.post_byte = post_byte
     self.additional = additional
     self.size = size
예제 #3
0
 def translate(self):
     return CodePackage(
         op_code=NumericValue(self.instruction.mode.rel),
         additional=self.value if self.value.is_address() else NoneValue(),
         size=self.instruction.mode.rel_sz,
         max_size=self.instruction.mode.rel_sz,
     )
예제 #4
0
 def __init__(self, width=100):
     self.symbol_table = dict()
     self.statements = []
     self.address = 0x0
     self.origin = NoneValue()
     self.name = None
     self.width = width
예제 #5
0
 def __init__(
     self,
     op_code=NoneValue(),
     address=NoneValue(),
     post_byte=NoneValue(),
     additional=NoneValue(),
     size=0,
     additional_needs_resolution=False,
     post_byte_choices=None,
     max_size=0,
 ):
     post_byte_choices = [] if post_byte_choices is None else post_byte_choices
     self.op_code = op_code
     self.address = address
     self.post_byte = post_byte
     self.additional = additional
     self.size = size
     self.additional_needs_resolution = additional_needs_resolution
     self.post_byte_choices = post_byte_choices
     self.max_size = max_size
예제 #6
0
 def __init__(self, operand_string, instruction, value=None):
     super().__init__(instruction)
     self.type = OperandType.EXPRESSION
     self.operand_string = operand_string
     match = EXPRESSION_REGEX.match(operand_string)
     if not match:
         raise ValueError(
             "[{}] is not a valid expression".format(operand_string))
     self.left = Value.create_from_str(match.group("left"), instruction)
     self.right = Value.create_from_str(match.group("right"), instruction)
     self.operation = match.group("operation")
     self.value = NoneValue("")
예제 #7
0
 def __init__(self, operand_string, instruction):
     super().__init__(instruction)
     self.operand_string = operand_string
     self.type = OperandType.PSEUDO
     if not instruction.is_pseudo:
         raise OperandTypeError("[{}] is not a pseudo instruction".format(instruction.mnemonic))
     self.value = NoneValue() if instruction.is_include else Value.create_from_str(operand_string, instruction)
     if instruction.is_pseudo_define:
         if self.operand_string.startswith("$") and len(self.operand_string) > 3:
             self.value = ExtendedNumericValue(self.value.int)
         elif self.value.hex_len() == 2:
             self.value = DirectNumericValue(self.value.int)
예제 #8
0
 def __init__(self, operand_string, instruction, value=None):
     super().__init__(instruction)
     self.operand_string = operand_string
     if value:
         self.value = value
         return
     if UNKNOWN_REGEX.search(operand_string):
         raise ValueError("[{}] invalid operand".format(operand_string))
     try:
         self.value = Value.create_from_str(operand_string, instruction)
     except ValueError:
         self.value = NoneValue()
예제 #9
0
 def test_none_byte_len_works_correctly(self):
     result = NoneValue('"abc"')
     self.assertEqual(0, result.byte_len())
예제 #10
0
    def translate(self):
        if not self.instruction.mode.ind:
            raise ValueError(
                "Instruction [{}] does not support indexed addressing".format(
                    self.instruction.mnemonic))
        raw_post_byte = 0x00
        size = self.instruction.mode.ind_sz
        additional = NoneValue()

        # Determine register (if any)
        if "X" in self.right:
            raw_post_byte |= 0x00
        if "Y" in self.right:
            raw_post_byte |= 0x20
        if "U" in self.right:
            raw_post_byte |= 0x40
        if "S" in self.right:
            raw_post_byte |= 0x60

        if self.left == "":
            raw_post_byte |= 0x80
            if "-" in self.right or "+" in self.right:
                if "+" in self.right:
                    raw_post_byte |= 0x00
                if "++" in self.right:
                    raw_post_byte |= 0x01
                if "-" in self.right:
                    raw_post_byte |= 0x02
                if "--" in self.right:
                    raw_post_byte |= 0x03
            else:
                raw_post_byte |= 0x04

        elif self.left == "A" or self.left == "B" or self.left == "D":
            raw_post_byte |= 0x80
            if self.left == "A":
                raw_post_byte |= 0x06
            if self.left == "B":
                raw_post_byte |= 0x05
            if self.left == "D":
                raw_post_byte |= 0x0B

        else:
            if "+" in self.right or "-" in self.right:
                raise ValueError("[{}] invalid indexed expression".format(
                    self.operand_string))
            if type(self.left) == str:
                self.left = NumericValue(self.left)
            if self.left.is_type(ValueType.ADDRESS):
                raise ValueError(
                    "[{}] cannot translate address in left hand side".format(
                        self.operand_string))
            numeric = self.left
            if numeric.byte_len() == 2:
                size += 2
                if "PC" in self.right:
                    raw_post_byte |= 0x8D
                    additional = numeric
                else:
                    raw_post_byte |= 0x89
                    additional = numeric
            elif numeric.byte_len() == 1:
                if "PC" in self.right:
                    raw_post_byte |= 0x8C
                    additional = numeric
                    size += 1
                else:
                    if numeric.int <= 0x1F:
                        raw_post_byte |= numeric.int
                    else:
                        raw_post_byte |= 0x88
                        additional = numeric
                        size += 1

        return CodePackage(op_code=NumericValue(self.instruction.mode.ind),
                           post_byte=NumericValue(raw_post_byte),
                           additional=additional,
                           size=size)
예제 #11
0
    def translate(self):
        if not self.instruction.mode.ind:
            raise OperandTypeError(
                "Instruction [{}] does not support indexed addressing".format(self.instruction.mnemonic)
            )
        size = self.instruction.mode.ind_sz

        if not type(self.value) == str and self.value.is_address():
            size += 2
            return CodePackage(
                op_code=NumericValue(self.instruction.mode.ind),
                post_byte=NumericValue(0x9F),
                additional=self.value,
                size=size,
                max_size=size,
            )

        if not type(self.value) == str and self.value.is_numeric():
            size += 2
            return CodePackage(
                op_code=NumericValue(self.instruction.mode.ind),
                post_byte=NumericValue(0x9F),
                additional=self.value,
                size=size,
                max_size=size,
            )

        raw_post_byte = 0x80
        post_byte_choices = []
        size = self.instruction.mode.ind_sz
        max_size = size
        additional = NoneValue()
        additional_needs_resolution = False

        if "X" in self.right:
            raw_post_byte |= 0x00
        if "Y" in self.right:
            raw_post_byte |= 0x20
        if "U" in self.right:
            raw_post_byte |= 0x40
        if "S" in self.right:
            raw_post_byte |= 0x60

        if self.left == "":
            if "-" in self.right or "+" in self.right:
                if self.right == "X+" or self.right == "Y+" or self.right == "U+" or self.right == "S+":
                    raise OperandTypeError("[{}] not allowed as an extended indirect value".format(self.right))
                if self.right == "-X" or self.right == "-Y" or self.right == "-U" or self.right == "-S":
                    raise OperandTypeError("[{}] not allowed as an extended indirect value".format(self.right))
                if "++" in self.right:
                    raw_post_byte |= 0x11
                if "--" in self.right:
                    raw_post_byte |= 0x13
            else:
                raw_post_byte |= 0x14

        elif self.left == "A" or self.left == "B" or self.left == "D":
            if self.left == "A":
                raw_post_byte |= 0x16
            if self.left == "B":
                raw_post_byte |= 0x15
            if self.left == "D":
                raw_post_byte |= 0x1B

        else:
            if "+" in self.right or "-" in self.right:
                raise OperandTypeError("[{}] invalid indexed expression".format(self.operand_string))
            if type(self.left) == str:
                self.left = Value.create_from_str(self.left)

            if self.left.is_address():
                additional_needs_resolution = True
                self.left = NumericValue(self.left.int)

            if self.left.is_expression():
                additional_needs_resolution = True

            if self.left.is_address_expression():
                additional_needs_resolution = True

            additional = self.left

            if "PCR" in self.right:
                if additional_needs_resolution:
                    raw_post_byte |= 0x00
                    post_byte_choices = [0x9C, 0x9D]
                    max_size += 2
                else:
                    size += 2 if self.left.is_extended() else 1
                    max_size = size
                    raw_post_byte |= 0x9D if self.left.is_extended() else 0x9C
            else:
                size += additional.byte_len()
                max_size = size
                raw_post_byte |= 0x99 if self.left.is_extended() else 0x98

        return CodePackage(
            op_code=NumericValue(self.instruction.mode.ind),
            post_byte=NumericValue(raw_post_byte),
            post_byte_choices=post_byte_choices,
            additional=additional,
            size=size,
            max_size=max_size,
            additional_needs_resolution=additional_needs_resolution,
        )
예제 #12
0
class Operand(ABC):
    def __init__(self, instruction, value=None):
        self.type = OperandType.UNKNOWN
        self.operand_string = ""
        self.instruction = instruction
        self.requires_resolution = False
        self.value = value if value else NoneValue(None)
        self.left = NoneValue(None)
        self.right = NoneValue(None)
        self.operation = ""

    @classmethod
    def create_from_str(cls, operand_string, instruction):
        try:
            return PseudoOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return SpecialOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return RelativeOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return InherentOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return ImmediateOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return DirectOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return ExtendedOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return ExtendedIndexedOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return IndexedOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return ExpressionOperand(operand_string, instruction)
        except ValueError:
            pass

        try:
            return UnknownOperand(operand_string, instruction)
        except ValueError:
            pass

        raise ValueError("[{}] unknown operand type".format(operand_string))

    def is_type(self, operand_type):
        """
        Returns True if the type of this operand class is the type being compared.

        :param operand_type: the OperandType to check
        :return: True if the OperandType values match, False otherwise
        """
        return self.type == operand_type

    def resolve_symbols(self, symbol_table):
        """
        Given a symbol table, searches the operands for any symbols, and resolves
        them with values from the symbol table. Returns a (possibly) new Operand
        class type as a result of symbol resolution.

        :param symbol_table: the symbol table to search
        :return: self, or a new Operand class type with a resolved value
        """
        if self.is_type(OperandType.EXPRESSION):
            return self.resolve_expression(symbol_table)

        if not self.value.is_type(ValueType.SYMBOL):
            return self

        symbol = self.get_symbol(self.value.ascii(), symbol_table)

        if symbol.is_type(ValueType.ADDRESS):
            self.value = AddressValue(symbol.int)
            if self.type == OperandType.UNKNOWN:
                return ExtendedOperand(self.operand_string,
                                       self.instruction,
                                       value=self.value)
            return self

        if symbol.is_type(ValueType.NUMERIC):
            self.value = copy(symbol)
            if self.value.hex_len() == 2:
                return DirectOperand(self.operand_string,
                                     self.instruction,
                                     value=self.value)
            return ExtendedOperand(self.operand_string,
                                   self.instruction,
                                   value=self.value)

    def resolve_expression(self, symbol_table):
        """
        Attempts to resolve the expression contained in the operand using the
        symbol table supplied. Returns a (possibly) new Operand class type as a
        result of symbol resolution.

        :param symbol_table: the symbol table to use for resolution
        :return: self, or a new Operand class type with a resolved value
        """
        if self.left.is_type(ValueType.SYMBOL):
            self.left = self.get_symbol(self.left.ascii(), symbol_table)

        if self.right.is_type(ValueType.SYMBOL):
            self.right = self.get_symbol(self.right.ascii(), symbol_table)

        if self.right.is_type(ValueType.NUMERIC) and self.left.is_type(
                ValueType.NUMERIC):
            left = self.left.int
            right = self.right.int
            if self.operation == "+":
                self.value = NumericValue("{}".format(left + right))
            if self.operation == "-":
                self.value = NumericValue("{}".format(left - right))
            if self.operation == "*":
                self.value = NumericValue("{}".format(int(left * right)))
            if self.operation == "/":
                self.value = NumericValue("{}".format(int(left / right)))
            if self.value.hex_len() == 2:
                return DirectOperand(self.operand_string,
                                     self.instruction,
                                     value=self.value)
            return ExtendedOperand(self.operand_string,
                                   self.instruction,
                                   value=self.value)

        raise ValueError("[{}] unresolved expression".format(
            self.operand_string))

    @staticmethod
    def get_symbol(symbol_label, symbol_table):
        if symbol_label not in symbol_table:
            raise ValueError("[{}] not in symbol table".format(symbol_label))
        return symbol_table[symbol_label]

    @abstractmethod
    def translate(self):
        """
예제 #13
0
    def translate(self):
        if not self.instruction.mode.ind:
            raise ValueError(
                "Instruction [{}] does not support indexed addressing".format(
                    self.instruction.mnemonic))
        size = self.instruction.mode.ind_sz

        if not type(self.value) == str and self.value.is_type(
                ValueType.ADDRESS):
            size += 2
            return CodePackage(op_code=NumericValue(self.instruction.mode.ind),
                               post_byte=NumericValue(0x9F),
                               additional=self.value,
                               size=size)

        if not type(self.value) == str and self.value.is_type(
                ValueType.NUMERIC):
            size += 2
            return CodePackage(op_code=NumericValue(self.instruction.mode.ind),
                               post_byte=NumericValue(0x9F),
                               additional=self.value,
                               size=size)

        raw_post_byte = 0x80
        additional = NoneValue()

        if "X" in self.right:
            raw_post_byte |= 0x00
        if "Y" in self.right:
            raw_post_byte |= 0x20
        if "U" in self.right:
            raw_post_byte |= 0x40
        if "S" in self.right:
            raw_post_byte |= 0x60

        if self.left == "":
            if "-" in self.right or "+" in self.right:
                if self.right == "X+" or self.right == "Y+" or self.right == "U+" or self.right == "S+":
                    raise ValueError(
                        "[{}] not allowed as an extended indirect value".
                        format(self.right))
                if self.right == "-X" or self.right == "-Y" or self.right == "-U" or self.right == "-S":
                    raise ValueError(
                        "[{}] not allowed as an extended indirect value".
                        format(self.right))
                if "++" in self.right:
                    raw_post_byte |= 0x11
                if "--" in self.right:
                    raw_post_byte |= 0x13
            else:
                raw_post_byte |= 0x14

        elif self.left == "A" or self.left == "B" or self.left == "D":
            if self.left == "A":
                raw_post_byte |= 0x16
            if self.left == "B":
                raw_post_byte |= 0x15
            if self.left == "D":
                raw_post_byte |= 0x1B

        else:
            if "+" in self.right or "-" in self.right:
                raise ValueError("[{}] invalid indexed expression".format(
                    self.operand_string))
            if type(self.left) == str:
                self.left = NumericValue(self.left)
            if self.left.is_type(ValueType.ADDRESS):
                raise ValueError(
                    "[{}] cannot translate address in left hand side".format(
                        self.operand_string))
            numeric = self.left
            if numeric.byte_len() == 2:
                size += 2
                if "PC" in self.right:
                    raw_post_byte |= 0x9D
                    additional = numeric
                else:
                    raw_post_byte |= 0x99
                    additional = numeric
            elif numeric.byte_len() == 1:
                size += 1
                if "PC" in self.right:
                    raw_post_byte |= 0x9C
                    additional = numeric
                else:
                    raw_post_byte |= 0x98
                    additional = numeric

        return CodePackage(op_code=NumericValue(self.instruction.mode.ind),
                           post_byte=NumericValue(raw_post_byte),
                           additional=additional,
                           size=size)
예제 #14
0
    def translate(self):
        if not self.instruction.mode.ind:
            raise OperandTypeError(
                "Instruction [{}] does not support indexed addressing".format(self.instruction.mnemonic)
            )
        raw_post_byte = 0x00
        post_byte_choices = []
        size = self.instruction.mode.ind_sz
        max_size = size
        additional = NoneValue()
        additional_needs_resolution = False

        # Determine register (if any)
        if "X" in self.right:
            raw_post_byte |= 0x00
        if "Y" in self.right:
            raw_post_byte |= 0x20
        if "U" in self.right:
            raw_post_byte |= 0x40
        if "S" in self.right:
            raw_post_byte |= 0x60

        if self.left == "":
            raw_post_byte |= 0x80
            if "-" in self.right or "+" in self.right:
                if "+" in self.right:
                    raw_post_byte |= 0x00
                if "++" in self.right:
                    raw_post_byte |= 0x01
                if "-" in self.right:
                    raw_post_byte |= 0x02
                if "--" in self.right:
                    raw_post_byte |= 0x03
            else:
                raw_post_byte |= 0x04

        elif self.left == "A" or self.left == "B" or self.left == "D":
            raw_post_byte |= 0x80
            if self.left == "A":
                raw_post_byte |= 0x06
            if self.left == "B":
                raw_post_byte |= 0x05
            if self.left == "D":
                raw_post_byte |= 0x0B

        else:
            if "+" in self.right or "-" in self.right:
                raise OperandTypeError("[{}] invalid indexed expression".format(self.operand_string))

            if self.left.is_address():
                additional_needs_resolution = True
                self.left = NumericValue(self.left.int)

            if self.left.is_expression():
                additional_needs_resolution = True

            if self.left.is_address_expression():
                additional_needs_resolution = True

            additional = self.left

            if "PCR" in self.right:
                if additional_needs_resolution:
                    raw_post_byte |= 0x00
                    post_byte_choices = [0x8C, 0x8D]
                    max_size += 2
                else:
                    size += 2 if self.left.is_extended() else 1
                    max_size = size
                    raw_post_byte |= 0x8D if self.left.is_extended() else 0x8C
            else:
                if additional.int <= 0x1F:
                    raw_post_byte |= additional.int
                else:
                    size += additional.byte_len()
                    max_size = size
                    raw_post_byte |= 0x89 if self.left.is_extended() else 0x88

        return CodePackage(
            op_code=NumericValue(self.instruction.mode.ind),
            post_byte=NumericValue(raw_post_byte),
            additional=additional,
            size=size,
            additional_needs_resolution=additional_needs_resolution,
            post_byte_choices=post_byte_choices,
            max_size=max_size,
        )
예제 #15
0
 def test_expression_raises_when_not_numeric_or_address_for_resolve(self):
     result = ExpressionValue("VAR+1")
     result.left = NoneValue()
     with self.assertRaises(ValueError) as context:
         result.resolve({})
     self.assertEqual("[VAR+1] unresolved expression", str(context.exception))
예제 #16
0
 def test_none_is_type_correct(self):
     result = NoneValue('"abc"')
     self.assertTrue(result.is_none())
예제 #17
0
 def test_none_str_works_correctly(self):
     result = NoneValue('"abc"')
     self.assertEqual("", str(result))
예제 #18
0
 def test_none_hex_works_correctly(self):
     result = NoneValue('"abc"')
     self.assertEqual("", result.hex())
예제 #19
0
 def test_none_ascii_works_correctly(self):
     result = NoneValue('"test string"')
     self.assertEqual("", result.ascii())
예제 #20
0
 def __init__(self):
     self.host_file = None
     self.load_addr = NoneValue()
     self.exec_addr = NoneValue()
     self.append_mode = False
     self.filename = None