Skip to main content

TFORTH

Overview

TFORTH is my custom version of FORTH. It started as a programming exercise that grew into a somewhat usable language. This version of FORTH is a bit odd in that it has no compiling mode at all. Not even bytecode compiling. Everything is 100% interpreted. So, it's essentially a fancy text parser. It also doesn't try to be ANSI compliant at all.

That being said, it does support a lot of common FORTH things like you would expect, including: custom function definitions, calling external functions via function pointers, full access to the system's memory map, input/output, etc.


 

Variables

There are some big differences, under-the-hood, with this version of FORTH. For one, there are no variables. Instead, I define variables as functions with a index to the "variable page," a page in memory dedicated to temporary storage. So, for example, 
 
5 0 !

would assign the literal value 5 to index 0 in the variable page. So, to declare a "variable," I would do the following 

: X 0 ; 

This would create a function called X which pushes the literal value 0 onto the stack. So, when you call: 

5 X !

it does the same operation as above. The reason I didn't implement the VARIABLE keyword is that, under-the-hood, the lookup process would be the same as if it was a function.

Functions

Functions, when defined, are stored as nodes in a linked list. The node itself has the following format:

1 byte  -   length of function name
n bytes -   function name string
1 byte  -   length of entire function def, used for calculating next node
n bytes -   string content of function, ';' terminated
 
So, as shown above, functions themselves are stored into memory as string literals. When the engine is instructed to execute a user-defined function, it stores the state of the engine and switches to parsing the string within the linked list. When the ';' function is called, it acts like a return function and reloads the previous state of the engine. Functions can be deleted with the DELETE keyword. This deletes the function and restores the consumed memory by shifting the linked list down as necessary. 
 
But, because nothing is compiled, the act of creating functions is more of a convenience than a requirement.  
  

Extended Memory (EXM)

As of writing, my version of FORTH works on 8-bit numbers. These can be represented as signed, unsigned, or hexadecimal numbers, but it is still limited to 8-bits. This becomes an issue when you want to access memory or functions in 16-bit address space. So, as a quick fix, I added in some extra functions and engine-specific variables.
 
EXML@           - Get EXtendedMemory L
EXMH@           - Get ExtendedMemory H
EXML!           - Set EXtendedMemory L
EXMH!           - Set ExtendedMemory H
EXM!            - Write value to (EXML, EXMH)
EXM@            - Read value from (EXML, EXMH)
EXMP++          - Increment (EXML, EXMH)
EXMP--          - Deincrement (EXML, EXMH)
EXMCALL         - Call subroutine at (EXML, EXMH)
ARGA!           - Set register A before exmcall
ARGX!           - Set register X before exmcall
ARGY!           - Set register Y before exmcall  
 
As shown, this kinda just bolts-on 16-bit memory functionality to this 8-bit system. As an example, if I had a function at $CE12 that I wanted to call from FORTH, I could do the following:
 
$ CE EXMH!      - Set EXMH to $CE
$ 12 EXML!      - Set EXML to $12
EXMCALL         - Call function at (EXML, EXMH)
 
In machine code, this effectively translates to:
 
lda #$CE
sta EXMH
lda #$12
sta EXML
pha
phx
phy
lda ARGA
ldx ARGX
ldy ARGY
jsr (EXML)
...
  
While this is a rather slow process, it allows the programmer to call external functions or read/write to the full 16-bit address space. 
 

Going Forward

Because this was just a programming exercise, I don't have any plans to make this ANSI compliant, if that's even possible, or more usable.  That said, I have found it useful in development of this computer. And, it is nifty to write in, what is essentially, a scripting language for a 65C02 computer. 
 

Comments

Popular posts from this blog

TPC65 - History: breadboards and protoboards

Since I was a teenager, something I've always wanted to do was design and build a computer, chip-by-chip. I was inspired by the movie Pirates of Silicon Valley, specifically when Steve Wozniak built a computer, the Apple 1, that started an empire. So, I started learning electronics with the main goal of making my own computer.   Breadboard Shenanigans   In 2018, I finally got around to working with the legendary 6502 CPU and built my first rudimentary computer that barely worked. This version of the computer relied on an Arduino Mega to act as an EEPROM and serial interface. Thus, the entire computer needed to be synchronized to the Arduino to function. Unfortunately, building computers on breadboards is a pretty frustrating task. Breadboards are prone to manufacturing defects that can cause intermittent shorts between components, intermittent connections between the breadboard and components, massive amounts of parasitic capacitance and inductance. All of which are incre...

TPC65 - History: The PCB Age

Version 1.0 Even though the protoboard computer works, and I successfully worked with it for months, it has some significant drawbacks: Difficult to modify Making any changes to the system requires maneuvering through a trunk of wires with an iron. Fragile Multiple wires are often joined to a single pad. This requires the solder joint to be reheated/reflowed multiple times. A wire that pops loose would be difficult to reattach. Not worth reproducing It took about three days of soldering to get the computer connected. Repeating that task is not something I was looking forward to. The obvious solution is to make a PCB version of the board. It always seemed kind of silly to me to make a PCB version of a one-off project. But, it's either that or doing it all by hand again. So, after following along with the excellent KiCAD tutorials by Shawn Hymel, I set out to put the computer onto copper.  A tricky thing about computers of this era is managing the bus lines between devices. The most...