*
***************************************************************************/
-// The order matches the execN function and determines the opcode value.
+// The order matches the execVM function and determines the opcode value.
// NOTE: must end in a space !!!!
const uint8_t cmdListBi[] = {
"bye + - * /% " // 1 -> 5
20014, // 1 gw get word
20030, // 2 num test if number
20022,10008, // 3 if
-
+
20031, // 5 push0 push a zero on math stack
20032,10030, // 6 goto jump to until function
20008, // 8 drop
20034, // 9 lu look up word
20022,10026, // 10 if did we find the word in the dictionary
-
+
20035,']', // 12 pushn next value on math stack look for ]
20036, // 14 over
20022,10022, // 16 if
20008, // 18 drop it was the ']' exit function
- 20037, // 19 push1 put a true on the math stack
+ 20037, // 19 push1 put a true on the math stack
20032,10030, // 20 goto jump to until func
20033, // 22 exec execute the function on the math stack (it is a call so we return to here)
20031, // 23 push0
20032,10030, // 24 goto jump to until func
-
+
// undefined string
-
+
20035,'?', // 26 pushn put the '?' on math stack
20039, // 28 emit output the ? to the terminal
20031, // 29 push0
-
+
20026, // 30 until
- 20040, // 31 return function
+ 20040, // 31 return function
// this is the ':' function hand compiled
-
+
20035,0x5555, // 32 just push a known value on the stack, will test at the end
20014, // 34 get a word from the input
20015, // 35 define it
20025, // 36 begin
- 20014, // 37 get a word
+ 20014, // 37 get a word
20030, // 38 see if number
20022,10047, // 39 if
-
+
// it is a number
-
+
20035,20035, // 41 put the push next number opcode on stack
20017, // 43 put that opcode in the def
20017, // 44 put the actual value next
20031, // 45 push 0
20026, // 46 until // we can have many untils for one begin
-
+
// wasn't a number, we need to test for many other things
- 20008, // 47 drop
+ 20008, // 47 drop
20034, // 48 look in dictionary
20020, // 49 not
20038, // 55 tell them what we couldn't find
20031, // 56 push0
20026, // 57 until
-
+
// we found it in the dictionary
-
+
20035,20022, // 58 pushn see if it is an if function
20036, // 60 over
20012, // 61 equal
20022,10070, // 62 if
-
+
// it is an if function
20017, // 64 append the if statement to the stack (it was still on the stack
20017, // 67 append it to memory
20031, // 68 push0
20026, // 69 until
-
- // **********************
-
+
+ // **********************
+
20035,20024, // 70 pushn see if it is an "else" function
20036, // 72 over
20012, // 73 equal
20022,10088, // 74 if
-
+
// it is an "else" statement
-
+
20035,20032, // 76 push a goto command on the math stack
20017, // 78 append it to the program
20043, // 79 h@ get location of next free word
20019, // 85 ! this will be in prog space
20031, // 86 push0
20026, // 87 until
-
- // *******************************
+
+ // *******************************
20035,20023, // 88 pushn see if it is a "then" function
20019, // 97 !
20031, // 98 push0
20026, // 99 until
-
+
// *********************************
-
+
20035,10001, // 100 pushn see if it is a "[" function
20036, // 102 over
- 20012, // 103 equal
+ 20012, // 103 equal
20022,10109, // 104 if
// it is a "["
-
+
10001, // 106 recurse into the monitor
20031, // 107 push0
20026, // 108 until
-
- // ********************************************
-
+
+ // ********************************************
+
20035,20040, // 109 pushn next value on math stack look for built in func ';'
20036, // 111 over
20012, // 112 equal test if function was a ';'
20020, // 113 not
- 20022,10119, // 114 if
+ 20022,10119, // 114 if
// this must be just an ordinary function ..... just push it in the prog
- 20017, // 116 append
+ 20017, // 116 append
20031, // 117 push0
20026, // 118 until
-
+
// must be the ';'
20017, // 119 append return function to prog
20012, // 122 equal
20020, // 123 not
20022,10132, // 124 if
-
+
20035,'?', // 126 push a '?' on the stack
20039, // 128 emit
20035,'s', // 129 push a 's' on the stack
// ***********************************************
// var create a variable
-
+
20043, // 135 get address of variable
20031, // 136 push0
20017, // 137 append ","
-
+
20014, // 138 get a word from the input
20015, // 139 define it
20035,20035, // 140 put the push next number opcode on stack
- 20017, // 142 append the pushn instruction
+ 20017, // 142 append the pushn instruction
20017, // 143 append the address we want to push
20035,20040, // 144 put a return instruction on stack
20017, // 146 put the return instruction in prog
20040, // 147 return
-
- };
+
+ };
*
* Local function prototypes
*
+ * xFunc() are closely related to opcodes
+ *
+ * Note: push/pop and such may be candidates for making non-static (public)
+ ***************************************************************************/
+/****************************************************************************
+ * Stack implementation
+ ***************************************************************************/
+static void pushMathStack(int16_t n);
+static int16_t popMathStack(void);
+static void ndrop(int16_t n);
+
+static void pushAddrStack(int16_t n);
+static int16_t popAddrStack(void);
+static void ndropAddr(int16_t n);
+
+/****************************************************************************
+ * Line input handling
***************************************************************************/
+static uint8_t getKeyB(void);
+static void getLine(void);
+static uint8_t nextPrintableChar(void);
+static uint8_t skipStackComment(void);
-uint8_t getKeyB(void);
-void getLine(void);
-uint8_t nextPrintableChar(void);
-uint8_t skipStackComment(void);
-void getWord(void);
-void listFunction(void);
-int16_t popMathStack(void);
-void pushMathStack(int16_t n);
-void ndrop(int16_t n);
-int16_t popAddrStack(void);
-void pushAddrStack(int16_t n);
-void ndropAddr(int16_t n);
-int16_t lookupToken(uint8_t *x, uint8_t *l);
-void luFunc(void);
-void opcode2wordFunc(void);
-void opcode2progFunc(void);
-void numFunc(void);
-void ifFunc(int16_t x);
-void loopFunc(int16_t n);
-void rollFunc(int16_t n);
-void pushnFunc(void);
-void dfnFunc(void);
-void printNumber(int16_t n);
-void printHexChar(int16_t n);
-void printHexByte(int16_t n);
-void printHexWord(int16_t n);
-void execN(int16_t n);
-void execFunc(void);
+/****************************************************************************
+ * Word buffer usage
+ ***************************************************************************/
+static int16_t lookupToken(uint8_t *x, uint8_t *l);
+static void dfnFunc(void);
+static void getWordFunc(void);
+static void luFunc(void);
+static void numFunc(void);
+/****************************************************************************
+ * Terminal output effects
+ ***************************************************************************/
+static void printNumber(int16_t n);
+static void printHexChar(int16_t n);
+static void printHexByte(int16_t n);
+static void printHexWord(int16_t n);
+static void listFunc(void);
+static void opcode2wordFunc(void);
+/****************************************************************************
+ * Other helpers
+ ***************************************************************************/
+static void execFunc(void);
+static void ifFunc(int16_t x);
+static void loopFunc(int16_t n);
+static void opcode2progFunc(void);
+static void pushnFunc(void);
+static void rollFunc(int16_t n);
/****************************************************************************
- *
- * Public functions
- *
+ * VM opcode execution
***************************************************************************/
+static void execVM(int16_t opcode);
-void msp4th_init(struct msp4th_config *c)
+
+
+/****************************************************************************
+ * Stack implementation
+ ***************************************************************************/
+#define TOS (*mathStackPtr)
+#define NOS (*(mathStackPtr + 1))
+#define STACK(n) (*(mathStackPtr + n))
+
+void pushMathStack(int16_t n)
{
- /*
- * Get addresses of user-configurable arrays from the pre-known vector
- * table locations.
- *
- * Changing the values in the msp4th_* locations and calling
- * msp4th_init() again restarts the interpreter with the new layout;
- */
- mathStackPtr = c->mathStackStart;
- addrStackPtr = c->addrStackStart;
- mathStackStart = c->mathStackStart;
- addrStackStart = c->addrStackStart;
- prog = c->prog;
- progOpcodes = c->progOpcodes;
- cmdList = c->cmdList;
- lineBuffer = c->lineBuffer;
- lineBufferLength = c->lineBufferLength;
- wordBuffer = c->wordBuffer;
- wordBufferLength = c->wordBufferLength;
- msp4th_putchar = c->putchar;
- msp4th_getchar = c->getchar;
- msp4th_puts = c->puts;
+#if defined(MSP430)
+ asm("decd %[ms]\n"
+ "mov %[n], @%[mso]\n"
+ : /* outputs */ [mso] "+r" (mathStackPtr)
+ : /* inputs */ [n] "r" (n), [ms] "r" (mathStackPtr)
+ : /* clobbers */
+ );
+#else
+ mathStackPtr--;
+ *mathStackPtr = n;
+#endif
+}
- xit = 0;
- echo = 1;
- progCounter = BUILTIN_INTERP_OFFSET;
- progIdx = 1; // this will be the first opcode
- cmdListIdx = 0;
+int16_t popMathStack(void)
+{
+ int16_t i;
- lineBufferIdx = 0;
- msp4th_puts((uint8_t *)"msp4th!");
+ i = *mathStackPtr;
+
+ // prevent stack under-flow
+ if (mathStackPtr < mathStackStart) {
+ mathStackPtr++;
+ }
+
+ return(i);
}
-void msp4th_processLoop(void) // this processes the forth opcodes.
+void ndrop(int16_t n)
{
- uint16_t opcode;
- uint16_t tmp;
+ mathStackPtr += n;
- while(xit == 0){
- if(progCounter >= BUILTIN_INTERP_OFFSET){
- tmp = progCounter - BUILTIN_INTERP_OFFSET;
- opcode = progBi[tmp];
- } else {
- opcode = prog[progCounter];
- }
+ if (mathStackPtr > mathStackStart) {
+ mathStackPtr = mathStackStart;
+ }
+}
- progCounter = progCounter + 1;
- if(opcode >= BUILTIN_OPCODE_OFFSET){
- // this is a built in opcode
- execN(opcode - BUILTIN_OPCODE_OFFSET);
- } else {
- pushAddrStack(progCounter);
- progCounter = progOpcodes[opcode];
- }
- } // while ()
+#define ATOS (*addrStackPtr)
+#define ANOS (*(addrStackPtr + 1))
+#define ASTACK(n) (*(addrStackPtr + n))
+
+void pushAddrStack(int16_t n)
+{
+#if defined(MSP430)
+ asm("decd %[as]\n"
+ "mov %[n], @%[aso]\n"
+ : /* outputs */ [aso] "+r" (addrStackPtr)
+ : /* inputs */ [n] "r" (n), [as] "r" (addrStackPtr)
+ : /* clobbers */
+ );
+#else
+ addrStackPtr--;
+ *addrStackPtr = n;
+#endif
+}
+
+
+int16_t popAddrStack(void)
+{
+ int16_t i;
+
+#if defined(MSP430)
+ asm("mov @%[as], %[out]\n"
+ "incd %[aso]\n"
+ : /* outputs */ [out] "=r" (i), [aso] "+r" (addrStackPtr)
+ : /* inputs */ [as] "r" (addrStackPtr)
+ : /* clobbers */
+ );
+#else
+ i = *addrStackPtr;
+ addrStackPtr++;
+#endif
+
+ return(i);
}
+void ndropAddr(int16_t n)
+{
+ addrStackPtr += n;
+}
+
/****************************************************************************
- *
- * The rest of the implementation
- *
+ * Line input handling
***************************************************************************/
-
uint8_t getKeyB(void)
{
uint8_t c;
}
-void getWord(void)
+/****************************************************************************
+ * Word buffer usage
+ ***************************************************************************/
+int16_t lookupToken(uint8_t *word, uint8_t *list)
+{
+ // looking for word in list
+ // Matches FIRST OCCURENCE of word in list
+
+ int16_t i;
+ int16_t j;
+ int16_t k;
+ int16_t n;
+
+ i = 0;
+ j = 0;
+ k = 0;
+ n = 1;
+
+ while (list[i] != 0) {
+ if ((word[j] != 0) && (list[i] == word[j])) {
+ // keep matching
+ j++;
+ } else if ((word[j] == 0) && (list[i] == ' ')){
+ // end of word, match iff it's the end of the list item
+ k = n;
+ //just break the while early
+ break;
+ } else {
+ j = 0;
+ n++;
+ while (list[i] > ' ') {
+ i++;
+ }
+ }
+
+ i++;
+ }
+
+ return(k);
+}
+
+
+void dfnFunc(void)
+{
+ // this function adds a new def to the list and creates a new opcode
+
+ uint16_t i;
+
+ i = 0;
+
+ while (wordBuffer[i]) {
+ cmdList[cmdListIdx++] = wordBuffer[i];
+ i = i + 1;
+ }
+
+ cmdList[cmdListIdx++] = ' ';
+ cmdList[cmdListIdx] = 0;
+ i = lookupToken(wordBuffer, cmdList);
+ progOpcodes[i] = progIdx;
+}
+
+
+void getWordFunc(void)
{
int16_t k;
uint8_t c;
}
-void listFunction(void)
-{
- msp4th_puts((uint8_t *)cmdListBi);
- msp4th_puts((uint8_t *)cmdListBi2);
- msp4th_puts(cmdList);
-}
-
-
-#define TOS (*mathStackPtr)
-#define NOS (*(mathStackPtr + 1))
-#define STACK(n) (*(mathStackPtr + n))
-
-int16_t popMathStack(void)
+void luFunc(void)
{
- int16_t i;
-
- i = *mathStackPtr;
+ int16_t opcode;
- // prevent stack under-flow
- if (mathStackPtr < mathStackStart) {
- mathStackPtr++;
- }
-
- return(i);
-}
-
-
-void pushMathStack(int16_t n)
-{
-#if defined(MSP430)
- asm("decd %[ms]\n"
- "mov %[n], @%[mso]\n"
- : /* outputs */ [mso] "+r" (mathStackPtr)
- : /* inputs */ [n] "r" (n), [ms] "r" (mathStackPtr)
- : /* clobbers */
- );
-#else
- mathStackPtr--;
- *mathStackPtr = n;
-#endif
-}
-
-
-void ndrop(int16_t n)
-{
- mathStackPtr += n;
-
- if (mathStackPtr > mathStackStart) {
- mathStackPtr = mathStackStart;
- }
-}
-
-
-#define ATOS (*addrStackPtr)
-#define ANOS (*(addrStackPtr + 1))
-#define ASTACK(n) (*(addrStackPtr + n))
-
-int16_t popAddrStack(void)
-{
- int16_t i;
-
-#if defined(MSP430)
- asm("mov @%[as], %[out]\n"
- "incd %[aso]\n"
- : /* outputs */ [out] "=r" (i), [aso] "+r" (addrStackPtr)
- : /* inputs */ [as] "r" (addrStackPtr)
- : /* clobbers */
- );
-#else
- i = *addrStackPtr;
- addrStackPtr++;
-#endif
-
- return(i);
-}
-
-
-void pushAddrStack(int16_t n)
-{
-#if defined(MSP430)
- asm("decd %[as]\n"
- "mov %[n], @%[aso]\n"
- : /* outputs */ [aso] "+r" (addrStackPtr)
- : /* inputs */ [n] "r" (n), [as] "r" (addrStackPtr)
- : /* clobbers */
- );
-#else
- addrStackPtr--;
- *addrStackPtr = n;
-#endif
-}
-
-
-void ndropAddr(int16_t n)
-{
- addrStackPtr += n;
-}
-
-
-int16_t lookupToken(uint8_t *word, uint8_t *list)
-{
- // looking for word in list
- // Matches FIRST OCCURENCE of word in list
-
- int16_t i;
- int16_t j;
- int16_t k;
- int16_t n;
-
- i = 0;
- j = 0;
- k = 0;
- n = 1;
-
- while (list[i] != 0) {
- if ((word[j] != 0) && (list[i] == word[j])) {
- // keep matching
- j++;
- } else if ((word[j] == 0) && (list[i] == ' ')){
- // end of word, match iff it's the end of the list item
- k = n;
- //just break the while early
- break;
- } else {
- j = 0;
- n++;
- while (list[i] > ' ') {
- i++;
- }
- }
-
- i++;
- }
-
- return(k);
-}
-
-
-void luFunc(void)
-{
- int16_t opcode;
-
- opcode = lookupToken(wordBuffer, (uint8_t *)cmdListBi);
+ opcode = lookupToken(wordBuffer, (uint8_t *)cmdListBi);
if (opcode) {
opcode += BUILTIN_OPCODE_OFFSET;
}
-void opcode2wordFunc(void)
-{
- // given an opcode, print corresponding ASCII word name
-
- int16_t n;
- int16_t opcode;
- uint8_t *list;
-
- n = 1; // opcode indices are 1-based
- opcode = popMathStack();
-
- // where is the opcode defined?
- // remove offset
- if (opcode >= BUILTIN_OPCODE_OFFSET) {
- list = (uint8_t *)cmdListBi;
- opcode -= BUILTIN_OPCODE_OFFSET;
- } else if (opcode >= BUILTIN_INTERP_OFFSET) {
- list = (uint8_t *)cmdListBi2;
- opcode -= BUILTIN_INTERP_OFFSET;
- } else {
- list = cmdList;
- }
-
- // walk list to get word
- // skip to start of the expected location
- while (n < opcode) {
- while (*list > ' ') {
- list++;
- }
- list++;
- n++;
- }
-
- if (*list != 0) {
- // not end of list, print next word
- while (*list > ' ') {
- msp4th_putchar(*list++);
- }
- } else {
- msp4th_putchar('?');
- }
-
- msp4th_putchar(' ');
-}
-
-
-void opcode2progFunc(void)
-{
- // given an opcode, get the start index of prog of it's definition
-
- if (TOS >= BUILTIN_INTERP_OFFSET) {
- // catches both OPCODE and INTERP_OFFSET
- TOS = 0;
- } else {
- TOS = progOpcodes[TOS];
- }
-}
-
-
void numFunc(void)
{
// the word to test is in wordBuffer
}
if ((wordBuffer[i] >= '0') && (wordBuffer[i] <= '9')) {
- // it is a number
+ // it is a number
isnum = 1;
// check if hex
if (wordBuffer[0] == '0' && wordBuffer[1] == 'x') {
}
-void ifFunc(int16_t x){
- // used as goto if x == 1
-
- uint16_t addr;
- uint16_t tmp;
+/****************************************************************************
+ * Terminal output effects
+ ***************************************************************************/
+void printNumber(register int16_t n)
+{
+ uint16_t nu;
int16_t i;
+ int16_t rem;
+ uint8_t x[7];
- if(progCounter >= BUILTIN_INTERP_OFFSET){
- tmp = progCounter - BUILTIN_INTERP_OFFSET;
- addr = progBi[tmp];
+ if (n < 0) {
+ msp4th_putchar('-');
+ nu = -n;
} else {
- addr = prog[progCounter];
+ nu = n;
}
- progCounter++;
+ i = 0;
+ do {
+ rem = nu % 10;
+ x[i] = (uint8_t)rem + (uint8_t)'0';
+ nu = nu / 10;
+ i = i + 1;
+ } while((nu != 0) && (i < 7));
- if (x == 1) {
- // this is a goto
- progCounter = addr;
- } else {
- // this is the "if" processing
- i = popMathStack();
- if(i == 0){
- progCounter = addr;
- }
- }
+ do{
+ i = i - 1;
+ msp4th_putchar(x[i]);
+ } while (i > 0);
+
+ msp4th_putchar(' ');
}
-void loopFunc(int16_t n)
+void printHexChar(int16_t n)
{
-#define j ATOS // loop address
-#define k ANOS // count
-#define m ASTACK(2) // limit
-
- k += n; // inc/dec the count
+ n &= 0x0F;
- if (((n > 0) && (k < m)) || ((n < 0) && (k > m))) {
- // loop
- progCounter = j;
- } else {
- // done, cleanup
- ndropAddr(3);
+ if (n > 9) {
+ n += 7;
}
-#undef j
-#undef k
-#undef m
+
+ n += '0';
+ msp4th_putchar(n);
}
-void rollFunc(int16_t n)
+void printHexByte(int16_t n)
{
- int16_t *addr;
- int16_t tmp;
+ printHexChar(n >> 4);
+ printHexChar(n);
+}
- tmp = STACK(n);
- addr = (mathStackPtr + n);
- while (addr > mathStackPtr) {
- *addr = *(addr - 1);
- addr--;
- }
+void printHexWord(int16_t n)
+{
+ // suppress sign bit extension
+ printHexByte((uint16_t)n >> 8);
+ printHexByte(n);
+}
- TOS = tmp;
+
+void listFunc(void)
+{
+ msp4th_puts((uint8_t *)cmdListBi);
+ msp4th_puts((uint8_t *)cmdListBi2);
+ msp4th_puts(cmdList);
}
-void pushnFunc(void)
+void opcode2wordFunc(void)
{
- int16_t i;
+ // given an opcode, print corresponding ASCII word name
- if (progCounter >= BUILTIN_INTERP_OFFSET) {
- i = progBi[progCounter - BUILTIN_INTERP_OFFSET];
+ int16_t n;
+ int16_t opcode;
+ uint8_t *list;
+
+ n = 1; // opcode indices are 1-based
+ opcode = popMathStack();
+
+ // where is the opcode defined?
+ // remove offset
+ if (opcode >= BUILTIN_OPCODE_OFFSET) {
+ list = (uint8_t *)cmdListBi;
+ opcode -= BUILTIN_OPCODE_OFFSET;
+ } else if (opcode >= BUILTIN_INTERP_OFFSET) {
+ list = (uint8_t *)cmdListBi2;
+ opcode -= BUILTIN_INTERP_OFFSET;
} else {
- i = prog[progCounter];
+ list = cmdList;
}
- progCounter = progCounter + 1;
- pushMathStack(i);
-}
+ // walk list to get word
+ // skip to start of the expected location
+ while (n < opcode) {
+ while (*list > ' ') {
+ list++;
+ }
+ list++;
+ n++;
+ }
+
+ if (*list != 0) {
+ // not end of list, print next word
+ while (*list > ' ') {
+ msp4th_putchar(*list++);
+ }
+ } else {
+ msp4th_putchar('?');
+ }
+ msp4th_putchar(' ');
+}
-void dfnFunc(void)
-{
- // this function adds a new def to the list and creates a new opcode
- uint16_t i;
+/****************************************************************************
+ * Other helpers
+ ***************************************************************************/
+void execFunc(void) {
+ int16_t opcode;
- i = 0;
+ opcode = popMathStack();
- while (wordBuffer[i]) {
- cmdList[cmdListIdx++] = wordBuffer[i];
- i = i + 1;
+ if (opcode >= BUILTIN_OPCODE_OFFSET) {
+ // this is a built in opcode
+ execVM(opcode - BUILTIN_OPCODE_OFFSET);
+ } else if (opcode >= BUILTIN_INTERP_OFFSET) {
+ // built in interp
+ pushAddrStack(progCounter);
+ progCounter = cmdList2N[opcode - BUILTIN_INTERP_OFFSET];
+ } else {
+ pushAddrStack(progCounter);
+ progCounter = progOpcodes[opcode];
}
-
- cmdList[cmdListIdx++] = ' ';
- cmdList[cmdListIdx] = 0;
- i = lookupToken(wordBuffer, cmdList);
- progOpcodes[i] = progIdx;
}
-void printNumber(register int16_t n)
-{
- uint16_t nu;
+void ifFunc(int16_t x){
+ // used as goto if x == 1
+
+ uint16_t addr;
+ uint16_t tmp;
int16_t i;
- int16_t rem;
- uint8_t x[7];
- if (n < 0) {
- msp4th_putchar('-');
- nu = -n;
+ if(progCounter >= BUILTIN_INTERP_OFFSET){
+ tmp = progCounter - BUILTIN_INTERP_OFFSET;
+ addr = progBi[tmp];
} else {
- nu = n;
+ addr = prog[progCounter];
}
- i = 0;
- do {
- rem = nu % 10;
- x[i] = (uint8_t)rem + (uint8_t)'0';
- nu = nu / 10;
- i = i + 1;
- } while((nu != 0) && (i < 7));
-
- do{
- i = i - 1;
- msp4th_putchar(x[i]);
- } while (i > 0);
+ progCounter++;
- msp4th_putchar(' ');
+ if (x == 1) {
+ // this is a goto
+ progCounter = addr;
+ } else {
+ // this is the "if" processing
+ i = popMathStack();
+ if(i == 0){
+ progCounter = addr;
+ }
+ }
}
-void printHexChar(int16_t n)
+void loopFunc(int16_t n)
{
- n &= 0x0F;
+#define j ATOS // loop address
+#define k ANOS // count
+#define m ASTACK(2) // limit
- if (n > 9) {
- n += 7;
- }
+ k += n; // inc/dec the count
- n += '0';
- msp4th_putchar(n);
+ if (((n > 0) && (k < m)) || ((n < 0) && (k > m))) {
+ // loop
+ progCounter = j;
+ } else {
+ // done, cleanup
+ ndropAddr(3);
+ }
+#undef j
+#undef k
+#undef m
}
-void printHexByte(int16_t n)
+void opcode2progFunc(void)
{
- printHexChar(n >> 4);
- printHexChar(n);
+ // given an opcode, get the start index of prog of it's definition
+
+ if (TOS >= BUILTIN_INTERP_OFFSET) {
+ // catches both OPCODE and INTERP_OFFSET
+ TOS = 0;
+ } else {
+ TOS = progOpcodes[TOS];
+ }
}
-void printHexWord(int16_t n)
+void pushnFunc(void)
{
- // suppress sign bit extension
- printHexByte((uint16_t)n >> 8);
- printHexByte(n);
+ int16_t i;
+
+ if (progCounter >= BUILTIN_INTERP_OFFSET) {
+ i = progBi[progCounter - BUILTIN_INTERP_OFFSET];
+ } else {
+ i = prog[progCounter];
+ }
+
+ progCounter = progCounter + 1;
+ pushMathStack(i);
}
-void execFunc(void) {
- int16_t opcode;
+void rollFunc(int16_t n)
+{
+ int16_t *addr;
+ int16_t tmp;
- opcode = popMathStack();
+ tmp = STACK(n);
+ addr = (mathStackPtr + n);
- if (opcode >= BUILTIN_OPCODE_OFFSET) {
- // this is a built in opcode
- execN(opcode - BUILTIN_OPCODE_OFFSET);
- } else if (opcode >= BUILTIN_INTERP_OFFSET) {
- // built in interp
- pushAddrStack(progCounter);
- progCounter = cmdList2N[opcode - BUILTIN_INTERP_OFFSET];
- } else {
- pushAddrStack(progCounter);
- progCounter = progOpcodes[opcode];
+ while (addr > mathStackPtr) {
+ *addr = *(addr - 1);
+ addr--;
}
+
+ TOS = tmp;
}
-void execN(int16_t opcode)
+/****************************************************************************
+ *
+ * VM opcode execution
+ *
+ ***************************************************************************/
+void execVM(int16_t opcode)
{
- int16_t i,j,k,m,n;
- int32_t x;
+ int16_t i,j,k,m,n;
+ int32_t x;
- switch(opcode){
- case 0: // unused
- break;
+ switch(opcode){
+ case 0: // unused
+ break;
- case 1: // bye
- xit = 1;
- break;
+ case 1: // bye
+ xit = 1;
+ break;
- case 2: // + ( a b -- a+b )
- NOS += TOS;
- popMathStack();
- break;
+ case 2: // + ( a b -- a+b )
+ NOS += TOS;
+ popMathStack();
+ break;
- case 3: // - ( a b -- a-b )
- NOS += -TOS;
- popMathStack();
- break;
+ case 3: // - ( a b -- a-b )
+ NOS += -TOS;
+ popMathStack();
+ break;
- case 4: // * ( a b -- reshi reslo )
+ case 4: // * ( a b -- reshi reslo )
#if defined(MSP430)
- asm("dint");
- MPYS = NOS;
- OP2 = TOS;
- NOS = RESHI;
- TOS = RESLO;
- asm("eint");
+ asm("dint");
+ MPYS = NOS;
+ OP2 = TOS;
+ NOS = RESHI;
+ TOS = RESLO;
+ asm("eint");
#else
- x = TOS * NOS;
- NOS = (int16_t)((x >> 16) & 0xffff);
- TOS = (int16_t)(x & 0xffff);
+ x = TOS * NOS;
+ NOS = (int16_t)((x >> 16) & 0xffff);
+ TOS = (int16_t)(x & 0xffff);
#endif
- break;
+ break;
- case 5: // /% ( a b -- a/b a%b )
+ case 5: // /% ( a b -- a/b a%b )
#if defined(MSP430)
- /* directly call divmodhi4, gcc calls it twice even though the fn returns
- * both values in one call */
- asm("mov 2(%[ms]), r12\n"
- "mov 0(%[ms]), r10\n"
- "call #__divmodhi4\n"
- "mov r12, 2(%[mso])\n"
- "mov r14, 0(%[mso])\n"
- : [mso] "+r" (mathStackPtr) /* outputs */
- : [ms] "r" (mathStackPtr) /* inputs */
- : /* clobbers */ "r10","r11","r12","r13","r14"
- );
+ /* directly call divmodhi4, gcc calls it twice even though the fn returns
+ * both values in one call */
+ asm("mov 2(%[ms]), r12\n"
+ "mov 0(%[ms]), r10\n"
+ "call #__divmodhi4\n"
+ "mov r12, 2(%[mso])\n"
+ "mov r14, 0(%[mso])\n"
+ : [mso] "+r" (mathStackPtr) /* outputs */
+ : [ms] "r" (mathStackPtr) /* inputs */
+ : /* clobbers */ "r10","r11","r12","r13","r14"
+ );
#else
- i = NOS;
- j = TOS;
- NOS = i / j;
- TOS = i % j;
+ i = NOS;
+ j = TOS;
+ NOS = i / j;
+ TOS = i % j;
#endif
- break;
-
- case 6: // . ( a -- )
- printNumber(popMathStack());
- break;
-
- case 7: // dup ( a -- a a )
- pushMathStack(TOS);
- break;
-
- case 8: // drop ( a -- )
- i = popMathStack();
- break;
-
- case 9: // swap ( a b -- b a )
- i = TOS;
- TOS = NOS;
- NOS = i;
- break;
-
- case 10: // < ( a b -- a<b )
- i = popMathStack();
- if(TOS < i){
- TOS = 1;
- } else {
- TOS = 0;
- }
- break;
-
- case 11: // > ( a b -- a>b )
- i = popMathStack();
- if(TOS > i){
- TOS = 1;
- } else {
- TOS = 0;
- }
- break;
-
- case 12: // == ( a b -- a==b )
- i = popMathStack();
- if(i == TOS){
- TOS = 1;
- } else {
- TOS = 0;
- }
- break;
-
- case 13: // hb. ( a -- )
- printHexByte(popMathStack());
- msp4th_putchar(' ');
- break;
-
- case 14: // gw ( -- ) \ get word from input
- getWord();
- break;
-
- case 15: // dfn ( -- ) \ create opcode and store word to cmdList
- dfnFunc();
- break;
-
- case 16: // abs ( a -- |a| ) \ -32768 is unchanged
- if (TOS < 0) {
- TOS = -TOS;
- }
- break;
-
- case 17: // , ( opcode -- ) \ push opcode to prog space
- prog[progIdx++] = popMathStack();
- break;
-
- case 18: // p@ ( opaddr -- opcode )
- i = TOS;
- TOS = prog[i];
- break;
-
- case 19: // p! ( opcode opaddr -- )
- i = popMathStack();
- j = popMathStack();
- prog[i] = j;
- break;
-
- case 20: // not ( a -- !a ) \ logical not
- if(TOS){
- TOS = 0;
- } else {
- TOS = 1;
- }
- break;
-
- case 21: // list ( -- ) \ show defined words
- listFunction();
- break;
-
- case 22: // if ( flag -- )
- ifFunc(0);
- break;
-
- case 23: // then ( trapped in ':')
- break;
-
- case 24: // else ( trapped in ':')
- break;
-
- case 25: // begin ( -- ) ( -a- pcnt )
- pushAddrStack(progCounter);
- break;
-
- case 26: // until ( flag -- ) ( addr -a- )
- i = popAddrStack();
- j = popMathStack();
- if(j == 0){
- addrStackPtr--; // number is still there ... just fix the pointer
- progCounter = i;
- }
- break;
-
- case 27: // depth ( -- n ) \ math stack depth
- pushMathStack(mathStackStart - mathStackPtr);
- break;
-
- case 28: // h. ( a -- )
- printHexWord(popMathStack());
- msp4th_putchar(' ');
- break;
-
- case 29: // ] ( trapped in interp )
- break;
-
- case 30: // num ( -- n flag ) \ is word in buffer a number?
- numFunc();
- break;
-
- case 31: // push0 ( -- 0 )
- pushMathStack(0);
- break;
-
- case 32: // goto ( for internal use only )
- ifFunc(1);
- break;
-
- case 33: // exec ( opcode -- )
- execFunc();
- break;
-
- case 34: // lu ( -- opcode 1 | 0 )
- luFunc();
- break;
-
- case 35: // pushn ( internal use only )
- pushnFunc();
- break;
-
- case 36: // over ( a b -- a b a )
- pushMathStack(NOS);
- break;
-
- case 37: // push1 ( -- 1 )
- pushMathStack(1);
- break;
-
- case 38: // pwrd ( -- ) \ print word buffer
- msp4th_puts(wordBuffer);
- break;
-
- case 39: // emit ( c -- )
- msp4th_putchar(popMathStack());
- break;
-
- case 40: // ; ( pcnt -a- )
- i = progCounter;
- progCounter = popAddrStack();
- break;
-
- case 41: // @ ( addr -- val ) \ read directly from memory address
- i = TOS >> 1;
- TOS = dirMemory[i];
- break;
-
- case 42: // ! ( val addr -- ) \ write directly to memory address words only!
- i = popMathStack(); // address to write to
- i = i >> 1;
- j = popMathStack(); // value to write
- dirMemory[i] = j;
- break;
-
- case 43: // h@ ( -- prog ) \ end of program code space
- pushMathStack(progIdx);
- break;
-
- //////// end of words used in progBi[] ///////////////////////////////////
-
- case 44: // do ( limit cnt -- ) ( -a- limit cnt pcnt )
- i = popMathStack(); // start of count
- j = popMathStack(); // end count
- k = progCounter;
-
- pushAddrStack(j); // limit on count
- pushAddrStack(i); // count (I)
- pushAddrStack(k); // address to remember for looping
- break;
-
- case 45: // loop ( -- ) ( limit cnt pcnt -a- | limit cnt+1 pcnt )
- loopFunc(1);
- break;
-
- case 46: // +loop ( n -- ) ( limit cnt pcnt -a- | limit cnt+n pcnt ) \ decrement loop if n<0
- loopFunc(popMathStack());
- break;
-
- case 47: // i ( -- cnt ) \ loop counter value
- i = ANOS;
- pushMathStack(i);
- break;
-
- case 48: // j ( -- cnt ) \ next outer loop counter value
- i = ASTACK(4);
- pushMathStack(i);
- break;
-
- case 49: // k ( -- cnt ) \ next next outer loop counter value
- i = ASTACK(7);
- pushMathStack(i);
- break;
-
- case 50: // ~ ( a -- ~a ) \ bitwise complement
- TOS = ~TOS;
- break;
-
- case 51: // ^ ( a b -- a^b ) \ bitwise xor
- NOS ^= TOS;
- popMathStack();
- break;
-
- case 52: // & ( a b -- a&b ) \ bitwise and
- NOS &= TOS;
- popMathStack();
- break;
-
- case 53: // | ( a b -- a|b ) \bitwise or
- NOS |= TOS;
- popMathStack();
- break;
-
- case 54: // */ ( a b c -- (a*b)/c ) \ 32b intermediate
+ break;
+
+ case 6: // . ( a -- )
+ printNumber(popMathStack());
+ break;
+
+ case 7: // dup ( a -- a a )
+ pushMathStack(TOS);
+ break;
+
+ case 8: // drop ( a -- )
+ i = popMathStack();
+ break;
+
+ case 9: // swap ( a b -- b a )
+ i = TOS;
+ TOS = NOS;
+ NOS = i;
+ break;
+
+ case 10: // < ( a b -- a<b )
+ i = popMathStack();
+ if (TOS < i) {
+ TOS = 1;
+ } else {
+ TOS = 0;
+ }
+ break;
+
+ case 11: // > ( a b -- a>b )
+ i = popMathStack();
+ if (TOS > i) {
+ TOS = 1;
+ } else {
+ TOS = 0;
+ }
+ break;
+
+ case 12: // == ( a b -- a==b )
+ i = popMathStack();
+ if (i == TOS) {
+ TOS = 1;
+ } else {
+ TOS = 0;
+ }
+ break;
+
+ case 13: // hb. ( a -- )
+ printHexByte(popMathStack());
+ msp4th_putchar(' ');
+ break;
+
+ case 14: // gw ( -- ) \ get word from input
+ getWordFunc();
+ break;
+
+ case 15: // dfn ( -- ) \ create opcode and store word to cmdList
+ dfnFunc();
+ break;
+
+ case 16: // abs ( a -- |a| ) \ -32768 is unchanged
+ if (TOS < 0) {
+ TOS = -TOS;
+ }
+ break;
+
+ case 17: // , ( opcode -- ) \ push opcode to prog space
+ prog[progIdx++] = popMathStack();
+ break;
+
+ case 18: // p@ ( opaddr -- opcode )
+ i = TOS;
+ TOS = prog[i];
+ break;
+
+ case 19: // p! ( opcode opaddr -- )
+ i = popMathStack();
+ j = popMathStack();
+ prog[i] = j;
+ break;
+
+ case 20: // not ( a -- !a ) \ logical not
+ if (TOS) {
+ TOS = 0;
+ } else {
+ TOS = 1;
+ }
+ break;
+
+ case 21: // list ( -- ) \ show defined words
+ listFunc();
+ break;
+
+ case 22: // if ( flag -- )
+ ifFunc(0);
+ break;
+
+ case 23: // then ( trapped in ':')
+ break;
+
+ case 24: // else ( trapped in ':')
+ break;
+
+ case 25: // begin ( -- ) ( -a- pcnt )
+ pushAddrStack(progCounter);
+ break;
+
+ case 26: // until ( flag -- ) ( addr -a- )
+ i = popAddrStack();
+ j = popMathStack();
+
+ if (j == 0) {
+ addrStackPtr--; // number is still there ... just fix the pointer
+ progCounter = i;
+ }
+ break;
+
+ case 27: // depth ( -- n ) \ math stack depth
+ pushMathStack(mathStackStart - mathStackPtr);
+ break;
+
+ case 28: // h. ( a -- )
+ printHexWord(popMathStack());
+ msp4th_putchar(' ');
+ break;
+
+ case 29: // ] ( trapped in interp )
+ break;
+
+ case 30: // num ( -- n flag ) \ is word in buffer a number?
+ numFunc();
+ break;
+
+ case 31: // push0 ( -- 0 )
+ pushMathStack(0);
+ break;
+
+ case 32: // goto ( for internal use only )
+ ifFunc(1);
+ break;
+
+ case 33: // exec ( opcode -- )
+ execFunc();
+ break;
+
+ case 34: // lu ( -- opcode 1 | 0 )
+ luFunc();
+ break;
+
+ case 35: // pushn ( internal use only )
+ pushnFunc();
+ break;
+
+ case 36: // over ( a b -- a b a )
+ pushMathStack(NOS);
+ break;
+
+ case 37: // push1 ( -- 1 )
+ pushMathStack(1);
+ break;
+
+ case 38: // pwrd ( -- ) \ print word buffer
+ msp4th_puts(wordBuffer);
+ break;
+
+ case 39: // emit ( c -- )
+ msp4th_putchar(popMathStack());
+ break;
+
+ case 40: // ; ( pcnt -a- )
+ i = progCounter;
+ progCounter = popAddrStack();
+ break;
+
+ case 41: // @ ( addr -- val ) \ read directly from memory address
+ i = TOS >> 1;
+ TOS = dirMemory[i];
+ break;
+
+ case 42: // ! ( val addr -- ) \ write directly to memory address words only!
+ i = popMathStack(); // address to write to
+ i = i >> 1;
+ j = popMathStack(); // value to write
+ dirMemory[i] = j;
+ break;
+
+ case 43: // h@ ( -- prog ) \ end of program code space
+ pushMathStack(progIdx);
+ break;
+
+ //////// end of words used in progBi[] ///////////////////////////////////
+
+ case 44: // do ( limit cnt -- ) ( -a- limit cnt pcnt )
+ i = popMathStack(); // start of count
+ j = popMathStack(); // end count
+ k = progCounter;
+
+ pushAddrStack(j); // limit on count
+ pushAddrStack(i); // count (I)
+ pushAddrStack(k); // address to remember for looping
+ break;
+
+ case 45: // loop ( -- ) ( limit cnt pcnt -a- | limit cnt+1 pcnt )
+ loopFunc(1);
+ break;
+
+ case 46: // +loop ( n -- ) ( limit cnt pcnt -a- | limit cnt+n pcnt ) \ decrement loop if n<0
+ loopFunc(popMathStack());
+ break;
+
+ case 47: // i ( -- cnt ) \ loop counter value
+ i = ANOS;
+ pushMathStack(i);
+ break;
+
+ case 48: // j ( -- cnt ) \ next outer loop counter value
+ i = ASTACK(4);
+ pushMathStack(i);
+ break;
+
+ case 49: // k ( -- cnt ) \ next next outer loop counter value
+ i = ASTACK(7);
+ pushMathStack(i);
+ break;
+
+ case 50: // ~ ( a -- ~a ) \ bitwise complement
+ TOS = ~TOS;
+ break;
+
+ case 51: // ^ ( a b -- a^b ) \ bitwise xor
+ NOS ^= TOS;
+ popMathStack();
+ break;
+
+ case 52: // & ( a b -- a&b ) \ bitwise and
+ NOS &= TOS;
+ popMathStack();
+ break;
+
+ case 53: // | ( a b -- a|b ) \bitwise or
+ NOS |= TOS;
+ popMathStack();
+ break;
+
+ case 54: // */ ( a b c -- (a*b)/c ) \ 32b intermediate
#if defined(MSP430)
- asm("dint");
- MPYS = popMathStack();
- OP2 = NOS;
- x = (((int32_t)RESHI << 16) | RESLO);
- asm("eint");
- x = (x / TOS);
- popMathStack();
- TOS = (int16_t)(x & 0xffff);
+ asm("dint");
+ MPYS = popMathStack();
+ OP2 = NOS;
+ x = (((int32_t)RESHI << 16) | RESLO);
+ asm("eint");
+ x = (x / TOS);
+ popMathStack();
+ TOS = (int16_t)(x & 0xffff);
#else
- i = popMathStack();
- j = TOS;
- k = NOS;
- x = j * k;
- x = x / i;
- popMathStack();
- TOS = (int16_t)(x & 0xffff);
+ i = popMathStack();
+ j = TOS;
+ k = NOS;
+ x = j * k;
+ x = x / i;
+ popMathStack();
+ TOS = (int16_t)(x & 0xffff);
#endif
- break;
-
- case 55: // key ( -- c ) \ get a key from input .... (wait for it)
- pushMathStack(msp4th_getchar());
- break;
-
- case 56: // cr ( -- )
- msp4th_putchar(0x0D);
- msp4th_putchar(0x0A);
- break;
-
- case 57: // 2* ( a -- a<<1 )
- TOS <<= 1;
- break;
-
- case 58: // 2/ ( a -- a>>1 )
- TOS >>= 1;
- break;
-
- case 59: // call0 ( &func -- *func() )
- i = TOS;
+ break;
+
+ case 55: // key ( -- c ) \ get a key from input .... (wait for it)
+ pushMathStack(msp4th_getchar());
+ break;
+
+ case 56: // cr ( -- )
+ msp4th_putchar(0x0D);
+ msp4th_putchar(0x0A);
+ break;
+
+ case 57: // 2* ( a -- a<<1 )
+ TOS <<= 1;
+ break;
+
+ case 58: // 2/ ( a -- a>>1 )
+ TOS >>= 1;
+ break;
+
+ case 59: // call0 ( &func -- *func() )
+ i = TOS;
GCC_DIAG_OFF(int-to-pointer-cast);
- TOS = (*(int16_t(*)(void)) i) ();
+ TOS = (*(int16_t(*)(void)) i) ();
GCC_DIAG_ON(int-to-pointer-cast);
- break;
+ break;
- case 60: // call1 ( a &func -- *func(a) )
- i = TOS;
- j = NOS;
+ case 60: // call1 ( a &func -- *func(a) )
+ i = TOS;
+ j = NOS;
GCC_DIAG_OFF(int-to-pointer-cast);
- NOS = (*(int16_t(*)(int16_t)) i) (j);
+ NOS = (*(int16_t(*)(int16_t)) i) (j);
GCC_DIAG_ON(int-to-pointer-cast);
- popMathStack();
- break;
+ popMathStack();
+ break;
- case 61: // call2 ( a b &func -- *func(a,b) )
- i = TOS;
- j = NOS;
- k = STACK(2);
+ case 61: // call2 ( a b &func -- *func(a,b) )
+ i = TOS;
+ j = NOS;
+ k = STACK(2);
GCC_DIAG_OFF(int-to-pointer-cast);
- STACK(2) = (*(int16_t(*)(int16_t, int16_t)) i) (k, j);
+ STACK(2) = (*(int16_t(*)(int16_t, int16_t)) i) (k, j);
GCC_DIAG_ON(int-to-pointer-cast);
- ndrop(2);
- break;
-
- case 62: // call3 ( a b c &func -- *func(a,b,c) )
- i = TOS;
- j = NOS;
- k = STACK(2);
- m = STACK(3);
+ ndrop(2);
+ break;
+
+ case 62: // call3 ( a b c &func -- *func(a,b,c) )
+ i = TOS;
+ j = NOS;
+ k = STACK(2);
+ m = STACK(3);
GCC_DIAG_OFF(int-to-pointer-cast);
- STACK(3) = (*(int16_t(*)(int16_t, int16_t, int16_t)) i) (m, k, j);
+ STACK(3) = (*(int16_t(*)(int16_t, int16_t, int16_t)) i) (m, k, j);
GCC_DIAG_ON(int-to-pointer-cast);
- ndrop(3);
- break;
-
- case 63: // call4 ( a b c d &func -- *func(a,b,c,d) )
- i = TOS;
- j = NOS;
- k = STACK(2);
- m = STACK(3);
- n = STACK(4);
+ ndrop(3);
+ break;
+
+ case 63: // call4 ( a b c d &func -- *func(a,b,c,d) )
+ i = TOS;
+ j = NOS;
+ k = STACK(2);
+ m = STACK(3);
+ n = STACK(4);
GCC_DIAG_OFF(int-to-pointer-cast);
- STACK(4) = (*(int16_t(*)(int16_t, int16_t, int16_t, int16_t)) i) (n, m, k, j);
+ STACK(4) = (*(int16_t(*)(int16_t, int16_t, int16_t, int16_t)) i) (n, m, k, j);
GCC_DIAG_ON(int-to-pointer-cast);
- ndrop(4);
- break;
+ ndrop(4);
+ break;
- case 64: // ndrop ( (x)*n n -- ) \ drop n math stack cells
- ndrop(popMathStack());
- break;
+ case 64: // ndrop ( (x)*n n -- ) \ drop n math stack cells
+ ndrop(popMathStack());
+ break;
- case 65: // swpb ( n -- n ) \ byteswap TOS
+ case 65: // swpb ( n -- n ) \ byteswap TOS
#if defined(MSP430)
- asm("swpb %[s]\n": [s] "+r" (mathStackPtr) : : );
+ asm("swpb %[s]\n": [s] "+r" (mathStackPtr) : : );
#else
- TOS = ((TOS >> 8) & 0x00ff) | ((TOS << 8) & 0xff00);
+ TOS = ((TOS >> 8) & 0x00ff) | ((TOS << 8) & 0xff00);
#endif
- break;
-
- case 66: // +! ( n addr -- ) \ *addr += n
- i = popMathStack();
- j = popMathStack();
- dirMemory[i] += j;
- break;
-
- case 67: // roll ( n -- ) \ nth stack removed and placed on top
- rollFunc(popMathStack());
- break;
-
- case 68: // pick ( n -- ) \ nth stack copied to top
- i = popMathStack();
- pushMathStack(STACK(i));
- break;
-
- case 69: // tuck ( a b -- b a b ) \ insert copy TOS to after NOS
- i = NOS;
- pushMathStack(TOS);
- STACK(2) = TOS;
- NOS = i;
- break;
-
- case 70: // max ( a b -- c ) \ c = a ? a>b : b
- i = popMathStack();
- if (i > TOS) {
- TOS = i;
- }
- break;
-
- case 71: // min ( a b -- c ) \ c = a ? a<b : b
- i = popMathStack();
- if (i < TOS) {
- TOS = i;
- }
- break;
-
- case 72: // s. ( -- ) \ print stack contents, TOS on right
- { // addr is strictly local to this block
- int16_t *addr;
- addr = mathStackStart;
- while (addr >= mathStackPtr) {
- printNumber(*addr);
- addr--;
- }
- }
- break;
-
- case 73: // sh. ( -- ) \ print stack contents in hex, TOS on right
- { // addr is strictly local to this block
- int16_t *addr;
- addr = mathStackStart;
- while (addr >= mathStackPtr) {
- printHexWord(*addr);
- msp4th_putchar(' ');
- addr--;
- }
- }
- break;
-
- case 74: // neg ( a -- -a ) \ twos complement
- TOS *= -1;
- break;
-
- case 75: // echo ( bool -- ) \ ?echo prompts and terminal input?
- echo = popMathStack();
- break;
-
- case 76: // init ( &config -- ) \ clears buffers and calls msp4th_init
- *lineBuffer = 0; // if location is same, the call is recursive otherwise
+ break;
+
+ case 66: // +! ( n addr -- ) \ *addr += n
+ i = popMathStack();
+ j = popMathStack();
+ dirMemory[i] += j;
+ break;
+
+ case 67: // roll ( n -- ) \ nth stack removed and placed on top
+ rollFunc(popMathStack());
+ break;
+
+ case 68: // pick ( n -- ) \ nth stack copied to top
+ i = popMathStack();
+ pushMathStack(STACK(i));
+ break;
+
+ case 69: // tuck ( a b -- b a b ) \ insert copy TOS to after NOS
+ i = NOS;
+ pushMathStack(TOS);
+ STACK(2) = TOS;
+ NOS = i;
+ break;
+
+ case 70: // max ( a b -- c ) \ c = a ? a>b : b
+ i = popMathStack();
+ if (i > TOS) {
+ TOS = i;
+ }
+ break;
+
+ case 71: // min ( a b -- c ) \ c = a ? a<b : b
+ i = popMathStack();
+ if (i < TOS) {
+ TOS = i;
+ }
+ break;
+
+ case 72: // s. ( -- ) \ print stack contents, TOS on right
+ { // addr is strictly local to this block
+ int16_t *addr;
+ addr = mathStackStart;
+ while (addr >= mathStackPtr) {
+ printNumber(*addr);
+ addr--;
+ }
+ }
+ break;
+
+ case 73: // sh. ( -- ) \ print stack contents in hex, TOS on right
+ { // addr is strictly local to this block
+ int16_t *addr;
+ addr = mathStackStart;
+ while (addr >= mathStackPtr) {
+ printHexWord(*addr);
+ msp4th_putchar(' ');
+ addr--;
+ }
+ }
+ break;
+
+ case 74: // neg ( a -- -a ) \ twos complement
+ TOS *= -1;
+ break;
+
+ case 75: // echo ( bool -- ) \ ?echo prompts and terminal input?
+ echo = popMathStack();
+ break;
+
+ case 76: // init ( &config -- ) \ clears buffers and calls msp4th_init
+ *lineBuffer = 0; // if location is same, the call is recursive otherwise
GCC_DIAG_OFF(int-to-pointer-cast);
- msp4th_init((struct msp4th_config *)popMathStack());
+ msp4th_init((struct msp4th_config *)popMathStack());
GCC_DIAG_ON(int-to-pointer-cast);
- break;
+ break;
- case 77: // o2w ( opcode -- ) \ leaves name of opcode in wordBuffer
- opcode2wordFunc();
- break;
+ case 77: // o2w ( opcode -- ) \ prints name of opcode
+ opcode2wordFunc();
+ break;
- case 78: // o2p ( opcode -- progIdx ) \ lookup opcode definition, 0 if builtin
- opcode2progFunc();
- break;
+ case 78: // o2p ( opcode -- progIdx ) \ lookup opcode definition, 0 if builtin
+ opcode2progFunc();
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
}
+/****************************************************************************
+ *
+ * Public functions
+ *
+ ***************************************************************************/
+void msp4th_init(struct msp4th_config *c)
+{
+ /*
+ * Get addresses of user-configurable arrays from the pre-known vector
+ * table locations.
+ *
+ * Changing the values in the msp4th_* locations and calling
+ * msp4th_init() again restarts the interpreter with the new layout;
+ */
+ mathStackPtr = c->mathStackStart;
+ addrStackPtr = c->addrStackStart;
+ mathStackStart = c->mathStackStart;
+ addrStackStart = c->addrStackStart;
+ prog = c->prog;
+ progOpcodes = c->progOpcodes;
+ cmdList = c->cmdList;
+ lineBuffer = c->lineBuffer;
+ lineBufferLength = c->lineBufferLength;
+ wordBuffer = c->wordBuffer;
+ wordBufferLength = c->wordBufferLength;
+ msp4th_putchar = c->putchar;
+ msp4th_getchar = c->getchar;
+ msp4th_puts = c->puts;
+
+
+ xit = 0;
+ echo = 1;
+ progCounter = BUILTIN_INTERP_OFFSET;
+ progIdx = 1; // this will be the first opcode
+ cmdListIdx = 0;
+
+ lineBufferIdx = 0;
+ msp4th_puts((uint8_t *)"msp4th!");
+}
+
+
+void msp4th_processLoop(void) // this processes the forth opcodes.
+{
+ uint16_t opcode;
+ uint16_t tmp;
+
+ while(xit == 0){
+ if(progCounter >= BUILTIN_INTERP_OFFSET){
+ tmp = progCounter - BUILTIN_INTERP_OFFSET;
+ opcode = progBi[tmp];
+ } else {
+ opcode = prog[progCounter];
+ }
+
+ progCounter = progCounter + 1;
+
+ if(opcode >= BUILTIN_OPCODE_OFFSET){
+ // this is a built in opcode
+ execVM(opcode - BUILTIN_OPCODE_OFFSET);
+ } else {
+ pushAddrStack(progCounter);
+ progCounter = progOpcodes[opcode];
+ }
+ } // while ()
+}
+