def test_numeric_enumeration_operand(self): with pkg_resources.path(config_files, 'test_operand_features.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) lineid = LineIdentifier(33, 'test_numeric_enumeration_operand') t1 = InstructionLine.factory(lineid, 'num my_val+7', 'comment', isa_model) t1.set_start_address(1) t1.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t1, InstructionLine) self.assertEqual(t1.byte_size, 1, 'has 1 bytes') t1.generate_bytes() self.assertEqual(list(t1.get_bytes()), [0b10101000], 'instruction byte should match') t2 = InstructionLine.factory(lineid, 'sftl a, 1', 'comment', isa_model) t2.set_start_address(1) t2.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t2, InstructionLine) self.assertEqual(t2.byte_size, 1, 'has 1 bytes') t2.generate_bytes() self.assertEqual(list(t2.get_bytes()), [0b10001001], 'instruction byte should match') with self.assertRaises(SystemExit, msg='test invalid enumeration values'): e1 = InstructionLine.factory(lineid, 'num 7', 'number 7 is not allowed', isa_model) e1.label_scope = TestInstructionParsing.label_values e1.generate_bytes()
def test_deferred_operands(self): with pkg_resources.path(config_files, 'test_operand_features.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) lineid = LineIdentifier(13, 'test_deferred_operands') t1 = InstructionLine.factory(lineid, ' ld a, [[$F0]]', 'comment', isa_model) t1.set_start_address(1) t1.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t1, InstructionLine) self.assertEqual(t1.byte_size, 2, 'has 2 bytes') t1.generate_bytes() self.assertEqual(list(t1.get_bytes()), [0b00010101, 0xF0], 'instruction byte should match') t2 = InstructionLine.factory(lineid, ' ld [[my_val]],x', 'comment', isa_model) t2.set_start_address(1) t2.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t2, InstructionLine) self.assertEqual(t2.byte_size, 2, 'has 2 bytes') t2.generate_bytes() self.assertEqual(list(t2.get_bytes()), [0b10011101, 0x08], 'instruction byte should match')
def test_predefined_entities(self): with pkg_resources.path(config_files, 'test_compiler_features.yaml') as fp: model = AssemblerModel(str(fp), 0) self.assertSetEqual(set(model.predefined_labels), set(['CONST1', 'CONST2', 'buffer']), 'label set should equal')
def test_bad_registers_in_configuratin(self): with pkg_resources.path( config_files, 'test_bad_registers_in_configuratin.yaml') as fp: with self.assertRaises( SystemExit, msg= 'model configuration should not specify prohibited register names' ): model = AssemblerModel(str(fp), 0)
def test_label_parsing(self): with pkg_resources.path(config_files, 'test_instructions_with_variants.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) lineid = LineIdentifier(42, 'test_label_parsing') l1: LineObject = LineOjectFactory.parse_line(lineid, "LABEL = %00001111", isa_model)[0] self.assertIsInstance(l1, LabelLine) self.assertTrue(l1.is_constant, ) self.assertEqual(l1.get_value(), 0x0F, 'value should be right')
def test_indirect_indexed_regsiter_operands(self): with pkg_resources.path( config_files, 'test_indirect_indexed_register_operands.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) ins0 = InstructionLine.factory(22, 'mov a, [hl+i]', 'some comment!', isa_model) ins0.set_start_address(1212) self.assertIsInstance(ins0, InstructionLine) self.assertEqual(ins0.byte_size, 1, 'has 1 bytes') ins0.label_scope = TestInstructionParsing.label_values ins0.generate_bytes() self.assertEqual(list(ins0.get_bytes()), [0x81], 'instruction byte should match') ins1 = InstructionLine.factory(22, 'mov [$2000], [hl+i]', 'some comment!', isa_model) ins1.set_start_address(1212) self.assertIsInstance(ins1, InstructionLine) self.assertEqual(ins1.byte_size, 3, 'has 3 bytes') ins1.label_scope = TestInstructionParsing.label_values ins1.generate_bytes() self.assertEqual(list(ins1.get_bytes()), [0xB1, 0x00, 0x20], 'instruction byte should match') ins2 = InstructionLine.factory(22, 'mov [$2000], [hl+[sp+2]]', 'some comment!', isa_model) ins2.set_start_address(1212) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 4, 'has 4 bytes') ins2.label_scope = TestInstructionParsing.label_values ins2.generate_bytes() self.assertEqual(list(ins2.get_bytes()), [0xB3, 0x00, 0x20, 0x02], 'instruction byte should match') ins2 = InstructionLine.factory(22, 'mov [mar + $44], [$8020]', 'some comment!', isa_model) ins2.set_start_address(1212) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 4, 'has 4 bytes') ins2.label_scope = TestInstructionParsing.label_values ins2.generate_bytes() self.assertEqual(list(ins2.get_bytes()), [0xFE, 0x20, 0x80, 0x44], 'instruction byte should match, operands reversed') with self.assertRaises(SystemExit, msg='no instruction should match here'): bad1 = InstructionLine.factory(22, ' mov a, [sp+i]', 'some comment!', isa_model) bad1.set_start_address(666) bad1.label_scope = TestInstructionParsing.label_values bad1.generate_bytes()
def test_enumeration_operand(self): with pkg_resources.path(config_files, 'test_operand_features.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) lineid = LineIdentifier(21, 'test_enumeration_operand') t1 = InstructionLine.factory(lineid, ' tst bee', 'comment', isa_model) t1.set_start_address(1) t1.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t1, InstructionLine) self.assertEqual(t1.byte_size, 2, 'has 2 bytes') t1.generate_bytes() self.assertEqual(list(t1.get_bytes()), [0b00111001, 0xBB], 'instruction byte should match')
def __init__( self, config_file_path: str, is_verbose: int, export_dir: str, language_name: str, language_version: str, code_extension: str, ) -> None: self._model = AssemblerModel(config_file_path, is_verbose) self._verbose = is_verbose self._export_dir = export_dir self._language_name = self.model.isa_name if language_name is None else language_name self._language_version = self.model.isa_version if language_version is None else language_version self._extension = code_extension if code_extension is not None else self.model.assembly_file_extenions
def test_numeric_bytecode_operand(self): with pkg_resources.path(config_files, 'test_operand_features.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) lineid = LineIdentifier(33, 'test_numeric_bytecode_operand') t1 = InstructionLine.factory(lineid, ' tstb x, the_two+1', 'comment', isa_model) t1.set_start_address(1) t1.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t1, InstructionLine) self.assertEqual(t1.byte_size, 1, 'has 1 bytes') t1.generate_bytes() self.assertEqual(list(t1.get_bytes()), [0b10011011], 'instruction byte should match') t2 = InstructionLine.factory(lineid, ' tstb a, 7', 'comment', isa_model) t2.set_start_address(1) t2.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t2, InstructionLine) self.assertEqual(t2.byte_size, 1, 'has 1 bytes') t2.generate_bytes() self.assertEqual(list(t2.get_bytes()), [0b00011111], 'instruction byte should match') t3 = InstructionLine.factory(lineid, ' enumarg 6', 'comment', isa_model) t3.set_start_address(1) t3.label_scope = TestInstructionParsing.label_values self.assertIsInstance(t3, InstructionLine) self.assertEqual(t3.byte_size, 2, 'has 2 bytes') t3.generate_bytes() self.assertEqual(list(t3.get_bytes()), [254, 64], 'instruction byte should match') with self.assertRaises(SystemExit, msg='test bounds'): e1 = InstructionLine.factory(lineid, ' tstb b, 14', 'second argument is too large', isa_model) e1.label_scope = TestInstructionParsing.label_values e1.generate_bytes() with self.assertRaises(SystemExit, msg='test invalid enumerations'): e2 = InstructionLine.factory(lineid, ' enumarg 12', 'comment', isa_model) e2.label_scope = TestInstructionParsing.label_values e2.generate_bytes()
def test_bad_instruction_lines(self): with pkg_resources.path(config_files, 'register_argument_exmaple_config.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) label_values = GlobalLabelScope(isa_model.registers) # this instruction should fail because register A is not configured to be an # indirect register, so the parser assumes this is a indirect numeric expression # and then sees a register used there. with self.assertRaises(SystemExit, msg='this instruction should fail'): InstructionLine.factory(22, ' mov [a+2],5', 'move it', isa_model) # this instruction should fail because register i is being used in a numeric # expression with self.assertRaises(SystemExit, msg='this instruction should fail'): InstructionLine.factory(22, ' add i+5', 'add it', isa_model)
def test_specifc_configured_operands(self): with pkg_resources.path(config_files, 'register_argument_exmaple_config.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) label_values = GlobalLabelScope(isa_model.registers) label_values.set_label_value('test1', 0xABCD, 1) ins1 = InstructionLine.factory(22, 'mov i,[mar]', 'specific operands', isa_model) ins1.set_start_address(1234) self.assertIsInstance(ins1, InstructionLine) self.assertEqual(ins1.byte_size, 1, 'has 1 byte') ins1.label_scope = label_values ins1.generate_bytes() self.assertEqual(ins1.get_bytes(), bytearray([0x52]), 'instruction should match') ins2 = InstructionLine.factory(22, 'mov [sp+8],[mar]', 'specific operands', isa_model) ins2.set_start_address(1234) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 2, 'has 2 byte') ins2.label_scope = label_values ins2.generate_bytes() self.assertEqual(ins2.get_bytes(), bytearray([0x6D, 0x08]), 'instruction should match') # ensure operand sets operands still work when instruction has specific operands configured ins3 = InstructionLine.factory(22, 'mov a,[sp+8]', 'specific operands', isa_model) ins3.set_start_address(1234) self.assertIsInstance(ins3, InstructionLine) self.assertEqual(ins3.byte_size, 2, 'has 2 byte') ins3.label_scope = label_values ins3.generate_bytes() self.assertEqual(ins3.get_bytes(), bytearray([0x45, 0x08]), 'instruction should match')
def __init__( self, source_file: str, config_file: str, output_file: str, binary_start: int, binary_end: int, binary_fill_value: int, enable_pretty_print: bool, pretty_print_output: str, is_verbose: int, include_paths: list[str], ): self.source_file = source_file self._output_file = output_file self._config_file = config_file self._enable_pretty_print = enable_pretty_print self._pretty_print_output = pretty_print_output self._binary_fill_value = binary_fill_value & 0xff self._verbose = is_verbose self._binary_start = binary_start self._binary_end = binary_end self._model = AssemblerModel(self._config_file, self._verbose) self._include_paths = include_paths
def test_instruction_line_creation_little_endian(self): with pkg_resources.path( config_files, 'test_instruction_line_creation_little_endian.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) label_values = GlobalLabelScope(isa_model.registers) label_values.set_label_value('test1', 0xABCD, 1) ins1 = InstructionLine.factory(22, ' lda test1', 'some comment!', isa_model) ins1.set_start_address(1212) self.assertIsInstance(ins1, InstructionLine) self.assertEqual(ins1.byte_size, 3, 'has 3 byte') ins1.label_scope = label_values ins1.generate_bytes() self.assertEqual(ins1.get_bytes(), bytearray([0x10, 0xCD, 0xAB]), 'instruction should match') ins2 = InstructionLine.factory(22, 'set test1', 'set it!', isa_model) ins2.set_start_address(1212) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 3, 'has 3 byte') ins2.label_scope = label_values ins2.generate_bytes() self.assertEqual(ins2.get_bytes(), bytearray([0x30, 0xAB, 0xCD]), 'instruction should match') ins3 = InstructionLine.factory(22, 'big $f', 'big money', isa_model) ins3.set_start_address(1212) self.assertIsInstance(ins3, InstructionLine) self.assertEqual(ins3.byte_size, 2, 'has 2 byte') ins3.label_scope = label_values ins3.generate_bytes() self.assertEqual(ins3.get_bytes(), bytearray([0xFF, 0x3C]), 'instruction should match')
def test_instruction_line_creation(self): with pkg_resources.path( config_files, 'test_instruction_list_creation_isa.json') as fp: isa_model = AssemblerModel(str(fp), 0) label_values = GlobalLabelScope(isa_model.registers) label_values.set_label_value('test1', 0xA, 1) label_values.set_label_value('high_de', 0xde00, 1) ins1 = InstructionLine.factory(22, ' lda test1', 'some comment!', isa_model) ins1.set_start_address(1212) self.assertIsInstance(ins1, InstructionLine) self.assertEqual(ins1.byte_size, 1, 'has 1 byte') ins1.label_scope = label_values ins1.generate_bytes() self.assertEqual(ins1.get_bytes(), bytearray([0x1a]), 'instruction should match') ins2 = InstructionLine.factory(22, ' hlt', 'stop it!', isa_model) ins2.set_start_address(1212) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 1, 'has 1 byte') ins2.label_scope = label_values ins2.generate_bytes() self.assertEqual(ins2.get_bytes(), bytearray([0xF0]), 'instruction should match') ins3 = InstructionLine.factory(22, ' seta (high_de + $00AD)', 'is it alive?', isa_model) ins3.set_start_address(1313) self.assertIsInstance(ins3, InstructionLine) self.assertEqual(ins3.byte_size, 3, 'has 3 bytes') ins3.label_scope = label_values ins3.generate_bytes() self.assertEqual(ins3.get_bytes(), bytearray([0x30, 0xAD, 0xDE]), 'instruction should match') ins4 = InstructionLine.factory(22, ' lda test1+2', 'load it', isa_model) ins4.set_start_address(1313) self.assertIsInstance(ins4, InstructionLine) self.assertEqual(ins4.byte_size, 1, 'has 1 byte') ins4.label_scope = label_values ins4.generate_bytes() self.assertEqual(ins4.get_bytes(), bytearray([0x1c]), 'instruction should match') ins5 = InstructionLine.factory(22, ' plus 8', 'plus it', isa_model) ins5.set_start_address(888) self.assertIsInstance(ins5, InstructionLine) self.assertEqual(ins5.byte_size, 2, 'has 2 bytes') ins5.label_scope = label_values ins5.generate_bytes() self.assertEqual(ins5.get_bytes(), bytearray([0x40, 0x08]), 'instruction should match') ins6 = InstructionLine.factory(22, ' lda test1-2', 'load it', isa_model) ins6.set_start_address(888) self.assertIsInstance(ins6, InstructionLine) self.assertEqual(ins6.byte_size, 1, 'has 1 byte1') ins6.label_scope = label_values ins6.generate_bytes() self.assertEqual(ins6.get_bytes(), bytearray([0x18]), 'instruction should match')
def test_label_line_with_instruction(self): with pkg_resources.path(config_files, 'test_instructions_with_variants.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) label_values = GlobalLabelScope(isa_model.registers) label_values.set_label_value('a_const', 40, 1) lineid = LineIdentifier(123, 'test_label_line_with_instruction') # test data line on label line objs1: list[LineObject] = LineOjectFactory.parse_line( lineid, 'the_byte: .byte 0x88 ; label and instruction', isa_model) self.assertEqual(len(objs1), 2, 'there should be two instructions') self.assertIsInstance(objs1[0], LabelLine, 'the first line object should be a label') self.assertIsInstance(objs1[1], DataLine, 'the first line object should be a data line') self.assertEqual(objs1[0].get_label(), 'the_byte', 'the label string should match') objs1[1].label_scope = label_values objs1[1].generate_bytes() self.assertEqual(objs1[1].byte_size, 1, 'the data value should have 1 byte') self.assertEqual(list(objs1[1].get_bytes()), [0x88], 'the data value should be [0x88]') # test instruction on label line objs2: list[LineObject] = LineOjectFactory.parse_line( lineid, 'the_instr: mov a, a_const ; label and instruction', isa_model) self.assertEqual(len(objs2), 2, 'there should be two instructions') self.assertIsInstance(objs2[0], LabelLine, 'the first line object should be a label') self.assertIsInstance( objs2[1], InstructionLine, 'the first line object should be an Instruction line') self.assertEqual(objs2[0].get_label(), 'the_instr', 'the label string should match') objs2[1].label_scope = label_values objs2[1].generate_bytes() self.assertEqual(objs2[1].byte_size, 2, 'the instruction value should have 2 bytes') self.assertEqual(list(objs2[1].get_bytes()), [0b01000111, 40], 'the instruction bytes should match') # labels with no inline instruction should also work objs3: list[LineObject] = LineOjectFactory.parse_line( lineid, 'the_label: ;just a label', isa_model) self.assertEqual(len(objs3), 1, 'there should be two instructions') self.assertIsInstance(objs3[0], LabelLine, 'the first line object should be a label') self.assertEqual(objs3[0].get_label(), 'the_label', 'the label string should match') # labels with constants should not work with self.assertRaises(SystemExit, msg='this instruction should fail'): LineOjectFactory.parse_line( lineid, 'the_label: const = 3 ; label with constant', isa_model) # labels with other labels should not work with self.assertRaises(SystemExit, msg='this instruction should fail'): LineOjectFactory.parse_line( lineid, 'the_label: the_second_label: ; label with another label', isa_model)
def test_instruction_parsing(self): with pkg_resources.path(config_files, 'eater-sap1-isa.yaml') as fp: model1 = AssemblerModel(str(fp), 0) test_line_id = LineIdentifier(1212, 'test_instruction_parsing') pi1 = model1.parse_instruction(test_line_id, 'LDA $f') self.assertEqual(pi1.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(pi1.get_bytes(TestConfigObject.label_values), bytearray([0x1F]), 'assembled instruction') pi2 = model1.parse_instruction(test_line_id, 'add label1+5') self.assertEqual(pi2.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(pi2.get_bytes(TestConfigObject.label_values), bytearray([0x27]), 'assembled instruction') pi3 = model1.parse_instruction(test_line_id, 'out') self.assertEqual(pi3.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(pi3.get_bytes(TestConfigObject.label_values), bytearray([0xE0]), 'assembled instruction') with pkg_resources.path(config_files, 'register_argument_exmaple_config.yaml') as fp: model2 = AssemblerModel(str(fp), 0) piA = model2.parse_instruction(LineIdentifier(1, 'test_mov_a_i'), 'mov a, i') self.assertEqual(piA.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(list(piA.get_bytes(TestConfigObject.label_values)), [0b01000010], 'assembled instruction') piB = model2.parse_instruction(test_line_id, 'mov a,[$1120 + label1]') self.assertEqual(piB.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piB.get_bytes(TestConfigObject.label_values), bytearray([0b01000110, 0x22, 0x11]), 'assembled instruction') piC = model2.parse_instruction(test_line_id, 'add i') self.assertEqual(piC.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(piC.get_bytes(TestConfigObject.label_values), bytearray([0b10111010]), 'assembled instruction') piD = model2.parse_instruction( test_line_id, 'mov [$110D + (label1 + LABEL2)] , 0x88') self.assertEqual(piD.byte_size, 4, 'assembled instruciton is 4 byte') self.assertEqual(piD.get_bytes(TestConfigObject.label_values), bytearray([0b01110111, 0x88, 0xFF, 0x11]), 'arguments should be in reverse order') piE = model2.parse_instruction(test_line_id, 'mov [sp - label1] , 0x88') self.assertEqual(piE.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piE.get_bytes(TestConfigObject.label_values), bytearray([0b01101111, 0x88, 0b11111110]), 'arguments should be in reverse order') piF = model2.parse_instruction(test_line_id, 'mov [sp+label1] , 0x88') self.assertEqual(piF.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piF.get_bytes(TestConfigObject.label_values), bytearray([0b01101111, 0x88, 2]), 'arguments should be in reverse order') piG = model2.parse_instruction(test_line_id, 'mov [sp] , 0x88') self.assertEqual(piG.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piG.get_bytes(TestConfigObject.label_values), bytearray([0b01101111, 0x88, 0]), 'arguments should be in reverse order') piH = model2.parse_instruction(test_line_id, 'mov [$8000], [label1]') self.assertEqual(piH.byte_size, 5, 'assembled instruciton is 5 byte') self.assertEqual(piH.get_bytes(TestConfigObject.label_values), bytearray([0b01110110, 2, 0, 0, 0x80]), 'arguments should be in reverse order') piI = model2.parse_instruction(test_line_id, 'mov [mar], [label1]') self.assertEqual(piI.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piI.get_bytes(TestConfigObject.label_values), bytearray([0b01100110, 2, 0]), 'no offset should be emitted for [mar]') piJ = model2.parse_instruction(test_line_id, 'swap [$8000], [label1]') self.assertEqual(piJ.byte_size, 5, 'assembled instruciton is 3 byte') self.assertEqual(piJ.get_bytes(TestConfigObject.label_values), bytearray([0b11110110, 0, 0x80, 2, 0]), 'arguments should NOT be in reverse order') piK = model2.parse_instruction(test_line_id, 'mov [sp+2], [sp+4]') self.assertEqual(piK.byte_size, 3, 'assembled instruciton is 3 byte') self.assertEqual(piK.get_bytes(TestConfigObject.label_values), bytearray([0b01101101, 4, 2]), 'arguments should be in reverse order') piL = model2.parse_instruction(test_line_id, 'pop i') self.assertEqual(piL.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(list(piL.get_bytes(TestConfigObject.label_values)), [0b00001010], 'pop to i') piM = model2.parse_instruction( LineIdentifier(158, 'test_pop_empty_arg'), 'pop') self.assertEqual(piM.byte_size, 1, 'assembled instruciton is 1 byte') self.assertEqual(piM.get_bytes(TestConfigObject.label_values), bytearray([0b00001111]), 'just pop') piN = model2.parse_instruction(test_line_id, 'mov a, [sp+2]') self.assertEqual(piN.byte_size, 2, 'assembled instruciton is 2 byte') self.assertEqual(piN.get_bytes(TestConfigObject.label_values), bytearray([0b01000101, 2]), 'just move [sp+2] into a') with self.assertRaises( SystemExit, msg='should error on unallowed operand combinations'): model2.parse_instruction(test_line_id, 'mov a, a') with self.assertRaises(SystemExit, msg='[mar] should have no offset'): model2.parse_instruction(test_line_id, 'mov [mar+2], [label1]') with self.assertRaises(SystemExit, msg='should error due to too many operands'): model2.parse_instruction(test_line_id, 'mov a, i, j') with self.assertRaises(SystemExit, msg='should error due to too many operands'): model2.parse_instruction(test_line_id, 'nop 123') with self.assertRaises(SystemExit, msg='should error due to too few operands'): model2.parse_instruction(test_line_id, 'mov a')
def test_min_required_version(self): with pkg_resources.path(config_files, 'test_min_required_version_config.yaml') as fp: with self.assertRaises(SystemExit, msg='the min version check should fail'): model = AssemblerModel(str(fp), 0)
def test_instruction_variant_matching(self): with pkg_resources.path(config_files, 'test_instructions_with_variants.yaml') as fp: isa_model = AssemblerModel(str(fp), 0) # start simple ins1 = InstructionLine.factory(22, ' nop', 'some comment!', isa_model) ins1.set_start_address(1212) self.assertIsInstance(ins1, InstructionLine) self.assertEqual(ins1.byte_size, 1, 'has 1 byte') ins1.label_scope = TestInstructionParsing.label_values ins1.generate_bytes() self.assertEqual(ins1.get_bytes(), bytearray([0x00]), 'instruction should match') # match default variant operand sets ins2 = InstructionLine.factory(22, ' mov a, [sp+2]', 'some comment!', isa_model) ins2.set_start_address(1212) self.assertIsInstance(ins2, InstructionLine) self.assertEqual(ins2.byte_size, 2, 'has 2 byte') ins2.label_scope = TestInstructionParsing.label_values ins2.generate_bytes() self.assertEqual(ins2.get_bytes(), bytearray([0x44, 0x02]), 'instruction should match') # match default variant specific operand ins3 = InstructionLine.factory(22, ' mov a, [hl+6]', 'some comment!', isa_model) ins3.set_start_address(1212) self.assertIsInstance(ins3, InstructionLine) self.assertEqual(ins3.byte_size, 2, 'has 2 byte') ins3.label_scope = TestInstructionParsing.label_values ins3.generate_bytes() self.assertEqual(ins3.get_bytes(), bytearray([0x45, 0x06]), 'instruction should match') # match first variant ins4 = InstructionLine.factory(22, ' mov a, h', 'some comment!', isa_model) ins4.set_start_address(1212) self.assertIsInstance(ins4, InstructionLine) self.assertEqual(ins4.byte_size, 1, 'has 1 byte') ins4.label_scope = TestInstructionParsing.label_values ins4.generate_bytes() self.assertEqual(ins4.get_bytes(), bytearray([0x81]), 'instruction should match') # match second variant ins5 = InstructionLine.factory(22, ' mov h, $88', 'some comment!', isa_model) ins5.set_start_address(1212) self.assertIsInstance(ins5, InstructionLine) self.assertEqual(ins5.byte_size, 2, 'has 2 byte') ins5.label_scope = TestInstructionParsing.label_values ins5.generate_bytes() self.assertEqual(ins5.get_bytes(), bytearray([0x9F, 0x88]), 'instruction should match') # match no variant with self.assertRaises(SystemExit, msg='no instruction variant should match here'): InstructionLine.factory(22, ' mov h, l', 'some comment!', isa_model) with self.assertRaises(SystemExit, msg='no instruction variant should match here'): InstructionLine.factory(22, ' mov 27', 'some comment!', isa_model)