Ejemplo n.º 1
0
def next3_ram_rom():
    """NEXT3 to use when in RAM->ROM mode"""
    label("forth.next3.ram-rom-mode")
    adda(-(cost_of_next3_ram_rom / 2))  # 1
    ld([IP_hi], Y)  # 2
    C("W <- [IP]")
    ld([IP_lo], X)  # 3
    ld([Y, X])  # 4
    st([W_lo])  # 5
    ld([IP_lo])  # 6
    adda(1)  # 7
    ld(AC, X)  # 8
    ld([Y, X])  # 9
    # Increment IP
    st([W_hi])  # 10
    C("IP <- IP + 2")
    ld([IP_lo])  # 11
    adda(2)  # 12
    beq(pc() + 5)  # 13
    st([IP_lo])  # 14
    REENTER(14)
    label(".page-boundary")
    ld([IP_hi])  # 15
    adda(1)  # 16
    st([IP_hi])  # 17
    REENTER(17)
Ejemplo n.º 2
0
def _two_times():
    """Implements a left-shift by one which is used for two words

    2* ( x1 -- x2 )
    CELLS ( n1 -- n2 )

    """
    label("forth.core.2*")
    label("forth.core.CELLS")
    adda(-add_cost_of_next(cost_of_two_times) / 2)  # 1
    # ld(data_stack_page, Y)  # Implemented in page header, but still counted here.
    # ld([data_stack_pointer], X)
    C("Load low-byte")
    ld([X])
    anda(0b1000_0000, X)  # 5
    C("Calculate bit to shift in to the high-byte")
    ld([X])
    st([tmp0])
    ld([data_stack_pointer], X)
    C("Reload and left-shift")
    ld([X])
    adda(AC)  # 10
    st([Y, Xpp])
    ld([Y, X])
    C("Load high byte and left-shift")
    adda(AC)
    adda([tmp0])
    st([Y, X])  # 15
    NEXT(cost_of_two_times)
Ejemplo n.º 3
0
def set():
    """Write a call value at an aligned address ( x a-addr -- )"""
    label("forth.core.!")
    adda(-add_cost_of_next(cost_of_set) / 2)  # 1
    ld(data_stack_page, Y)
    C("Remove 4 bytes from stack (SP moves by 4)")
    ld([data_stack_pointer])
    ld(AC, X)
    adda(4)  # 5
    st([data_stack_pointer])  # 6
    address_low, address_high, data_low, data_high = tmp0, tmp1, tmp2, tmp3
    C("Copy stack data and low part of address to temporary")
    for dest in [address_low, address_high, data_low]:
        ld([Y, X])  # 1
        st([dest])
        st([Y, Xpp])  # 3
    ld([Y, X])  # 1
    st([data_high])
    C("Load address")
    ld([address_low], X)
    ld([address_high], Y)
    C("Write data")
    ld([data_low])  # 5
    st([Y, Xpp])
    ld([data_high])
    st([Y, X])  # 8
    NEXT(cost_of_set)
Ejemplo n.º 4
0
 def drop():
     label("forth.core." + name)
     adda(-add_cost_of_next(cost_of_drop) / 2)
     ld([data_stack_pointer])
     adda(size)
     st([data_stack_pointer])
     NEXT(cost_of_drop)
Ejemplo n.º 5
0
def char_lit_rom_mode():
    """C-LIT - word that reads a byte encoded in the thread, and pushes it to the stack"""
    label("forth.internal.C-LIT")
    adda(-(cost_of_char_lit_rom_mode // 2))

    ld(-(cost_of_char_lit_rom_mode // 2))
    C("Store cost")
    st([tmp0])

    ld([data_stack_pointer])
    C("Decrement Data stack pointer and store high byte of 0")
    suba(1)  # 5
    ld(AC, X)
    ld(0)
    st([X])
    ld([data_stack_pointer])
    suba(2)  # 10
    ld(AC, X)
    st([data_stack_pointer])

    ld([IP_hi], Y)
    C("Jump to the code in the thread")
    ld(5)
    C("We're going to shift the IP by 5")
    nop(
    )  # 15, to meet requirement of move-ip that we must use an even number of cycles
    jmp(Y, [IP_lo])
    ld(0x00, Y)  # 17
Ejemplo n.º 6
0
def _start_definiton(label):
    """Mark the start of a definition"""
    global _current_label
    _assembler_call_buffer[:] = []  # Clear anything in the buffer
    _current_label = label
    _capture_asm_state()
    asm.label(label)
    docol_rom_only()
Ejemplo n.º 7
0
def restart_or_quit():
    assert pc() & 0xFF == 0, "restart_or_quit must be placed at the start of a page"
    label("forth.restart-or-quit")
    bra([W_lo])  # 6
    ble(pc() + 1)  # 7
    # 8 happens in start of thread again
    label(".quit")
    ld(hi("forth.exit"), Y)  # 9
    C("jmp forth.exit.from-failed-test")
    jmp(Y, lo("forth.exit.from-failed-test"))  # 10
Ejemplo n.º 8
0
def invert():
    label("forth.core.INVERT")
    adda(-add_cost_of_next(cost_of_invert) / 2)  # 1
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)
    ld([Y, X])
    xora(0xFF)  # 5
    st([Y, Xpp])
    ld([Y, X])
    xora(0xFF)
    st([Y, X])  # 9
    NEXT(cost_of_invert)
Ejemplo n.º 9
0
def _rshift__amount_eq_8():
    # Offset to n==8 case = 3
    label("forth.core.RSHIFT.n==8")
    adda(-add_cost_of_next(cost_of_rshift__amount_eq_8) / 2)  # 1
    # ld(data_stack_page, Y) # Happen in head of page, but still counted
    # ld([data_stack_pointer], X)
    st([Y, Xpp])  # Blat low byte
    ld([Y, X])  # 5
    ld([data_stack_pointer], X)
    st([Y, Xpp])
    ld(0)
    st([Y, X])  # 9
    NEXT(cost_of_rshift__amount_eq_8)
Ejemplo n.º 10
0
def next3_rom_head():
    """Start the process of next3"""
    label("forth.next3")
    label("forth.next3.rom-mode")
    adda(-(cost_of_next3_rom // 2))  # 1
    ld(-(cost_of_next3_rom // 2))  # 2
    st([tmp0])  # 3
    ld(W, X)  # 4
    ld(3)  # We're going to shift the IP by 3
    ld([IP_hi], Y)  # 6
    nop()  # 7
    jmp(Y, [IP_lo])  # 8
    ld(0x00, Y)  # 9
Ejemplo n.º 11
0
def _rshift__amount_lt_8():
    label("forth.core.RSHIFT.n<8")
    adda(-add_cost_of_next(cost_of_rshift__amount_lt_8) / 2)  # 1
    # ld(data_stack_page, Y) # Happen in head of page, but still counted
    # ld([data_stack_pointer], X)
    ld(lo("forth.core.RSHIFT.n<8.continuation1"))
    st([continuation])  # 5
    bra("right-shift-by-n")
    ld([amount])
    label("forth.core.RSHIFT.n<8.continuation1")
    st([Y, Xpp])
    ld(lo("forth.core.RSHIFT.n<8.continuation2"))
    st([continuation])  # 10
    bra("left-shift-by-n")
    ld([transfer_amount])
    label("forth.core.RSHIFT.n<8.continuation2")
    ld([data_stack_pointer], X)
    ora([Y, X])
    st([Y, Xpp])  # 15
    ld(lo("forth.core.RSHIFT.n<8.continuation3"))
    st([continuation])
    bra("right-shift-by-n.second-time")
    ld([mask])
    label("forth.core.RSHIFT.n<8.continuation3")
    st([Y, X])  # 20
    NEXT(cost_of_rshift__amount_lt_8)
Ejemplo n.º 12
0
def _lshift__amount_lt_8():
    """LSHIFT (x1 u -- x2)

    Special case where u < 8
    """
    label("forth.core.LSHIFT.n<8")
    adda(-add_cost_of_next(cost_of_lshift__amount_lt_8) / 2)  # 1
    # ld(data_stack_page, Y)
    # ld([data_stack_pointer], X)
    ld(lo("forth.core.LSHIFT.n<8.continuation1"))
    st([continuation])  # 5
    bra("right-shift-by-n")
    ld([transfer_amount])
    label("forth.core.LSHIFT.n<8.continuation1")
    st([high_byte_temp])
    ld(lo("forth.core.LSHIFT.n<8.continuation2"))
    st([continuation])  # 10
    bra("left-shift-by-n")
    ld([amount])
    label("forth.core.LSHIFT.n<8.continuation2")
    st([Y, Xpp])
    ld(lo("forth.core.LSHIFT.n<8.continuation3"))
    st([continuation])  # 15
    bra("left-shift-by-n")
    ld([amount])
    label("forth.core.LSHIFT.n<8.continuation3")
    ora([high_byte_temp])
    st([Y, X])  # 19
    NEXT(cost_of_lshift__amount_lt_8)
Ejemplo n.º 13
0
def shift(vtmp):
    """Place all of the code required for 2*, LSHIFT, RSHIFT and 2/

    Needs a page to itself.
    """
    # Customized restart or quit trampoline which loads Y and X so that
    # they point at the data stack. This saves space at no runtime cost.
    assert pc(
    ) & 0xFF == 0, "restart_or_quit must be placed at the start of a page"
    label("forth.restart-or-quit")
    ble(pc() + 3)  # 6
    ld(data_stack_page, Y)  # 7
    bra([W_lo])
    ld([data_stack_pointer], X)  # 8; nop for purposes of .quit
    label(".quit")
    ld(hi("forth.exit"), Y)  # 9
    C("jmp forth.exit.from-failed-test")
    jmp(Y, lo("forth.exit.from-failed-test"))  # 10
    # 11, overlap with whatever comes next - hopefully not a branch or jump!

    _two_times()
    offset_start = pc()
    _lshift()
    offset_of_shift_by_8 = pc() - offset_start
    _lshift__amount_eq_8()
    offset_of_shift_by_gt_8 = pc() - offset_start
    _lshift__amount_gt_8()
    offset_of_shift_by_lt_8 = pc() - offset_start
    _lshift__amount_lt_8()

    rshift_offset_start = pc()
    _rshift()
    assert pc() - rshift_offset_start <= offset_of_shift_by_8
    fillers(until=(rshift_offset_start + offset_of_shift_by_8) & 255)
    _rshift__amount_eq_8()
    assert pc() - rshift_offset_start <= offset_of_shift_by_gt_8
    fillers(until=(rshift_offset_start + offset_of_shift_by_gt_8) & 255)
    _rshift__amount_gt_8()
    assert pc() - rshift_offset_start <= offset_of_shift_by_lt_8
    fillers(until=(rshift_offset_start + offset_of_shift_by_lt_8) & 255)
    _rshift__amount_lt_8()
    _shift_entry(
        offset_to_amount_eq_8=offset_of_shift_by_8,
        offset_to_amount_gt_8=offset_of_shift_by_gt_8,
        offset_to_amount_lt_8=offset_of_shift_by_lt_8,
    )
    _left_shift_by_n()
    _right_shift_by_n(vtmp)
    _two_div(vtmp)
Ejemplo n.º 14
0
def do_restore_mode():
    label("forth.DO-RESTORE-MODE")
    adda(-add_cost_of_reenter(cost_of_do_restore_mode) / 2)
    ld(return_stack_page, Y)
    ld([return_stack_pointer], X)
    ld([return_stack_pointer])
    adda(1)
    st([return_stack_pointer])
    ld([Y, X])
    st([mode])
    ld(0, Y)
    ld(W, X)
    st(lo("forth.core.EXIT"), [Y, Xpp])
    st(hi("forth.core.EXIT"), [Y, Xpp])  # 12
    REENTER(cost_of_do_restore_mode)
Ejemplo n.º 15
0
def exit():
    """Word to exit from a thread"""
    label("forth.core.EXIT")
    adda(-add_cost_of_next(cost_of_exit) / 2)
    ld(return_stack_page, Y)
    ld([return_stack_pointer], X)
    ld([Y, X])
    st([IP_lo])
    ld([return_stack_pointer])
    adda(1, X)
    adda(2)
    st([return_stack_pointer])
    ld([Y, X])
    st([IP_hi])  # 11
    NEXT(cost_of_exit)
Ejemplo n.º 16
0
def _lshift__amount_eq_8():
    """LSHIFT (x1 u -- x2)

    Special case where u = 8
    """
    label("forth.core.LSHIFT.n==8")
    adda(-add_cost_of_next(cost_of_lshift__amount_eq_8) / 2)  # 1
    # ld(data_stack_page, Y)
    # ld([data_stack_pointer], X)
    ld([Y, X])
    st([tmp0])  # 5
    ld(0)
    st([Y, Xpp])
    ld([tmp0])
    st([Y, X])  # 9
    NEXT(cost_of_lshift__amount_eq_8)
Ejemplo n.º 17
0
def branch_rom_mode():
    """Unconditional Branch ( -- )"""
    label("forth.internal.rom-mode.BRANCH")
    adda(-cost_of_branch_rom_mode // 2)  # 1

    ld(-(cost_of_branch_rom_mode // 2))
    C("Store cost")
    st([tmp0])

    ld(W, X)
    C("X <- W")

    ld([IP_hi], Y)  # 5
    C("Jump to the code in the thread")
    jmp(Y, [IP_lo])
    ld(0x00, Y)  # 7
Ejemplo n.º 18
0
def next1(vTicks):
    """Routine to make continue or abort decisions, and dispatch to the next word"""
    # Invariant - on entry the vTicks variable and the accumulator both hold
    # an accurate number of cycles until we must be back in the display loop,
    # starting from the first instruction of this routine.
    # This value will always be greater than the cost of failing continue/abort test. This is true
    # whenever we return here from another word, and true when we first enter from the
    # display loop.
    label("forth.next1")
    C(
        "Timing point: [vTicks] == AC == accurate number of ticks until we need to be back"
    )
    suba((cost_of_successful_test + cost_of_failfast) / 2)  # 1
    ld([W_hi], Y)  # 2
    jmp(Y, [W_lo])  # 3
    bra("forth.restart-or-quit")  # 4
Ejemplo n.º 19
0
def move_ip():
    """Page-Zero code to move the IP by the amount contained in AC

    This routine is used by the ROM mode next3, and also by literal, branch and zero_branch.
    As these routines all have different lengths, it uses a variable (tmp0) to tell it what length to return

    It always jumps to forth.next1.reenter.odd, and it has an odd length itself code calling it must have an even length
    """
    assert pc() >> 8 == 0
    label("forth.move-ip")
    adda([IP_lo])  # 1
    st([IP_lo])  # 2
    ld(hi("forth.next1.reenter"), Y)  # 3
    C("REENTER")
    jmp(Y, lo("forth.next1.reenter.odd"))  # 4
    ld([tmp0])  # 5
Ejemplo n.º 20
0
def two_dup():
    label("forth.core.2DUP")
    adda(-add_cost_of_next(cost_of_2dup) / 2)  # 1
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)  # 3
    for tmp in [tmp0, tmp1, tmp2, tmp3]:
        ld([Y, X])
        st([tmp])
        st([Y, Xpp])  # 15 = 3 + 4 * 3
    ld([data_stack_pointer])
    suba(4)
    st([data_stack_pointer], X)  # 18
    for tmp in [tmp0, tmp1, tmp2, tmp3]:
        ld([tmp])
        st([Y, Xpp])  # 26 = 18 + 4 * 2
    NEXT(cost_of_2dup)
Ejemplo n.º 21
0
def _rshift__amount_gt_8():
    # offset to n > 8 case
    label("forth.core.RSHIFT.n>8")
    adda(-add_cost_of_next(cost_of_rshift__amount_gt_8) / 2)  # 1
    # ld(data_stack_page, Y) # Happen in head of page, but still counted
    # ld([data_stack_pointer], X)
    ld(lo("forth.core.RSHIFT.n>8.continuation"))
    st([continuation])  # 5
    bra("right-shift-by-n")
    ld([amount])
    label("forth.core.RSHIFT.n>8.continuation")
    st([Y, Xpp])
    st([Y, Xpp])
    ld([data_stack_pointer], X)  # 10
    ld(0)
    st([Y, X])  # 12
    NEXT(cost_of_rshift__amount_gt_8)
Ejemplo n.º 22
0
def emit_kernel_words(vtmp):
    #### Page
    _start_page()
    _next.next3_rom_head()
    _next.next3_ram_rom()
    _next.next3_ram_ram()
    _docol_exit.do_restore_mode()
    _docol_exit.restore_mode()
    _docol_exit.exit()
    _docol_exit.docol_ram_ram()
    _memory.char_at()
    _memory.char_set()
    _arithmetic.increment()
    _arithmetic.decrement()
    _arithmetic.zero_equal()
    _literal.lit_rom_mode()
    _literal.char_lit_rom_mode()
    _branching.branch_rom_mode()
    ####
    _start_page()
    _branching.question_branch_rom_mode()
    _stackmanipulation.drop()
    _stackmanipulation.drop_two()
    _stackmanipulation.swap()
    _stackmanipulation.dup()
    _stackmanipulation.over()
    _stackmanipulation.rot()
    _stackmanipulation.two_swap()
    _arithmetic.bitwise()
    _arithmetic.invert()
    # No-op thread used for testing DOCOL and EXIT
    # This can probably be removed later
    label("forth.NOP")
    _docol_exit.make_thread()
    # Shifts have a special restart or quit trampoline to save space.
    align(0x100, 0x100)
    _shift.shift(vtmp)
    _start_page()
    _stackmanipulation.two_dup()
    _arithmetic.add()
    _memory.at()
    _memory.set()
    from . import _compiler

    _compiler.compile_file("core.f")
Ejemplo n.º 23
0
def increment():
    "Add one to the top of the stack (n -- n)"
    label("forth.core.1+")
    adda(-add_cost_of_next(cost_of_increment) / 2)  # 1
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)
    ld([Y, X])
    adda(1)  # 5
    bne(lo(".done"))  # 6
    st([Y, Xpp])  # 7

    ld([Y, X])  # 8
    adda(1)
    st([Y, X])
    NEXT(cost_of_increment__two_words_written)

    label(".done")
    NEXT(cost_of_increment__one_word_written)
Ejemplo n.º 24
0
def decrement():
    "Subtract one from the top of the stack (n -- n)"
    label("forth.core.1-")
    adda(-add_cost_of_next(cost_of_decrement) / 2)  # 1
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)
    ld([Y, X])
    beq(lo(".low-byte-was-zero"))  # 5
    suba(1)  # 6
    st([Y, X])  # 7
    NEXT(cost_of_decrement__one_word_written)

    label(".low-byte-was-zero")
    st([Y, Xpp])  # 7
    ld([Y, X])
    suba(1)
    st([Y, X])  # 10
    NEXT(cost_of_decrement__two_words_written)
Ejemplo n.º 25
0
def char_at():
    label("forth.core.C@")
    adda(-add_cost_of_next(cost_of_char_at) / 2)  # 1
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)
    ld([Y, X])
    st([tmp0])  # 5
    st([Y, Xpp])
    ld([Y, X])
    ld(AC, Y)
    ld([tmp0], X)
    ld([Y, X])  # 10
    ld(data_stack_page, Y)
    ld([data_stack_pointer], X)
    st([Y, Xpp])
    ld(0)
    st([Y, X])  # 15
    NEXT(cost_of_char_at)
Ejemplo n.º 26
0
def dup():
    label("forth.core.DUP")
    adda(-add_cost_of_next(cost_of_dup) / 2)
    ld([data_stack_pointer], X)
    ld([X])
    st([tmp0])
    ld([data_stack_pointer])  # 5
    adda(1, X)
    ld([X])
    st([tmp1])
    ld(data_stack_page, Y)
    ld([data_stack_pointer])  # 10
    suba(2)
    st([data_stack_pointer], X)
    ld([tmp0])
    st([Y, Xpp])
    ld([tmp1])  # 15
    st([Y, X])  # 16
    NEXT(cost_of_dup)
Ejemplo n.º 27
0
def docol_ram_ram():
    """Word that implements DOCOL for a thread in RAM"""
    label("forth.DOCOL")
    adda(-add_cost_of_next(cost_of_docol_ram_ram) / 2)  # 1
    ld(return_stack_page, Y)
    _push_ip_to_return_stack()
    # The Next3 for ram-ram mode leaves the thread address in tmp0, tmp1
    # We need to increment it by two, and store in IP
    ld([tmp0])
    adda(2)
    st([IP_lo])  # 5
    beq(lo(".page-boundary#docol"))  # Page boundary test
    ld([tmp1])  # 7
    st([IP_hi])  # 8
    NEXT(cost_of_docol_ram_ram__page_not_crossed)
    label(".page-boundary#docol")
    adda(1)  # 8
    st([IP_hi])  # 9
    NEXT(cost_of_docol_ram_ram__page_crossed)
Ejemplo n.º 28
0
def exit(vTicks, vReturn):
    label("forth.exit")  # Counting down
    label("forth.exit.from-failed-test")
    ld(-(cost_of_failed_next1 + 1) / 2)  # 7
    label("forth.exit.from-next1-reenter")
    label("forth.exit.from-next2")
    adda([vTicks])  # 6
    ld(hi("vBlankStart"), Y)  # 5
    bgt(pc() & 0xFF)  # 4
    suba(1)  # 3
    jmp(Y, [vReturn])  # 2
    nop()  # 1
Ejemplo n.º 29
0
def over():
    label("forth.core.OVER")
    adda(-add_cost_of_next(cost_of_over) / 2)
    ld([data_stack_pointer])
    adda(2, X)
    ld([X])
    st([tmp0])  # 5
    ld([data_stack_pointer])
    adda(3, X)
    ld([X])
    st([tmp1])
    ld(data_stack_page, Y)  # 10
    ld([data_stack_pointer])
    suba(2)
    st([data_stack_pointer], X)
    ld([tmp0])
    st([Y, Xpp])  # 15
    ld([tmp1])
    st([Y, X])  # 17
    NEXT(cost_of_over)
Ejemplo n.º 30
0
def _lshift__amount_gt_8():
    """LSHIFT (x1 u -- x2)

    Special case where u > 8
    """
    label("forth.core.LSHIFT.n>8")
    adda(-add_cost_of_next(cost_of_lshift__amount_gt_8) / 2)  # 1
    # ld(data_stack_page, Y)
    # ld([data_stack_pointer], X)
    ld(lo("forth.core.LSHIFT.n>8.continuation"))
    st([continuation])  # 5
    bra("left-shift-by-n")  # 6
    ld([amount])  # 7
    label("forth.core.LSHIFT.n>8.continuation")
    st([Y, Xpp])  # 1
    st([Y, Xpp])  # 2
    ld([data_stack_pointer], X)  # 3
    ld(0)  # 4
    st([Y, Xpp])  # 5
    NEXT(cost_of_lshift__amount_gt_8)