Author: Virgil Dupras <email@example.com>
Date: Thu, 6 Apr 2023 09:58:09 -0400
HAL transition complete!
3 files changed, 28 insertions(+), 79 deletions(-)
diff --git a/README.md b/README.md
@@ -67,13 +67,19 @@ generated in the first place. This is so much simpler!
Object files? Global symbols? Nah. C functions that don't have a static storage
type are simple Forth words.
+### Harmonized Assembly Layer
+Dusk features what we call the [Harmonized Assembly Layer][hal] (HAL for short).
+This is a cross-CPU assembler, on which the C compiler relies, which prioritizes
+implementation and usage simplicity, but is also designed to generate efficient
### Shortest path to self-hosting for an "almost C" compiler
-Dusk OS self-hosts in about 1000 lines of assembly and a few hundred lines of
+Dusk OS self-hosts in about 800 lines of assembly and a few hundred lines of
Forth (the exact number depends on the target machine). From there, it
bootstraps to DuskCC, which is roughly 2000 lines of Forth code (including
-arch-specific backend and assembler). To my knowledge, Dusk OS is unique in
+arch-specific assemblers). To my knowledge, Dusk OS is unique in that regard.
You can pick any C compiler that requires POSIX and it will automatically
require order of magnitudes more lines of code to bootstrap because you need
@@ -266,6 +272,7 @@ Press Escape to return to prompt. You can try the same thing with:
diff --git a/fs/doc/stc.txt b/fs/doc/stc.txt
@@ -1,73 +0,0 @@
-# Dusk OS is a STC
-This Forth is a Subroutine Thread Code (STC) Forth, that is, each reference to
-words is a native call instead of being a reference. The drawback to this
-structure, compared to DTC or ITC forths (the ones with a "next" (not the "next"
-from iterators, the "core next of forth")), is significantly bigger binary size.
-It's also more complex to "disassemble" a compiled word. The upsides, however,
-are real juicy.
-First, there's speed. Calling words natively is faster than going through a
-Second, and most importantly, there's the ability for forth code to freely mix
-up with native code. That's huge and we use this extensively in Dusk through
-its "meta compilation" capabilities.
-## Meta compilation
-The vast majority of forths have the "compile" class of words. That's your
-grampa's compilation and it simply writes down a call to the specified word.
-Dusk kernels go further than that and allow the compilation of further native
-### Direct PS/RS control
-One of those constructs is direct control over the Parameter and Return Stacks.
-The "p+," compiles native code that grows or shrink PS by the specified number
-of bytes. "r+," does the same thing for RS.
-For example, here's the implementation of "drop" (from xcomp/bootlo.fs)
-code drop 4 p+, exit,
-Under a i386 kernel, this is the exact equivalent of writing "bp 4 i) add, ret,"
-In other words, meta compilation words in Dusk are a kind of limited portable
-assembler allowing you to sprinkle native code around.
-### The A register
-The "A" register is a (ideally) hardware register that helps making some memory-
-related operations less "PS-heavy". "A" is for "Address" and it will generally
-contain a memory address upon which it will work.
-Other forths have "A" registers, such as Collapse OS, and this register is
-generally directly used by the operator. Not here. The A register is extremely
-short-lived and will be written over all the time. Few words are guaranteed to
-preserve A, so you'll typically only use it in local, specific places. For
-example, ">r" uses the A register:
-: >r -4 r+, RSP>A, A!, ; immediate
-RSP>A, compiles native code that copies the RS pointer to the A register and A!,
-compiles native code that pops PS into the address contained in the A register.
-By the way, "A" words are "binary modulated", so "8b A!," will compile a native
-The A register generally saves us a roundtrip of the address to PS, resulting
-in considerable speedups. Let's use another example that illustrates it better:
-: value doer , immediate does> compiling if LIT>A, then toptr@ execute ;
-When we refer to a value in compile mode, we need to compile its address and
-then apply the appropriate "to" word (if any) to it. In "regular" forth, this
-would be implemented with "litn" followed by, for example, "!". This means that
-the address has to be pushed to PS and then popped again during !. With the A
-register, we save ourselves this roundtrip.
-This is a small gain, but it's a gain that we get in values, local variables and
-struct field access, so it adds up to nice sums.
-See "A register" section in doc/dict for a list of words.
diff --git a/fs/doc/usage.txt b/fs/doc/usage.txt
@@ -17,10 +17,24 @@ That being said, Dusk OS has some additional features that need explaining:
## Subroutine Threaded Code
This Forth is a Subroutine Thread Code (STC) Forth, that is, each reference to
-words is a native call instead of being a reference. This means that we don't
-have a "next" interpret loop. It's calls all the way down.
+words is a native call instead of being a reference. The drawback to this
+structure, compared to DTC or ITC forths (the ones with a "next" (not the "next"
+from iterators, the "core next of forth")), is significantly bigger binary size.
+It's also more complex to "disassemble" a compiled word. The upsides, however,
+are real juicy.
-See doc/stc for detailed information on what it implies.
+First, there's speed. Calling words natively is faster than going through a
+Second, and most importantly, there's the ability for forth code to freely mix
+up with native code. That's huge and we use this extensively in Dusk through
+its "meta compilation" capabilities, which is what the HAL is all about.
+## The HAL
+Dusk features a Harmonized Assembly Layer on which DuskCC relies and allows
+some really nice tricks. For regular usage, HAL knowledge isn't needed, so it's
+not covered here. You can read about it in doc/hal.
## Number literals
@@ -452,6 +466,7 @@ the interpreter, but you are hungry for more. What to read next?
* doc/sys/io is central to many, many things in Dusk.
* doc/sys/file lets you play with the filesystem.
* doc/lib/alloc covers dynamic memory allocation.
+* doc/hal covers the HAL on which the coolest Dusk features rely.
* doc/cc covers Dusk's central feature: its C compiler.
* doc/text/ed to edit text files.