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")
def setup_module(): global vars, symbol_table, execution_address """Load the Emulator from the ROM script and Mandelbrot """ reload(asm) name, _ = os.path.splitext(os.path.basename(SCRIPT)) script_globals = {"__file__": str(SCRIPT.absolute()), "__name__": name} with SCRIPT.open("rb") as file: exec(compile(file.read(), SCRIPT, "exec"), script_globals) Emulator.load_rom_from_asm_module() vars = SimpleNamespace(**script_globals) # This sequence of calls is roughly taken from compilegcl.py old_rom_size = asm._romSize program = gcl.Program("Mandelbrot", forRom=False) user_code = asm.symbol("userCode") user_vars = asm.symbol("userVars") program.org(user_code) asm.align(1) asm.zpReset(user_vars) with GCL.open("r", encoding="utf-8") as fp: for line in fp.readlines(): program.line(line) program.end() asm.end() # Copy the resulting data straight into RAM, in the appropriate blocks data = asm.getRom1()[old_rom_size:] index, more_data = 0, bool(data) while more_data: start_address = int.from_bytes(data[index:index + 2], "big", signed=False) index += 2 size = data[index] or 256 index += 1 chunk = data[index:index + size] index += size RAM[start_address:start_address + len(chunk)] = chunk more_data = data[index] execution_address = program.execute symbol_table = program.vars
def emit_entry_page(vticks, vreturn): """Emit the data for NEXT and some other core routines The first page does not have the 'restart-or-quit' trampoline at 0x00 So we can't put any Forth word in here. """ while pc() & 255 < 255: nop() assert _next.INTERPRETER_ENTER_PAGE == pc() >> 8 label("FORTH_ENTER") C("You are now entering... Forth") adda(_next.INBOUND_TICK_CORRECTION) # --- Page boundary --- align(0x100, 0x100) st([vticks]) _next.next1(vticks) _next.next1_reenter(vticks) _next.next2(vticks) _next.exit(vticks, vreturn) _docol_exit.do_docol_rom() _docol_exit.do_docol_ram()
#----------------------------------------------------------------------- # Compile #----------------------------------------------------------------------- asm.loadBindings(args.sym) if args.gt1x: asm.loadBindings('Core/interface-dev.json') userCode = asm.symbol('userCode') userVars = asm.symbol('userVars') print('Compiling file %s' % args.gclSource) program = gcl.Program('Main', forRom=False) program.org(userCode) asm.align(1) # Forces default maximum ROM size asm.zpReset(userVars) # User variables can start here for line in open(args.gclSource).readlines(): program.line(line) program.end() asm.end() # End assembly data = asm.getRom1() #----------------------------------------------------------------------- # Append ending #----------------------------------------------------------------------- address = program.execute # Inject patch for reliable start using ROM v1 Loader application # See: https://forum.gigatron.io/viewtopic.php?p=27#p27
result = zpByte(2) # Used for storage tmp = zpByte() # Used for the continuation address after lookup. continuation = zpByte() # Used for the action to take with the high byte. high_byte_action = zpByte() # The following code implements a lookup table of floored quarter squares, # for values up to 255. # This is supposed to enable a fast multiplication for 7-bit numbers. # First the high-bytes. # The table is shifted down by 32 places, as the first 32 high-bytes are all zero # This allows us to have code later in the page which we can branch back to. align(0x100, size=0x100) label("Quarter-squares lookup table") for i in range(32, 256): val = math.floor(i**2 / 4) ld(hi(val)) C(f"${val:04x} = {val} = floor({i} ** 2 / 4); ${val:04x} >> 8 = ${val >> 8:02x}" ) # We jump back here after looking up the low-byte of the result. label("low-byte return point") ld(hi("multiply 7x7"), Y) jmp(Y, [continuation]) ld(hi(pc()), Y) # Make it easy to get back here! cost_of_low_byte_return = 3 label("table entry.possibly-negative") # AC is negative, if b > a. Find absolute value
def _start_page(): align(0x100, 0x100) _next.restart_or_quit()