Ejemplo n.º 1
0
def test_docol_ram(emulator, return_stack, ip, mode, return_stack_depth):
    """Test the docol implementation for RAM mode

    On entry:
    IP holds the RAM address after the one we've just come from
    W holds the address of our NOP instruction
    mode holds the mode

    On exit:
    IP holds the first address of the thread
    mode holds the address of NEXT3-ROM-Mode
    The return stack holds:
        Top: The address of restore-mode (little-endian)
        2:   The previous mode
        3:   The old ip (little endian)
    """
    # Arrange
    return_stack.set_depth_in_bytes(return_stack_depth)
    set_IP(ip)
    set_mode(mode)
    set_W(asm.symbol("forth.NOP"))
    # Act
    do_test_word(emulator, "forth.NOP")
    # Assert
    assert end_of_docol == get_IP()
    assert asm.symbol("forth.next3.rom-mode") & 0xFF == get_mode()
    assert [asm.symbol("forth.RESTORE-MODE"), mode, ip] == [
        return_stack.pop_u16(),
        return_stack.pop_u8(),
        return_stack.pop_u16(),
    ]
    assert len(return_stack) == return_stack_depth
Ejemplo n.º 2
0
def test_branch_rom_mode(emulator, address, target):
    # Arrange
    # Jump target must not intersect with jump
    assume(not set(range(address, address + 2))
           & set(range(target, target + 3)))
    # Jump address cannot be encoded right at the end of a page.
    # In practice this is not a problem, it's a two instruction encoding, and we
    # already have a requirement that threads can't cross pages.
    assume(address & 0xFF != 0xFF)
    set_IP(address)
    ip_movement = target - address + 3
    ROM[target:target + 3] = [
        b"\xdc\x42",  # st $42,[y, x++]
        [0xE0, asm.symbol("forth.move-ip")],  # jmp [y,]
        b"\xdc\x82",  # $82,[y, x++]
    ]
    ROM[address:address + 2] = [
        # Encoding for data
        [0xFC, target & 0xFF],  # bra target
        [0x00, ip_movement & 0xFF],  # ld ip_movement
    ]
    # Act
    do_test_word(emulator,
                 "forth.internal.rom-mode.BRANCH",
                 continue_on_reenter=False)
    # Assert
    assert (target + 3) & 0xFF == get_IP(
    ) & 0xFF  # low-byte equality, because move-ip doesn't handle page crossings
    assert 0x8242 == get_W()
Ejemplo n.º 3
0
def test_docol_rom(emulator, return_stack, ip, return_stack_depth):
    """Test the docol implementation for RAM mode

    On entry:
    IP holds the ROM address after the one we've just come from
    W holds the address of our NOP instruction
    mode holds ROM mode

    On exit:
    IP holds the first address of the thread
    mode holds the address of NEXT3-ROM-Mode
    The return stack holds the old ip (little endian)
    """
    # Arrange
    return_stack.set_depth_in_bytes(return_stack_depth)
    set_IP(ip)
    set_mode(asm.symbol("forth.next3.rom-mode") & 0xFF)
    set_W(nop_start_rom)
    # Act
    do_test_word(emulator, nop_start_rom)
    # Assert
    assert end_of_docol == get_IP()
    assert asm.symbol("forth.next3.rom-mode") & 0xFF == get_mode()
    assert [ip] == [return_stack.pop_u16()]
    assert len(return_stack) == return_stack_depth
Ejemplo n.º 4
0
def test_invert(emulator, data_stack, data_stack_depth, tos):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(tos)
    # Act
    do_test_word(emulator, "forth.core.INVERT")
    # Assert
    assert (~tos & 0xFFFF) == data_stack.pop_u16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 5
0
def test_zero_equal(emulator, data_stack, data_stack_depth, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(data)
    # Act
    do_test_word(emulator, "forth.core.0=")
    # Assert
    assert (data == 0) == data_stack.pop_flag()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 6
0
def test_decrement(emulator, data_stack, data_stack_depth, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(data)
    # Act
    do_test_word(emulator, "forth.core.1-")
    # Assert
    assert (data - 1) & 0xFFFF == data_stack.pop_i16() & 0xFFFF
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 7
0
def test_exit(emulator, return_stack, return_address, return_stack_depth):
    # Arrange
    return_stack.set_depth_in_bytes(return_stack_depth)
    return_stack.push_word(return_address)
    # Act
    do_test_word(emulator, "forth.core.EXIT")
    # Assert
    assert return_address == get_IP()
    assert len(return_stack) == return_stack_depth
Ejemplo n.º 8
0
def test_swap(emulator, data_stack, initial_stack):
    for value in reversed(initial_stack):
        data_stack.push_word(value)
    # Act
    do_test_word(emulator, "forth.core.SWAP")
    # Assert
    expected_stack = list(reversed(initial_stack[:2])) + initial_stack[2:]
    actual_stack = [data_stack.pop_u16() for _ in range(len(data_stack) // 2)]
    assert actual_stack == expected_stack
Ejemplo n.º 9
0
def test_2drop(emulator, data_stack, initial_stack):
    # Arrange
    for value in reversed(initial_stack):
        data_stack.push_word(value)
    # Act
    do_test_word(emulator, "forth.core.2DROP")
    # Assert
    expected_stack = initial_stack[2:]
    actual_stack = [data_stack.pop_u16() for _ in range(len(data_stack) // 2)]
    assert actual_stack == expected_stack
Ejemplo n.º 10
0
def test_add(emulator, data_stack, data_stack_depth, tos, nos):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(nos)
    data_stack.push_word(tos)
    # Act
    do_test_word(emulator, "forth.core.+")
    # Assert
    assert (tos + nos) & 0xFFFF == data_stack.pop_u16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 11
0
def test_two_dup(emulator, data_stack, initial_stack):
    # Arrange
    for value in reversed(initial_stack):
        data_stack.push_word(value)
    # Act
    do_test_word(emulator, "forth.core.2DUP")
    # Assert
    expected_stack = [initial_stack[0], initial_stack[1]] + initial_stack
    actual_stack = [data_stack.pop_u16() for _ in range(len(data_stack) // 2)]
    assert actual_stack == expected_stack
Ejemplo n.º 12
0
def test_next3_ram_rom(emulator, ip):
    # Arrange
    emulator.next_instruction = "forth.next3.ram-rom-mode"
    set_IP(ip)
    RAM[ip:ip + 2] = bytearray(struct.pack("<H", WORD_START))
    # Act
    do_test_word(emulator, continue_on_reenter=False)
    # Assert
    assert get_W() == WORD_START
    assert get_IP() == ip + 2
Ejemplo n.º 13
0
def test_at(emulator, data_stack, data_stack_depth, address, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    RAM[address:address + 2] = data.to_bytes(2, "little", signed=True)
    data_stack.push_word(address)
    # Act
    do_test_word(emulator, "forth.core.@")
    # Assert
    assert data == data_stack.pop_i16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 14
0
def test_char_set(emulator, data_stack, data_stack_depth, address, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(data)
    data_stack.push_word(address)
    # Act
    do_test_word(emulator, "forth.core.C!")
    # Assert
    assert data_stack_depth == len(data_stack)
    assert RAM[address] == data
Ejemplo n.º 15
0
def test_char_at(emulator, data_stack, data_stack_depth, address, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    RAM[address] = data
    data_stack.push_word(address)
    # Act
    do_test_word(emulator, "forth.core.C@")
    # Assert
    assert data == data_stack.pop_i16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 16
0
 def test(emulator, data_stack, data_stack_depth, tos, nos):
     # Arrange
     data_stack.set_depth_in_bytes(data_stack_depth)
     data_stack.push_word(nos)
     data_stack.push_word(tos)
     # Act
     do_test_word(emulator, f"forth.core.{name}")
     # Assert
     expected = operator(tos, nos)
     assert expected == data_stack.pop_i16()
     assert data_stack_depth == len(data_stack)
Ejemplo n.º 17
0
def test_2swap(emulator, data_stack, initial_stack):
    # Arrange
    for value in reversed(initial_stack):
        data_stack.push_word(value)
    # Act
    do_test_word(emulator, "forth.core.2SWAP")
    # Assert
    x4, x3, x2, x1, *rest = initial_stack
    expected_stack = [x2, x1, x4, x3] + rest
    actual_stack = [data_stack.pop_u16() for _ in range(len(data_stack) // 2)]
    assert actual_stack == expected_stack
Ejemplo n.º 18
0
def test_set(emulator, data_stack, data_stack_depth, address, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(data)
    data_stack.push_word(address)
    # Act
    do_test_word(emulator, "forth.core.!")
    # Assert
    assert data_stack_depth == len(data_stack)
    assert data == int.from_bytes(RAM[address:address + 2],
                                  "little",
                                  signed=True)
Ejemplo n.º 19
0
def test_next3_ram_ram(emulator, ip, target):
    # Arrange
    # Address IP and target address can't intersect
    assume(not set(range(target, target + 2)) & set(range(ip, ip + 2)))
    emulator.next_instruction = "forth.next3.ram-ram-mode"
    RAM[target:target + 2] = bytearray(struct.pack("<H", WORD_START))
    set_IP(ip)
    RAM[ip:ip + 2] = bytearray(struct.pack("<H", target))
    # Act
    do_test_word(emulator, continue_on_reenter=False)
    # Assert
    assert get_W() == WORD_START
    assert get_IP() == ip + 2
Ejemplo n.º 20
0
def test_next3_rom(emulator):
    emulator.next_instruction = "forth.next3.rom-mode"
    set_IP(WORD_START)
    ROM[WORD_START:WORD_START + 3] = [
        b"\xdc\x42",  # st $42,[y, x++]
        [0xE0, asm.symbol("forth.move-ip")],  # jmp [y,]
        b"\xdc\x82",  # $82,[y, x++]
    ]

    do_test_word(emulator, continue_on_reenter=False)

    assert get_W() == 0x8242
    assert get_IP() == WORD_START + 3
Ejemplo n.º 21
0
def test_exit_to_ram_mode(emulator, return_stack, return_address, mode,
                          return_stack_depth):
    # Arrange
    return_stack.set_depth_in_bytes(return_stack_depth)
    return_stack.push_word(return_address)
    return_stack.push_byte(mode)
    return_stack.push_word(asm.symbol("forth.RESTORE-MODE"))
    # Act
    do_test_word(emulator, "forth.core.EXIT")
    # Exit should have left restore-mode in IP, so next should DTRT
    do_test_word(emulator, "forth.next3.rom-mode")
    # Assert
    assert mode == get_mode()
    assert return_address == get_IP()
    assert len(return_stack) == return_stack_depth
Ejemplo n.º 22
0
def test_two_div(emulator, data_stack, data_stack_depth, tos):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(tos)
    # Act
    do_test_word(
        emulator,
        "forth.core.2/",
        cycles_shifted_to_trampoline=2,
        before_each_entry_do=lambda: data_stack.set_x_and_y_registers(emulator
                                                                      ),
    )
    # Assert
    assert (tos >> 1) == data_stack.pop_i16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 23
0
def test_rshift(emulator, data_stack, data_stack_depth, tos, nos):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(nos)
    data_stack.push_word(tos)
    set_W(asm.symbol("forth.core.RSHIFT"))

    # Act
    do_test_word(
        emulator,
        "forth.core.RSHIFT",
        cycles_shifted_to_trampoline=2,
        before_each_entry_do=lambda: data_stack.set_x_and_y_registers(emulator
                                                                      ),
    )
    # Assert
    assert ((nos & 0xFFFF) >> tos) == data_stack.pop_u16()
    assert data_stack_depth == len(data_stack)
Ejemplo n.º 24
0
def test_question_branch_rom_mode(emulator, data_stack, address, target,
                                  data_stack_depth, tos):
    # Arrange
    # Jump target must not intersect with jump
    assume(not set(range(address, address + 5))
           & set(range(target, target + 3)))
    # We need to not be within the last five bytes of the page,
    # as there needs to be an instruction after us to run into if we don't branch.
    assume((address & 0xFF) + 5 <= 0xFF)
    data_stack.set_depth_in_bytes(data_stack_depth)
    data_stack.push_word(tos)
    set_IP(address)
    ip_movement = target - address + 3
    ROM[target:target + 3] = [
        b"\xdc\x00",  # st $00,[y, x++]
        [0xE0, asm.symbol("forth.move-ip")],  # jmp [y,]
        b"\xdc\x00",  # $00,[y, x++]
    ]
    ROM[address:address + 5] = [
        # Encoding for data
        [0xFC, target & 0xFF],  # bra target
        [0x00, ip_movement & 0xFF],  # ld ip_movement
        # Encoding for following word
        b"\xdc\xff",  # st $ff,[y, x++]
        [0xE0, asm.symbol("forth.move-ip")],  # jmp [y,]
        b"\xdc\xff",  # $ff,[y, x++]
    ]
    # Act
    do_test_word(emulator,
                 "forth.internal.rom-mode.?BRANCH",
                 continue_on_reenter=False)
    # Assert
    if not tos:
        # IP should point after target address
        assert (target + 3) & 0xFF == get_IP(
        ) & 0xFF  # low-byte equality, because move-ip doesn't handle page crossings
        # Target instruction should be about to run
        assert 0x0000 == get_W()
    else:
        # We run into the encoding of the next instruction, so IP should point after it.
        assert (address + 5) & 0xFF == get_IP() & 0xFF
        # Next instruction should be about to run
        assert 0xFFFF == get_W()
Ejemplo n.º 25
0
def test_rom_mode_char_literal(emulator, data_stack, data_stack_depth, data):
    # Arrange
    data_stack.set_depth_in_bytes(data_stack_depth)
    set_IP(WORD_START)
    ROM[WORD_START : WORD_START + 5] = [
        # Encoding for data
        [0xDC, data & 0xFF],
        [0x10, W],  # ld $00,x
        # Encoding for next word
        b"\xdc\x42",  # st $42,[y, x++]
        [0xE0, asm.symbol("forth.move-ip")],  # jmp [y,]
        b"\xdc\x82",  # $82,[y, x++]
    ]
    # Act
    do_test_word(emulator, "forth.internal.C-LIT", continue_on_reenter=False)
    # Assert
    assert data == data_stack.pop_i16()
    assert data_stack_depth == len(data_stack)
    assert WORD_START + 5 == get_IP()
    assert 0x8242 == get_W()
Ejemplo n.º 26
0
def test_docol_ram_ram(emulator, return_stack, ip, target, return_stack_depth):
    """Test jumping from one thread in RAM to another"""
    # Arrange
    emulator.zero_memory()
    return_stack.set_depth_in_bytes(return_stack_depth)
    assume(not {ip, ip + 1} & {target, target + 1})
    set_IP(ip)
    set_mode(asm.symbol("forth.next3.ram-ram-mode") & 0xFF)
    RAM[target:target + 2] = [
        asm.symbol("forth.DOCOL") & 0xFF,
        asm.symbol("forth.DOCOL") >> 8,
    ]
    RAM[ip:ip + 2] = [
        target & 0xFF,
        target >> 8,
    ]
    # Act
    do_test_word(emulator, "forth.next3.ram-ram-mode")
    # Assert
    assert len(return_stack) == return_stack_depth + 2
    assert [ip + 2] == [return_stack.pop_u16()]
    assert target + 2 == get_IP()
Ejemplo n.º 27
0
def _do_test_thread(emulator, label):
    set_IP(0x4282)
    set_W(symbol(label))
    do_test_word(emulator, get_W())
    while get_IP() != 0x4282:
        do_test_word(emulator, "forth.next3.rom-mode")