Bootstrappable language

Roger Ivie rivie at ridgenet.net
Thu Dec 11 02:40:12 CST 2008


On Thu, 11 Dec 2008, bfranchuk at jetnet.ab.ca wrote:
> I am still trying to figure out my word length here again.  I can do 18 bits 
> with CPLD's
> or 20 bits with  2901's now you got me thinking  of the overhead of  modern 
> logic.
> The architecture is the classic PDP 8 style design but with full alu ops 
> Add,sub,and,or,xor,ld,st.
> Immediate (#) instructions have been added so I have use  JZ,JNZ rather than 
> skips.
> I still think a tiny but full bootstrap[1] language could fit in 16 Kb of 
> memory as well as
> a limited assembler for the bootstrap language [2].

Don't count FORTH out.  I've done a simple FORTH on PDP-8. My particular 
implemenation is extremely portable, being expressed in terms of a four-level 
fixed-depth math stack. This is not the math stack seen by FORTH, but is used 
to construct the FORTH stack; the basic idea behind the four-level stack is
that it's used for working calculations much in the manner of an HP
calculator.

The FORTH system relies on a compiler crafted in C that builds the
headers and compiles the simple stack machine assembly. Over the years,
I've run the FORTH with 4-byte (VAX, i960), 2-byte (Z80), and 1-byte
(PDP-8) cells, all with no changes to the basic FORTH code. Except for
console terminal I/O and system startup, these systems have identical
source even for those words normally done in assembly, because those are
expressed in an assembly for the simple stack machine.

On the PDP-8, the implementation is almost a bytecode. Each simple stack
machine op compiles as a page-zero indirect jump through a word 
that holds a pointer to the implementing function.

For the simple stack-machine assembly, the basic rules are that the math
stack must be empty going into a branch or coming out of a label,
allowing the compiler to track the stack depth. For the PDP-8, the compiler 
selects one of four functions to execute the primitive based upon the current 
depth of the math stack. Other implementations compile to assembly for
the target processor, selecting the registers involved in each
instruction based on the stack depth.

On the PDP-8, the system requires approximately 3KW.

Oddly enough, I've just been resurrecting it for a new project. This
time, I have it compiling to a bytecode compiled with MACRO32 on an
Alpha; the difficulty with direct compilation on the Alpha is that the
MACRO32 compiler does not allow data and instructions to be mixed, which
I circumvent by compiling to a bytecode.

I had the following versions lying around:

The new Alpha bytecode version requires 1765 32-bit words for the FORTH
system compiled to bytecode and approximately 532 32-bit words for the
bytecode interpreter, for a total of about 2297 words. I just got this
version running today, so I know it works.

The PDP-8 system, described above, requires 3262 words for the
combination of FORTH code and primitive functions. This excludes space
required for the math and return stacks; I place them at opposite ends
of a chunk of memory growing towards each other.

The Z80 version is implemented in a manner similar to the PDP-8 version,
but subroutine calls require three bytes instead of the PDP-8's single
12-bit byte, so the code is a bit larger. It requires 4102 16-bit words.
This version has also been run.

I did, but did never debugged, a 68HC08 version. That one requires 2843
16-bit words for the combined system, but that does not include I/O
because I never got far enough in that project to wind up with target
hardware.

The PowerPC version compiles the simple stack-machine primitives to
PowerPC assembly. I don't think I ever ran that one, either. It requires
3973 32-bit words for the combined FORTH and primitives.

The VAX version also compiles to assembly code instead of bytecode. I've
run it both standalone on a MicroVAX 2000 and under my long-neglected
port of CP/M to that platform. It requires 2347 32-bit bit words for the
combined FORTH and primitives.

I also have an ARM version that compiles to assembly code, but has never
been executed; like the 68HC08 version, it has no I/O because I never
got far enough to have a concrete target. That version requires about
2287 32-bit words for the combined FORTH and primitives.

It is by no means a standard FORTH; it only has a couple of control
structures, all numeric console I/O is done in hex, and it can't do
inline string constants (i.e., no ." I have to declare a word containing
the constant instead and then compile a reference to that word).

Efficiency also was not a goal; the threaded code is
position-independent, which makes NEXT larger (a design goal for the
original i960 implementation was the ability to migrate the system from
ROM to RAM so the EPROM it was booted from could be erased and
re-programmed). The PDP-8 and Z-80 systems as a whole aren't position 
independent because the functions that implement the primitives aren't.

It's small, primitive, and portable. I'll be using it to bring up some
new hardware in the near future.
-- 
roger ivie
rivie at ridgenet.net



More information about the cctech mailing list