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 = ""
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
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, )
def __init__(self, width=100): self.symbol_table = dict() self.statements = [] self.address = 0x0 self.origin = NoneValue() self.name = None self.width = width
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
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("")
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)
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()
def test_none_byte_len_works_correctly(self): result = NoneValue('"abc"') self.assertEqual(0, result.byte_len())
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)
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, )
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): """
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)
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, )
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))
def test_none_is_type_correct(self): result = NoneValue('"abc"') self.assertTrue(result.is_none())
def test_none_str_works_correctly(self): result = NoneValue('"abc"') self.assertEqual("", str(result))
def test_none_hex_works_correctly(self): result = NoneValue('"abc"') self.assertEqual("", result.hex())
def test_none_ascii_works_correctly(self): result = NoneValue('"test string"') self.assertEqual("", result.ascii())
def __init__(self): self.host_file = None self.load_addr = NoneValue() self.exec_addr = NoneValue() self.append_mode = False self.filename = None