Hey Dr Jefyll, thanks for your intelligent questions re: Tiger, and bringing up the F-word:)
Tiger implements a 2-stack RPN machine with its meager 16 instructions, but not a true Forth machine which would require many more.
The d-stack is best understood as a hyper-accumulator, with the significance of the 4 members changing in accordance with the
sequential execution of each instruction per "Tiger_opcodes.v", which is the definitive reference published within the zipfile
in the prior related topic
viewtopic.php?f=15&t=661 (which you have renamed as the attachment
"Tiger_opcodes.txt" in your previous post).
One must understand all 16 of Tiger's instructions and the before -> after notation used to describe their behavior in order
to make sense of any example of code, or to write original code with any confidence.
The d-stack may be abused at the programmer's discretion (unlike Forth's obligation to balance the stack). On the other hand,
CPU logic will halt and light a dedicated LED in the event of a run-time p-stack error (too-many-call-levels or unbalanced-return).
See TigerCPU.v in the zipfile for the filthy details (Ctrl-f "sane").
Since Tiger lacks Forth stack-gymnastics instructions (except for the indispensable tt() (Forth dup)), named static variables
are used to buffer temporary data. In my opinion, clarity of expression benefits by avoiding the old shell game in the gnarly
parts of a non-trivial algorithm. In particular, I've been amazed how attempts to write "obviously-correct" code have worked
the first time even when I was a newbie programming this cub of my own creation. I hope that any valiant audience members will
enjoy similar success.
Constrained by the limit of no more than 4 d-stack members, one may write junk like:
Code:
...
lit(uart); ld(); tt(); tt() # -> keystroke keystroke keystroke
lit(tx); call() # echo
# resolve defined keystroke commands, drop through if undefined
lit(ord('h')); bxor(); lit(got_help); jz()
lit(ord('u')); bxor(); lit(got_unit_circle); jz()
...
The first line primes the d-stack with 3 copies of keystroke.
The second line lit nudges keystroke into the persistent realm that you have correctly surmised (i.e. the stickiness of d[3],
the bottom of the d-stack).
The fourth and subsequent lines rely on the persistence of a flooded d-stack.
I have no plans to expand the assembler with structured programming syntax nor even the most obvious/common macros (eg. lld(uart)).
I have done so in past projects, but not doing so with Tiger facilitates codespace/timing analysis and novel control structures
beyond the traditional.
The seeming lack of addressing modes beyond the nuisance of lit-direct is actually the freedom to synthesize whatever mode the
programmer deems to be valuable in a given scenario. For example, interpreters and state machines are easily implemented.
BTW, my local TigerSOC directory has progressed far beyond the original Dec 2019 zipfile, but I have not spammed the forum with an
update. If requested, I will share the current snapshot which has all kinds of tested goodies and improved documentation. The current
zipfile is just over 7 Mbytes, mostly due to the inclusion of SPI device datasheets in the doc directory.