예제 #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
예제 #2
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
예제 #3
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()
예제 #4
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
예제 #5
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
예제 #6
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()
예제 #7
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
예제 #8
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
예제 #9
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
예제 #10
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()
예제 #11
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()
예제 #12
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")