Still working on clarifying my use of PAD RAM and documenting things which has led to some circular activity where documenting caused understanding which caused code changes which etc... :-)
However as we are all keen on the 9900 architecture here I thought I would share a bit of innovation that the old girl allowed me to do in the CAMEL99 Forth implementation.
I can't think of another CPU where this would be possible.
I think I explained it well enough for those less familiar with Forth but ask questions if I failed.
CPU RAM PAD DETAIL
CAMEL99 makes special use of the small 256 byte RAM chip (PAD) that resides on the 16 bit buss. In this Forth system there are three separate uses of the “PAD” RAM:
1. Workspace: CPU registers 0 to 15
2. User Variables: A table of variables that are duplicated every time you create a new task.
3. CODE routines: This 16 bit memory is two times faster than expansion ram so putting some of the internal parts of Forth here make the system run about 20% faster.
User Area Description
User Variables were created in Forth to support multitasking. They create what is typically called a USER AREA, a block of memory that is unique to each Forth task running on the machine. In a typical Forth system the USER AREA may contain all the system variables needed by the Forth interpreter and the compiler, the I/O system and the DATA and RETURN stacks as well. Most Forth implementations must either allocate a register or create a memory location to be the USER Pointer (UP) that points to the USER AREA in memory, of the currently running task. The 9900 lets us do things differently…
No UP Register Required with the 9900
CAMEL99 Forth takes the 9900 “Workspace” concept one step further. Using to the TMS9900 Architecture, CAMEL99 has the CPU registers in the Workspace, as per normal, but then it also adds the USER VARIABLES immediately following the registers.
The 9900 internal Workspace register (WP) already points to a form of “user area” for the CPU registers. CAMEL99 simply expands the workspace to be 110 bytes rather than 32 bytes. The first 32 bytes are registers and the rest are USER VARIABLES. We are using the internal CPU Workspace pointer as a replacement for the normal “User Pointer” (UP) register in a conventional Forth implementation.
This means there is one less thing to change when we switch from task to task. In fact we context switch in CAMEL99 with one instruction: RTWP
In practical programmer terms this means that the USER VARIABLE list starts at >20 rather than 0. No big deal.
At runtime to access a USER VARIABLE we run three instructions:
(For the un-initiated Forth variables return a address and you must fetch the value from the address explicitly.
Ya I know it seems backwards. It's Forth. But what do you do in Assembler with a DATA address... )
\ The ‘W’ register points to the DATA field of the running Forth word
\ (in this case a user variable)
CODE: DOUSER ( -- addr)
TOS PUSH, \ make some space in the TOS register
TOS STWP, \ store workspace register WP in TOS
*W TOS ADD, \ add the offset stored in the USER variable
One Minor Caveat
The only problem we had to navigate was there are 3 CELLS right in the middle of our variables in PAD RAM that are used by the Device Service Routines. Not a problem!
We simply NEVER declare USER VARIABLES >54, >56 and >58.