Skip to content

sneakin/north-arm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nolan’s Forth for Linux on ARM processors.

Using only a shell (and Emacs and Qemu 🤫), statically and dynamically linked ELF files are built that can load an assembler and cross compiler to rebuild themselves.

Copyright (C) 2020-2024 Nolan Eakins, SemanticGap(TM). All rights reserved.

SemanticGap is a trademark of Nolan Eakins. All rights reserved.

Arm(R) is a registered trademark of Arm Limited (or its subsidaries) in the US and/or elsewhere. This program’s only association to Arm is that it executes on Arm processors.

Dependencies

Runtime

  • One of:
    • Termux on Android
    • GNU/Linux
  • Thumb capable ARM, with Thumb 2 preferred
    • Or qemu-arm.

Build

  • Bash but not 5.1.4 which has a memory leak.
  • Make
  • Git

Quick Start

Building with the shell script is quite slow. The prebuilt binaries under ./bootstrap/ can be used to skip steps.

make quick will copy bootstrap/interp.elf to bin/ but you may want one of:

./bootstrap/interp.static.elf
Only requires a Linux kernel, but can not load dynamic libraries.
./bootstrap/interp.android.elf
Is built to use Android’s dynamic linker.
./bootstrap/interp.gnueabi.elf
Is built to use the GNU dynamic linker found on desktops.

Termux may set $LD_PRELOAD which requires unsetting it: LD_PRELOAD='' ./bin/interp.elf

Building

All

I cheated: make is the preferred build tool. If you’re on a different architecture from your target, you will to set binfmt up to execute using Qemu.

The default task, make all, will use Bash to boot strap a static executable: bin/interp.elf.

Run the following to start the build on an X86-64 host, targeting a Thumb device with static linking:

make all HOST=x86_64-linux-static TARGET=thumb-linux-static

Be prepared to wait.

To skip the Bash build. use make quick or:

make all QUICK=1 HOST=x86_64-linux-static TARGET=thumb-linux-static

Stages

make targets will print a full list of HOST and TARGET strings, and to view information about the host and target there is make env.

bin/interp.elf will then be used to rebuild itself as bin/interp.${linker}.1.elf and bin/builder.${linker}.1.elf which then builds a dynamically linked versions with the 2.elf and 3.elf suffixes. ${linker} may be any or all of static, android, and gnueabi. The HOST, TARGET, OUT_TARGETS Make variables control and define the platform triples. STAGE controls what stage is building.

The build scripts / top level programs found in src/bin/ can be built by running make bin/${app}.elf. This build will be done with Bash. make bin/${app}.1.elf will use bin/interp.${linker}.${stage}.elf. The $stage can be changed to any value of 1, 2, and 3.

make boot will rebuild ./bootstrap/ from a clean clone of the repository.

Running

All executables built can be found in ./bin/.

Bash

./src/bash/forth.sh is Forth writen for Bash. It is used before any binary is available. ./bin/fforth is a shortcut capable of loading ./bin/fforth.dict for a fast initial state. make bin/fforth.dict will build that.

load-core will load the compiling words. This load step can be skipped by using ./bin/fforth after running make bin/fforth.dict.

Build scripts under src/bin/ can be cat into it and writen to a file: cat src/bin/interp.4th | ./src/bash/forth.sh > interp.elf

Boot strapped

This describes any of the ./bin/interp* executables. These will need Qemu or suitable emulator if compiled for a different platform.

A list of words can be printed with words. Compiling words with iwords.

Using

Loaders

Once running, various sets of functionality can be loaded with the following words:

load-core
Very essential functions mostly found in ./src/interp/boot/core.4th.
load-debug
Collection of value printers found in ./src/interp/boot/debug/.
load-thumb-asm
Words to assemble Thumb code and cross compile.
load-runner
Starts the self build of the ops needed for an interpreter.
load-interp
Loads the bare interpreter when building.

Demos

Command Line

src/bin/interp.4th
of course
src/bin/scanner.4th
Scans source files and has dictionaries for stats, highlighting in HTML, etc.

TTY

If https://github.com/sneakin/north has been cloned to ../north, the following demos can be loaded:

src/demos/tty/drawing.4th
exercises the drawing routines. Load and execute demo-tty-line, demo-tty-circle, demo-tty-ellipse, or demo-tty-blit.
src/demos/tty/clock.4th
has three clocks for the terminal: tty-raw-clock-loop, tty-buffer-clock, and tty-analog-clock. Each takes a timezone argument in the form of an offset in seconds.
src/demos/tty/raycast.4th
is ray caster like Wolfenstein 3d and Ken’s Labryinth. Load and execute raycaster-init. Then world0 to world9 are defined. raycaster-turn will render and interact one screen and input line at a time. raycaster-real uses epoll and threads for a bore interactive experience.

Programming

Binaries

Interpreting

./bin/interp.elf

Building binaries

./bin/builder.elf

Words

load
load/2
load-string

Documentation

( comments )

Definitions

defcol
exit
def
exit-frame
return
:
alias>
immediate

Conditions

IF
UNLESS
ELSE
THEN

Looping

loop
repeat-frame

Data

Words

literal
pointer

Numbers

Strings

s”
c”
d”
tmp”

Variables

var>
poke
peek

Constants

const>
string-const>
symbol>

Cross Compiling

:
defcol
def
defvar>
defconst>
cross-immediate
out-immediate
out’
out-off’