of816/docs/porting.md

168 lines
6.8 KiB
Markdown
Raw Normal View History

2019-07-01 17:33:44 +00:00
# Porting OF816
OF816's base system is usable either as a library of sorts or as the basis of a
port to a particular platform. The main build script in the root directory,
when given no platform argument, will create a forth.o in the same location that
may be linked at any address with ld65.
A specific platform may be supported by creating a platforms/<name> directory
and populating it. The best way to see how to do this is to examine the
existing ports.
## Linker/Segments
When creating a ld65 configuration file, the following segments must be
configured/placed:
* ZEROPAGE - a bss segment for the direct page. The system will initialize
this.
* FSystem - The main system. ROMable.
* FCode - Place as an optional segment. May be located in a separate bank.
ROMable.
Segments may *not* cross bank boundaries.
## Using as a "Library"
To use OF816 as a library, set your options in config.inc and run build.sh.
The resulting Forth.o may be linked as per above and placed in RAM or ROM.
Currently the beginning of the FSystem segment has a jump table with two entries
that may be called using JSL:
### FSystem+$0: ``_Forth_initialize``
This call initializes the Forth interpreter. This should be called with the
direct page register set to the address you wish the Forth interpreter to use.
The other registers need not contain any specific values.
The 65C816 stack should contain the following items when ``_Forth_initialize``
is called:
```
+--------- Top of Stack ----------+
| System Memory High | 32-bit
| System Memory Low | 32-bit
| Stack Top | 16-bit
| Stack Bottom | 16-bit
| Return Stk Top | 16-bit
| System Interface Function | 32-bit
-------- Bottom of Stack ---------+
```
System Memory High and Low define the data space used by Forth. This space must
be contiguous and may cross bank boundaries. The Low address points to the
first usable byte in data space, and the High address points to the byte
immediately after the last usable byte in data space.
The Stack Top and Stack bottom define the addresses of the Forth parameter stack
*relative to the direct page*. The stack grows downward as the 65C816 does, but
the stack pointer (X register) points to the first entry of the Forth stack
(rather than the first unused byte). The Top is the address immediately after
the first usable cell. The Bottom value is the address of the last usable cell.
Note this reverse of sense with regard to how items on the stack are referred.
The Return Stack Top is the address in Bank 0 that has the highest usable
address of the return stack to be used by Forth. Calls to Forth will save the
return stack pointer upon entry and restore it on exit.
To meet the standards to which OF816 strives for and prevent ``ENVIRONMENT?``
from lying, the parameter stack and return stack must be at least 64 cells in
size (256 bytes).
The System Interface Function is described in its own section, below.
The system does not use any absolute addresses (though platform ports might),
so it is entirely possible to initialize more than one Forth in a system. An
external task manager could multitask these, in theory. Subsequent calls to an
initialized Forth require only that the direct page be correctly set.
### FSystem+$3: ``_Forth_ui``
This should be called with the direct page set to the Forth direct page used
when ``_Forth_initialize`` was called. This function enters the outer
interpreter (the user interface of Forth) and does not return until ``BYE``
is executed.
## Using as a Port
The system may be specifically ported to a platform. This has the advantage of
allowing platform-specific words to be defined as well as providing a means to
initialize other parts of the system prior to initializing the Forth system.
The best way to see how to do a platform port is to examine the Apple IIgs and
W65C816SXB ports included with OF816.
Ports must still define their System Interface Function and use the jump table
described above, but the code may use internals of the Forth system for ease of
implementation and compactness.
## The System Interface Function
When ``_Forth_initialize`` is called, one of the parameters passed to it is the
System Interface Function. This function is used to allow for extra
initialization of the system as well as provide console and other services.
The System Interface Function is always called with the following:
* Called via JSL.
* Processor in native mode with long registers.
* Direct page and return stack pointers are the Forth system values.
* A register: Function code (values described below). Function codes < $8000
are reserved to be defined by the Forth system. Function codes >= $8000
may be defined by the platform port.
* X register: Forth stack pointer (relative to direct page). The Forth stack
consists of 32-bit cells and grows downward.
* Y register: Current depth of Forth stack.
The System Interface Function must exit with the following:
* Return via RTL, with the processor mode, direct page, and return stack
intact.
* Have the expected Forth parameter stack effects.
* The A and Y registers contain the high and low words of a throw code or zero
if successful.
* Carry set if an error occurred (``THROW`` will be executed in most cases).
* Carry clear if no error occurred.
### System Interface Function Codes
#### $0000 - Pre Initialize Platform ( -- )
This is called immediately before the inner interpreter is entered for the first
time for initialization, so that last-minute platform initialization may occur.
This routine is not checked for errors.
#### $0001 - Post Initialize Platform ( -- )
This is called immediately after the inner interpreter exits from
initialization, so that additional platform-specific initialization may occur.
This routine is not checked for errors.
#### $0002 - Emit Character ( char -- )
This routine should emit a the given character to the console output device.
#### $0003 - Input Ready Query ( -- f )
Return with f true (all bits set, typically) if there is a character ready to
be read from the console input device.
#### $0004 - Input Character ( -- char )
Recieve char from the console device, waiting for it to arrive.
#### $0005 - FCode List Pointer ( -- address ) currently not used
When the feature is implemented and FCode support is built assembled into the
Forth system, this function should return the address of one or more cells
containing the addresses of tokenized FCode to evaluate at initialization time,
or zero if there are none. The list should end with zeros.
For now, this should simply return 0.
#### $0006 - Reset-All ( -- ) reboot the system as if the power had been cycled
When this call is made, it should reset the system as if the power had been
recycled. If this is not possible for the platform, it should return an
exception code.