Ejemplo n.º 1
0
def test_using_auto_post_increment_with_register_non_index_register_raises_value_error(
):
    asm = AsmDsl()
    asm(LDA, {0: A + 1}, "GET SQUARE OF DATA")
    s = statements(asm)
    with raises(ValueError):
        assemble(s)
Ejemplo n.º 2
0
def test_using_indexed_addressing_offset_register_with_index_register_raises_value_error(
):
    asm = AsmDsl()
    asm(LDA, {Y: X}, "GET SQUARE OF DATA")
    s = statements(asm)
    with raises(ValueError):
        assemble(s)
Ejemplo n.º 3
0
def test_fcb_operand_integers_out_of_range_raises_value_error(items):
    asm = AsmDsl()
    asm(FCB, tuple(items))
    s = statements(asm)
    with raises(ValueError,
                match=r'Value -?\d+ at index \d+ not in range\(0, 256\)'):
        assemble(s)
Ejemplo n.º 4
0
def test_label_reuse_raises_runtime_error():
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET FIRST OPERAND")
    asm(CMPA, {0x41}, "IS SECOND OPERAND LARGER?")
    asm(BHS, asm.stres)
    asm(LDA, {0x41}, "YES,GET SECOND OPERAND")
    asm.stres(STA, {0x42}, "STORE LARGER OPERAND")
    asm.stres(SWI)
    s = statements(asm)
    with raises(RuntimeError):
        assemble(s)
Ejemplo n.º 5
0
def test_unreferenced_label_reports_error():
    asm = AsmDsl()
    asm.UNUSED(ADDB, {0x20}, "ADD 0x20 TO ACCUMULATOR B")

    logger = logging.getLogger('test-logger')
    logger.setLevel(logging.WARN)
    for handler in logger.handlers:
        logger.removeHandler(handler)
    handler = ListLogHandler()
    logger.addHandler(handler)
    assemble(statements(asm), logger=logger)
    assert handler.messages[0] == 'Unreferenced label: UNUSED'
Ejemplo n.º 6
0
def test_warning_log_is_empty_when_no_warnings_emitted():
    asm = AsmDsl()
    asm(ADDB, {0x20}, "ADD 0x20 TO ACCUMULATOR B")

    logger = logging.getLogger('test-logger')
    logger.setLevel(logging.WARN)
    for handler in logger.handlers:
        logger.removeHandler(handler)
    handler = ListLogHandler()
    logger.addHandler(handler)
    assemble(statements(asm), logger=logger)
    assert len(handler.messages) == 0
Ejemplo n.º 7
0
def test_origin_address_lies_within_existing_code_fragment():
    asm = AsmDsl()
    asm(LDB, {0x41}, "GET DATA")
    asm(LDX, asm.SQTAB, "GET BASE ADDRESS")
    asm(LDA, {B: X}, "GET SQUARE OF DATA")
    asm(STA, {0x42}, "STORE SQUARE")
    asm(SWI)
    asm(ORG, 0x03, "TABLE OF SQUARES")

    s = statements(asm)

    with raises(ValueError):
        assemble(s)
Ejemplo n.º 8
0
def test_label_reuse_raises_runtime_error_multiple_segments_created_in_reverse_address_order(
):
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET FIRST OPERAND")
    asm(CMPA, {0x41}, "IS SECOND OPERAND LARGER?")
    asm(BHS, asm.stres)
    asm(LDA, {0x41}, "YES,GET SECOND OPERAND")
    asm(ORG, 0x50)
    asm.stres(STA, {0x42}, "STORE LARGER OPERAND")
    asm(ORG, 0x30)
    asm.stres(SWI)
    s = statements(asm)
    with raises(RuntimeError):
        assemble(s)
Ejemplo n.º 9
0
def asm(source_filepath, output_file, output_format, repeat):
    """
    Args:
        source_filepath: A string path to the source file.

        output_file: A file-like object to which the output will be written.

        output_format: "bin", "hex" or "srec"

        repeat: The number of times binary data will be copied into
            the output file. Useful for 'doubling-up' binary images for
            putting, say, a 16 K image into a 32 K EPROM.

    Raises:
        FileNotFoundError: If the source_filepath could not be found.
        ModuleLoadError: If the module could not be loaded.
        TooManyPassesError: If too many assembly passes were required.
    """
    try:
        m = import_module_from_file(source_filepath)
    except Exception as e:
        raise ModuleLoadError(source_filepath, e)

    code_blocks = assemble(statements(m.asm))

    for address, code in code_blocks.items():
        hex_assembly = ' '.join(format(b, '02X') for b in code)
        logger.debug("{:04X}: {}".format(address, hex_assembly))
        logger.info("code length: {} bytes".format(len(code)))

    export_code_blocks(output_file, code_blocks, output_format, repeat)
Ejemplo n.º 10
0
def test_levethal_5_2__16_bit_sum_of_data_long_offset():
    asm = AsmDsl()
    asm(CLRA, "MSB'S OF SUM = ZERO")
    asm(CLRB, "LSB'S OF SUM = ZERO")
    asm(LDX, 0x43, "POINT TO START OF ARRAY")
    asm.SUMD(ADDB, {0: X + 1}, "SUM = SUM + DATA")
    asm(ADCA, 0, "     AND ADD IN CARRY")
    asm(
        DEC,
        {0x42},
    )
    asm(LBRA, asm.TEST)
    asm.TEST(LBNE, asm.SUMD)
    asm(STD, {0x40}, "SAVE SUM")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('4F'
                                    '5F'
                                    '8E 0043'
                                    'EB 80'
                                    '89 00'
                                    '0A 42'
                                    '16 0000'  # Check!
                                    '1026 FFF3'  # Check!
                                    'DD 40'
                                    '3F')
Ejemplo n.º 11
0
def test_leventhal_5_4__maximum_value():
    asm = AsmDsl()
    asm(LDB, {0x41}, "COUNT = NUMBER OF ELEMENTS")
    asm(CLRA, "MAX = (MINIMUM POSSIBLE)")
    asm(LDX, 0x42, "POINT TO FIRST ENTRY")
    asm.MAXM(CMPA, {0: X + 1}, "IS CURRENT ENTRY GREATER THAN MAX")
    asm(BHS, asm.NOCHG)
    asm(LDA, {-1: X}, "YES, REPLACE MAX WITH CURRENT ENTRY")
    asm.NOCHG(DECB, )
    asm(
        BNE,
        asm.MAXM,
    )
    asm(STA, {0x40}, "SAVE MAXIMUM")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('D6 41'
                                    '4F'
                                    '8E 0042'
                                    'A1 80'
                                    '24 02'
                                    'A6 1F'
                                    '5A'
                                    '26 F7'
                                    '97 40'
                                    '3F')
Ejemplo n.º 12
0
def test_leventhal_6_1a__length_of_a_string_of_characters():
    asm = AsmDsl()
    asm(CLRB, "STRING LENGTH = ZERO")
    asm(LDX, 0x41, "POINT TO START OF STRING")
    asm(LDA, 0x0D, "GET ASCII CARRIAGE RETURN " "(STRING TERMINATOR)")
    asm.CHKCR(CMPA, {0: X + 1}, "IS NEXT CHARACTER " "A CARRIAGE RETURN?")
    asm(BEQ, asm.DONE, "YES, END OF STRING")
    asm(INCB, "NO, ADD 1 TO STRING LENGTH")
    asm(
        BRA,
        asm.CHKCR,
    )
    asm.DONE(STB, {0x40}, "SAVE STRING LENGTH")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('5F'
                                    '8E 0041'
                                    '86 0D'
                                    'A1 80'
                                    '27 03'
                                    '5C'
                                    '20 F9'
                                    'D7 40'
                                    '3F')
Ejemplo n.º 13
0
def test_leventhal_4_5__clear_a_memory_location():
    asm = AsmDsl()
    asm(CLR, {0x40}, "CLEAR MEMORY LOCATION 0040")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('0F 40' '3F')
Ejemplo n.º 14
0
def test_index_with_accumulator_W_offset(index_register):
    asm = AsmDsl()
    asm(LDA, {W: index_register}, "ACCUMULATOR W OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6, 0b10001110 | INDEX_REGISTER_CODES[index_register]))
Ejemplo n.º 15
0
def test_index_with_zero_offset(index_register):
    asm = AsmDsl()
    asm(LDA, {0: index_register}, "ZERO OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6, 0b10000100 | INDEX_REGISTER_CODES[index_register]))
Ejemplo n.º 16
0
def test_index_with_eight_bit_offset(index_register, offset):
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "8-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6, 0b10001000 | INDEX_REGISTER_CODES[index_register],
         twos_complement(offset, 8)))
Ejemplo n.º 17
0
def test_leventhal_4_1__8_bit_data_transfer():
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET DATA")
    asm(STA, {0x41}, "TRANSFER to NEW LOCATION")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('96 40' '97 41' '3F')
Ejemplo n.º 18
0
def test_levethal_4_8__sixteen_bit_addition():
    asm = AsmDsl()
    asm(LDD, {0x40}, "GET FIRST 16-BIT NUMBER")
    asm(ADDD, {0x42}, "ADD SECOND 16-BIT NUMBER")
    asm(STD, {0x44}, "STORE 16-BIT RESULT")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('DC 40' 'D3 42' 'DD 44' '3F')
Ejemplo n.º 19
0
def test_leventhal_4_4__8_bit_addition():
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET DATA")
    asm(ANDA, 0b00001111, "MASK OUT FOR MSB'S")
    asm(STA, {0x41}, "STORE RESULT")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('96 40' '84 0F' '97 41' '3F')
Ejemplo n.º 20
0
def test_leventhal_4_2__8_bit_addition():
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET FIRST OPERAND")
    asm(ADDA, {0x41}, "ADD SECOND OPERAND")
    asm(STA, {0x42}, "STORE RESULT")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('96 40' '9B 41' '97 42' '3F')
Ejemplo n.º 21
0
def test_leventhal_4_3__shift_left_1_bit():
    asm = AsmDsl()
    asm(LDB, {0x40}, "GET DATA")
    asm(ASLB, "SHIFT LEFT")
    asm(STB, {0x41}, "STORE RESULT")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('D6 40' '58' 'D7 41' '3F')
Ejemplo n.º 22
0
def test_index_with_sixteen_bit_offset(offset, index_register):
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "16-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == (bytes(
        (0xA6, 0b10001001 | INDEX_REGISTER_CODES[index_register])) +
                       twos_complement(offset, 16).to_bytes(
                           length=2, byteorder='big', signed=False))
Ejemplo n.º 23
0
def test_index_with_five_bit_offset(index_register, offset):
    assume(offset != 0)
    asm = AsmDsl()
    asm(LDA, {offset: index_register}, "5-BIT OFFSET FROM INDEX REGISTER")

    code = assemble(statements(asm))
    assert code[0] == bytes(
        (0xA6,
         INDEX_REGISTER_CODES[index_register] | twos_complement(offset, 5)))
Ejemplo n.º 24
0
def test_levethal_4_10_ones_complement():
    asm = AsmDsl()
    asm(LDD, {0x40}, "GET 16-BIT NUMBER")
    asm(COMA, "ONES COMPLEMENT MSB'S")
    asm(COMB, "ONES COMPLEMENT LSB'S")
    asm(STD, {0x42}, "STORE 16-BIT ONES COMPLEMENT")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('DC 40' '43' '53' 'DD 42' '3F')
Ejemplo n.º 25
0
def test_levethal_4_9_modified__table_of_squares():
    asm = AsmDsl()
    asm(LDB, {0x41}, "GET DATA")
    asm(LDX, asm.SQTAB, "GET BASE ADDRESS")
    asm(LDA, {B: X}, "GET SQUARE OF DATA")
    asm(STA, {0x42}, "STORE SQUARE")
    asm(SWI)
    asm(ORG, 0x50, "TABLE OF SQUARES")
    asm.SQTAB(FCB, (0, 1, 4, 9, 16, 25, 36, 49))

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('D6 41' '8E 0050' 'A6 85' '97 42' '3F')

    assert code[0x50] == bytes.fromhex('00 01 04 09 10 19 24 31')
Ejemplo n.º 26
0
def test_program_counter_label():
    asm = AsmDsl()
    asm(LDX, asm.pc, "LOAD PROGRAM COUNTER AS IMMEDIATE INTO X")
    asm(LDY, asm.pc, "LOAD PROGRAM COUNTER AS IMMEDIATE INTO Y")
    asm(LDS, asm.pc, "LOAD PROGRAM COUNTER AS IMMEDIATE INTO S")
    asm(LDU, asm.pc, "LOAD PROGRAM COUNTER AS IMMEDIATE INTO U")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('8E 00 00'
                                    '108E 00 03'
                                    '10CE 00 07'
                                    'CE 00 0b'
                                    '3F')
Ejemplo n.º 27
0
def test_leventhal_4_7__find_larger_of_two_numbers():
    asm = AsmDsl()
    asm(LDA, {0x40}, "GET FIRST OPERAND")
    asm(CMPA, {0x41}, "IS SECOND OPERAND LARGER?")
    asm(BHS, asm.stres)
    asm(LDA, {0x41}, "YES,GET SECOND OPERAND")
    asm.stres(STA, {0x42}, "STORE LARGER OPERAND")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('96 40'
                                    '91 41'
                                    '24 02'
                                    '96 41'
                                    '97 42'
                                    '3F')
Ejemplo n.º 28
0
def test_leventhal_6_2__find_first_non_blank_character():
    asm = AsmDsl()
    asm(LDX, 0x42, "POINT TO START OF STRING")
    asm(LDA, 0x20, "GET ASCII SPACE FOR COMPARISON ")
    asm.CHBLK(CMPA, {0: X + 1}, "IS CHARACTER AN ASCII SPACE?")
    asm(BEQ, asm.CHBLK, "YES, KEEP EXAMINING CHARS")
    asm(LEAX, {-1: X}, "NO, MOVE POINTER BACK ONE")
    asm(STX, {0x40}, "SAVE ADDRESS OF FIRST" "NON-BLANK CHARACTER")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('8E 0042'
                                    '86 20'
                                    'A1 80'
                                    '27 FC'
                                    '30 1F'
                                    '9F 40'
                                    '3F')
Ejemplo n.º 29
0
def check_object_code(machine_code, instruction, operand=None):
    __tracebackhide__ = True
    asm = AsmDsl()
    if operand is None:
        asm(instruction)
    else:
        asm(instruction, operand)
    code = assemble(statements(asm))
    actual_code = code[0]
    expected_code = bytes.fromhex(machine_code)
    if actual_code != expected_code:
        pytest.fail(
            "{instruction} {operand!r} assembled to {actual} not {expected}".
            format(
                instruction=instruction,
                operand=operand,
                actual=' '.join(format(b, '02X') for b in actual_code),
                expected=' '.join(format(b, '02X') for b in expected_code),
            ))
Ejemplo n.º 30
0
def test_leventhal_6_1b__length_of_a_string_of_characters():
    asm = AsmDsl()
    asm(LDB, 0xFF, "STRING LENGTH = -1")
    asm(LDX, 0x41, "POINT TO START OF STRING")
    asm(LDA, 0x0D, "GET ASCII CARRIAGE RETURN " "(STRING TERMINATOR)")
    asm.CHKCR(INCB, "ADD 1 TO STRING LENGTH")
    asm(CMPA, {0: X + 1}, "IS NEXT CHARACTER " "A CARRIAGE RETURN?")
    asm(BNE, asm.CHKCR, "NO, KEEP CHECKING")
    asm.DONE(STB, {0x40}, "YES, SAVE STRING LENGTH")
    asm(SWI)

    code = assemble(statements(asm))
    assert code[0] == bytes.fromhex('C6 FF'
                                    '8E 0041'
                                    '86 0D'
                                    '5C'
                                    'A1 80'
                                    '26 FB'
                                    'D7 40'
                                    '3F')