How I actually extended Riscyforth

Before I suggested I was going to add dynamic linking by rolling on object files but that turned out to be pretty inflexible.

Then I thought I could pass needed initialisation values via use of the gp register (using it as a stack pointer). That actually seemed to work but it was pointed out to me that I could be taking a big gamble on what might happens when interrupts were called and I had a bogus value in that register.

The solution turned out to be quite simple – a very small shared library that is linked to both to the main executable and to the modules – I can even make it easy on myself and write it in C:

/** RISCYLIB                                            **/
/** Common code for Riscyforth and Riscyforth modules   **/
/** Copyright (C) Adrian McMenamin, 2022                **/
/** Licenced for reuse under the terms of v2 of GNU GPL **/

unsigned long nextAddress = 0;
unsigned long dictionaryAddress = 0;

unsigned long getNextAddress(void)
{
	return nextAddress;
}

void setNextAddress(unsigned long addressIn)
{
	nextAddress = addressIn;
}

unsigned long getDictionaryAddress(void)
{
	return dictionaryAddress;
}

void setDictionaryAddress(unsigned long addressIn)
{
	dictionaryAddress = addressIn;
}

This just providers getters and setters for two variables which are used to provide the address of the NEXT function (called by every Forth word at the end of execution) and to manage to end end of the dictionary (as we load modules we add their word definitions to the end of the dictionary).

Midnite Commander gives us some more information about the compiled libriscy.so:

Here dictionaryAddress and nextAddress symbols are marked as ‘B’ – ie in the BSS section, while the get and set functions/sysmpols are marked as T – ie in the “text”, or executable, section of the library.