You want to deploy Collapse OS on a new system? Read usage.txt,
impl.txt, cross.txt, then continue here.
What is Collapse OS? It is a binary placed either in ROM on
in RAM by a bootloader. That binary, when executed, initializes
itself to a Forth interpreter. In most cases, that Forth
interpreter will have some access to a mass storage device,
which allows it to access Collapse OS' disk blocks and bootstrap
itself some more.
This binary can be separated in 5 distinct layers:
1. Arch-specific boot code (B302 for Z80)
2. Arch-specific boot words (B304 for Z80)
3. Arch-independant core words (low) (B210)
4. Runtime HAL
5. Drivers, might contain arch-specific code
6. Arch-independant core words (high) (B226)
The boot code, which is arch-specific, contains these elements:
1. A jump to the early initialization routine
2. The stable ABI (see doc/impl.txt)
3. Core routines. At this point, lblnext, lblxt, lblcell,
lblpush and lbldoes are set.
4. The early initialization routines which initialized PSP and
RSP and then executed BOOT from its address in the stable
Then come the implementation of core Forth words in native
assembly. This is a limited set of words that implement core
operations. These words have to all be implemented in native
code because they're expected to be INLINE-able. The list of
boot words is:
QUIT ABORT BYE RCNT SCNT FIND * /MOD = TICKS (br) (?br) (loop)
C@ @ C! ! AND OR XOR 1+ 1- + - >> << >>8 <<8 I R> >R DUP DROP
SWAP OVER ROT ROT> >A A> A+ A-
On CPUs having ports, PC! and PC@ are also native.
Core words (low)
Then comes the part where we begin defining words in Forth.
Core words are designed to be cross-compiled (B200), from a
full Forth interpreter. This means that it has access to more
than boot words. This comes with tricky limitations.
Some of those words contain native code, but this code is always
cross-arch because it only uses INLINE-ed code mixed with HAL
ops. See doc/hal.txt
We usually want to include a runtime HAL in our binary so that
we can compile HAL code without needing to load the HAL first.
Many runtime applications (it's actually not true at the time
of this writing, but will soon be) have HAL optimizations, so
they need a HAL to be loaded.
Core words don't include (key) and (emit) implementations be-
cause that's hardware-dependant. This is where we need to load
code that implement it, as well as any other driver code we want
to include in the binary. This includes subsystems.
We do it now because if we wait until the high layer of core
words is loaded, we'll have messed up immediates and ":" will
be broken. If we load our code before, we won't have access to
a wide vocabulary.
See doc/drivers for more details.
Core words (high)
The final layer of core words contains the BOOT word as well
as tricky immediates which, if they're defined sooner, mess
cross compilation up. Once this layer is loaded, we become
severly limited in the words we can use without messing up.
So that's the anatomy of a Collapse OS binary. How do you build
one? If your machine is already covered by a recipe, you're in
luck: follow instructions.
If you're deploying to a new machine, you'll have to write a
new xcomp (cross compilation) unit. Let's look at its
anatomy. First, we have constants. Some of them are device-
specific, but some of them are always there. SYSVARS is the
address at which the RAM starts on the system. System variables
will go there and use $80 bytes. See impl.txt.
HERESTART determines where... HERE is at startup. 0 means
"same as CURRENT".
RS_ADDR is where RSP starts and PS_ADDR is where PSP starts.
RSP and PSP are designed to be contiguous. RSP goes up and PSP
goes down. If they meet, we know we have a stack overflow.
Then comes time time to load the blocks that will compile the
thing. Order is important.
First come the assembler (example, Z80A). There are core loader
words for all supported assemblers.
Then comes XCOMPL (xcomp "low"), which is the early part of the
xcomp toolkit and doesn't override important words. So, at this
point, we're still in "host" mode. What we need in XCOMPL are
all xcomp-related loader words such as Z80M, Z80C, etc.
Then comes CPU-specific macros, constants further loader words
such as the "H" and "C" units. They always live in B301 (see
doc/blk.txt). So, "301 LOAD". It's important that it's loaded
before XCOMPH because it's being executed during xcomp, not
included in the target binary.
The comes the CPU-specific HAL, the "H" unit (example: Z80H).
This comes before XCOMPH, will override the host's "native"
HAL. This is not the runtime HAL.
Now comes the real deal: XCOMPH. It's the "high" part of xcomp
and from this point on, we're in "target" mode. Everything we
define ends up in the target binary (see doc/cross.txt).
The first unit that comes after this is the "C" unit (example:
Z80C). "C" is for "code". It's the layers 1 and 2 from the layer
list at the top of this document.
We're done with the CPU-specific part! Now comes COREL, for
"core words (low)".
At this point, things are weird: we load the target's HAL again!
that's because this time, it's the runtime HAL.
Then comes the custom part: drivers and subsystems. This part
is heavily dependant on the target system and varies a lot.
After that, you need to define a INIT word. This will be called
by BOOT right before spitting the prompt. This is usually used
to call init words of all subsystems.
All xcomp unit end with XWRAP, a helper word that loads "high"
core words and then wrap things up (set CURRENT and LATEST in
the stable ABI). You're done!
To produce a Collapse OS binary, you run that xcomp unit and
then observe the values of ORG and HERE. That will give you
the start and stop offset of your binary, which you can then
copy to your target media.
This page generated at 2022-01-16 21:05:03 from documentation in CollapseOS snapshot 20220115.