[OpenBIOS] [commit] r960 - trunk/openbios-devel/kernel

repository service svn at openbios.org
Wed Nov 17 20:36:16 CET 2010


Author: blueswirl
Date: Wed Nov 17 20:36:16 2010
New Revision: 960
URL: http://tracker.coreboot.org/trac/openbios/changeset/960

Log:
kernel: avoid including C files from another

Merge kernel/internal.c and kernel/primitives.c into
kernel/forth.c. This helps with the build dependencies.

Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

Deleted:
   trunk/openbios-devel/kernel/internal.c
   trunk/openbios-devel/kernel/primitives.c
Modified:
   trunk/openbios-devel/kernel/build.xml
   trunk/openbios-devel/kernel/forth.c

Modified: trunk/openbios-devel/kernel/build.xml
==============================================================================
--- trunk/openbios-devel/kernel/build.xml	Mon Nov 15 23:13:13 2010	(r959)
+++ trunk/openbios-devel/kernel/build.xml	Wed Nov 17 20:36:16 2010	(r960)
@@ -1,15 +1,15 @@
 <build>
 
  <executable name="forthstrap" target="host">
-  <object source="bootstrap.c"/>
   <object source="dict.c"/>
-  <object source="primitives.c"/>
+  <object source="bootstrap.c"/>
+  <object source="forth.c"/>
   <object source="stack.c"/>
  </executable>
  
  <library name="bootstrap" type="static" target="target">
   <object source="dict.c"/>
-  <object source="primitives.c"/>
+  <object source="forth.c"/>
   <object source="stack.c"/>
  </library>
   

Modified: trunk/openbios-devel/kernel/forth.c
==============================================================================
--- trunk/openbios-devel/kernel/forth.c	Mon Nov 15 23:13:13 2010	(r959)
+++ trunk/openbios-devel/kernel/forth.c	Wed Nov 17 20:36:16 2010	(r960)
@@ -1,4 +1,5 @@
-/* tag: C implementation of all forth primitives
+/* tag: C implementation of all forth primitives,
+ * internal words, inner interpreter and such
  *
  * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
  *
@@ -6,6 +7,833 @@
  * the copyright and warranty status of this work.
  */
 
+#include "config.h"
+#include "sysinclude.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+
+/*
+ * cross platform abstraction
+ */
+
+#include "cross.h"
+
+#ifndef FCOMPILER
+#include "libc/vsprintf.h"
+#else
+#include <stdarg.h>
+#endif
+
+/*
+ * execution works as follows:
+ *  - PC is pushed on return stack
+ *  - PC is set to new CFA
+ *  - address pointed by CFA is executed by CPU
+ */
+
+typedef void forth_word(void);
+
+static forth_word * const words[];
+ucell PC;
+volatile int interruptforth = 0;
+
+#define DEBUG_MODE_NONE 0
+#define DEBUG_MODE_STEP 1
+#define DEBUG_MODE_TRACE 2
+#define DEBUG_MODE_STEPUP 3
+
+#define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n"
+
+/* Empty linked list of debug xts */
+struct debug_xt {
+    ucell xt_docol;
+    ucell xt_semis;
+    int mode;
+    struct debug_xt *next;
+};
+
+static struct debug_xt debug_xt_eol = { (ucell)0, (ucell)0, 0, NULL};
+static struct debug_xt *debug_xt_list = &debug_xt_eol;
+
+/* Static buffer for xt name */
+char xtname[MAXNFALEN];
+
+#ifndef FCOMPILER
+/* instead of pointing to an explicit 0 variable we
+ * point behind the pointer.
+ */
+static ucell t[] = { 0, 0, 0, 0 };
+static ucell *trampoline = t;
+
+/*
+ * Code Field Address (CFA) definitions (DOCOL and the like)
+ */
+
+void forth_init(void)
+{
+    init_trampoline(trampoline);
+}
+#endif
+
+#ifndef CONFIG_DEBUG_INTERPRETER
+#define dbg_interp_printk( a... )       do { } while(0)
+#else
+#define dbg_interp_printk( a... )       printk( a )
+#endif
+
+#ifndef CONFIG_DEBUG_INTERNAL
+#define dbg_internal_printk( a... )     do { } while(0)
+#else
+#define dbg_internal_printk( a... )     printk( a )
+#endif
+
+
+void init_trampoline(ucell *tramp)
+{
+    tramp[0] = DOCOL;
+    tramp[1] = 0;
+    tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell));
+    tramp[3] = 0;
+}
+
+static inline void processxt(ucell xt)
+{
+    void (*tokenp) (void);
+
+    dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC, xt);
+    tokenp = words[xt];
+    tokenp();
+}
+
+static void docol(void)
+{                               /* DOCOL */
+    PUSHR(PC);
+    PC = read_ucell(cell2pointer(PC));
+
+    dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC - sizeof(cell)) ));
+}
+
+static void semis(void)
+{
+    PC = POPR();
+}
+
+static inline void next(void)
+{
+    PC += sizeof(ucell);
+
+    dbg_interp_printk("next: PC is now %x\n", PC);
+    processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+}
+
+static inline void next_dbg(void);
+
+int enterforth(xt_t xt)
+{
+    ucell *_cfa = (ucell*)cell2pointer(xt);
+    cell tmp;
+
+    if (read_ucell(_cfa) != DOCOL) {
+        trampoline[1] = target_ucell(xt);
+        _cfa = trampoline;
+    }
+
+    if (rstackcnt < 0) {
+        rstackcnt = 0;
+    }
+
+    tmp = rstackcnt;
+    interruptforth = FORTH_INTSTAT_CLR;
+
+    PUSHR(PC);
+    PC = pointer2cell(_cfa);
+
+    while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) {
+        if (debug_xt_list->next == NULL) {
+            while (rstackcnt > tmp && !interruptforth) {
+                dbg_interp_printk("enterforth: NEXT\n");
+                next();
+            }
+        } else {
+            while (rstackcnt > tmp && !interruptforth) {
+                dbg_interp_printk("enterforth: NEXT_DBG\n");
+                next_dbg();
+            }
+        }
+
+        /* Always clear the debug mode change flag */
+        interruptforth = interruptforth & (~FORTH_INTSTAT_DBG);
+    }
+
+#if 0
+    /* return true if we took an exception. The caller should normally
+     * handle exceptions by returning immediately since the throw
+     * is supposed to abort the execution of this C-code too.
+     */
+
+    if (rstackcnt != tmp) {
+        printk("EXCEPTION DETECTED!\n");
+    }
+#endif
+    return rstackcnt != tmp;
+}
+
+/* called inline thus a slightly different behaviour */
+static void lit(void)
+{                               /* LIT */
+    PC += sizeof(cell);
+    PUSH(read_ucell(cell2pointer(PC)));
+    dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC)));
+}
+
+static void docon(void)
+{                               /* DOCON */
+    ucell tmp = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+    PUSH(tmp);
+    dbg_interp_printk("docon: PC=%x, value=%x\n", PC, tmp);
+}
+
+static void dovar(void)
+{                               /* DOVAR */
+    ucell tmp = read_ucell(cell2pointer(PC)) + sizeof(ucell);
+    PUSH(tmp);              /* returns address to variable */
+    dbg_interp_printk("dovar: PC: %x, %x\n", PC, tmp);
+}
+
+static void dobranch(void)
+{                               /* unconditional branch */
+    PC += sizeof(cell);
+    PC += read_cell(cell2pointer(PC));
+}
+
+static void docbranch(void)
+{                               /* conditional branch */
+    PC += sizeof(cell);
+    if (POP()) {
+        dbg_internal_printk("  ?branch: end loop\n");
+    } else {
+        dbg_internal_printk("  ?branch: follow branch\n");
+        PC += read_cell(cell2pointer(PC));
+    }
+}
+
+
+static void execute(void)
+{                               /* EXECUTE */
+    ucell address = POP();
+    dbg_interp_printk("execute: %x\n", address);
+
+    PUSHR(PC);
+    trampoline[1] = target_ucell(address);
+    PC = pointer2cell(trampoline);
+}
+
+/*
+ * call ( ... function-ptr -- ??? )
+ */
+static void call(void)
+{
+#ifdef FCOMPILER
+    printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n");
+    exit(1);
+#else
+    void (*funcptr) (void);
+    funcptr=(void *)cell2pointer(POP());
+    dbg_interp_printk("call: %x", funcptr);
+    funcptr();
+#endif
+}
+
+/*
+ * sys-debug ( errno -- )
+ */
+
+static void sysdebug(void)
+{
+#ifdef FCOMPILER
+    cell errorno=POP();
+    exception(errorno);
+#else
+    (void) POP();
+#endif
+}
+
+static void dodoes(void)
+{                               /* DODOES */
+    ucell data = read_ucell(cell2pointer(PC)) + (2 * sizeof(ucell));
+    ucell word = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+
+    dbg_interp_printk("DODOES data=%x word=%x\n", data, word);
+
+    PUSH(data);
+    PUSH(word);
+
+    execute();
+}
+
+static void dodefer(void)
+{
+    docol();
+}
+
+static void dodo(void)
+{
+    cell startval, endval;
+    startval = POP();
+    endval = POP();
+
+    PUSHR(endval);
+    PUSHR(startval);
+}
+
+static void doisdo(void)
+{
+    cell startval, endval, offset;
+
+    startval = POP();
+    endval = POP();
+
+    PC += sizeof(cell);
+
+    if (startval == endval) {
+        offset = read_cell(cell2pointer(PC));
+        PC += offset;
+    } else {
+        PUSHR(endval);
+        PUSHR(startval);
+    }
+}
+
+static void doloop(void)
+{
+    cell offset, startval, endval;
+
+    startval = POPR() + 1;
+    endval = POPR();
+
+    PC += sizeof(cell);
+
+    if (startval < endval) {
+        offset = read_cell(cell2pointer(PC));
+        PC += offset;
+        PUSHR(endval);
+        PUSHR(startval);
+    }
+
+}
+
+static void doplusloop(void)
+{
+    ucell high, low;
+    cell increment, startval, endval, offset;
+
+    increment = POP();
+
+    startval = POPR();
+    endval = POPR();
+
+    low = (ucell) startval;
+    startval += increment;
+
+    PC += sizeof(cell);
+
+    if (increment >= 0) {
+        high = (ucell) startval;
+    } else {
+        high = low;
+        low = (ucell) startval;
+    }
+
+    if (endval - (low + 1) >= high - low) {
+        offset = read_cell(cell2pointer(PC));
+        PC += offset;
+
+        PUSHR(endval);
+        PUSHR(startval);
+    }
+}
+
+/*
+ *  instance handling CFAs
+ */
+#ifndef FCOMPILER
+static ucell get_myself(void)
+{
+    static ucell *myselfptr = NULL;
+    if (myselfptr == NULL) {
+        myselfptr = (ucell*)cell2pointer(findword("my-self")) + 1;
+    }
+    ucell *myself = (ucell*)cell2pointer(*myselfptr);
+    return (myself != NULL) ? *myself : 0;
+}
+
+static void doivar(void)
+{
+    ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+    ucell ibase = get_myself();
+
+    dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p[0], p[1], ibase );
+
+    r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+    PUSH( r );
+}
+
+static void doival(void)
+{
+    ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+    ucell ibase = get_myself();
+
+    dbg_interp_printk("ivar, offset: %d size: %d\n", p[0], p[1] );
+
+    r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+    PUSH( *(ucell *)cell2pointer(r) );
+}
+
+static void doidefer(void)
+{
+    ucell *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+    ucell ibase = get_myself();
+
+    dbg_interp_printk("doidefer, offset: %d size: %d\n", p[0], p[1] );
+
+    PUSHR(PC);
+    PC = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+    PC -= sizeof(ucell);
+}
+#else
+static void noinstances(void)
+{
+    printk("Opening devices is not supported during bootstrap. Sorry.\n");
+    exit(1);
+}
+#define doivar   noinstances
+#define doival   noinstances
+#define doidefer noinstances
+#endif
+
+/*
+ * $include / $encode-file
+ */
+#ifdef FCOMPILER
+static void
+string_relay(void (*func)(const char *))
+{
+    int len = POP();
+    char *name, *p = (char*)cell2pointer(POP());
+    name = malloc(len + 1);
+    memcpy(name, p, len);
+    name[len] = 0;
+    (*func)(name);
+    free(name);
+}
+#else
+#define string_relay(dummy) do { DROP(); DROP(); } while(0)
+#endif
+
+static void
+do_include(void)
+{
+    string_relay(&include_file);
+}
+
+static void
+do_encode_file( void )
+{
+    string_relay(&encode_file);
+}
+
+/*
+ * Debug support functions
+ */
+
+static
+int printf_console(const char *fmt, ...)
+{
+    cell tmp;
+
+    char buf[512];
+    va_list args;
+    int i;
+
+    va_start(args, fmt);
+    i = vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+
+    /* Push to the Forth interpreter for console output */
+    tmp = rstackcnt;
+
+    PUSH(pointer2cell(buf));
+    PUSH((int)strlen(buf));
+    trampoline[1] = findword("type");
+
+    PUSHR(PC);
+    PC = pointer2cell(trampoline);
+
+    while (rstackcnt > tmp) {
+        dbg_interp_printk("printf_console: NEXT\n");
+        next();
+    }
+
+    return i;
+}
+
+static
+int getchar_console(void)
+{
+    cell tmp;
+
+    /* Push to the Forth interpreter for console output */
+    tmp = rstackcnt;
+
+    trampoline[1] = findword("key");
+
+    PUSHR(PC);
+    PC = pointer2cell(trampoline);
+
+    while (rstackcnt > tmp) {
+        dbg_interp_printk("getchar_console: NEXT\n");
+        next();
+    }
+
+    return POP();
+}
+
+static void
+display_dbg_dstack(void)
+{
+    /* Display dstack contents between parentheses */
+    int i;
+
+    if (dstackcnt == 0) {
+        printf_console(" ( Empty ) ");
+        return;
+    } else {
+        printf_console(" ( ");
+        for (i = 1; i <= dstackcnt; i++) {
+            if (i != 1) {
+                printf_console(" ");
+            }
+            printf_console("%" FMT_CELL_x, dstack[i]);
+        }
+        printf_console(" ) ");
+    }
+}
+
+static void
+display_dbg_rstack(void)
+{
+    /* Display rstack contents between parentheses */
+    int i;
+
+    if (rstackcnt == 0) {
+        printf_console(" ( Empty ) ");
+        return;
+    } else {
+        printf_console("\nR: ( ");
+        for (i = 1; i <= rstackcnt; i++) {
+            if (i != 1) {
+                printf_console(" ");
+            }
+            printf_console("%" FMT_CELL_x, rstack[i]);
+        }
+        printf_console(" ) \n");
+    }
+}
+
+static int
+add_debug_xt(ucell xt)
+{
+    struct debug_xt *debug_xt_item;
+
+    /* If the xt CFA isn't DOCOL then issue a warning and do nothing */
+    if (read_ucell(cell2pointer(xt)) != DOCOL) {
+        printf_console("\nprimitive words cannot be debugged\n");
+        return 0;
+    }
+
+    /* If this xt is already in the list, do nothing but indicate success */
+    for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+         debug_xt_item = debug_xt_item->next)
+        if (debug_xt_item->xt_docol == xt) {
+            return 1;
+        }
+
+    /* We already have the CFA (PC) indicating the starting cell of
+       the word, however we also need the ending cell too (we cannot
+       rely on the rstack as it can be arbitrarily changed by a forth
+       word). Hence the use of findsemis() */
+
+    /* Otherwise add to the head of the linked list */
+    debug_xt_item = malloc(sizeof(struct debug_xt));
+    debug_xt_item->xt_docol = xt;
+    debug_xt_item->xt_semis = findsemis(xt);
+    debug_xt_item->mode = DEBUG_MODE_NONE;
+    debug_xt_item->next = debug_xt_list;
+    debug_xt_list = debug_xt_item;
+
+    /* Indicate debug mode change */
+    interruptforth |= FORTH_INTSTAT_DBG;
+
+    /* Success */
+    return 1;
+}
+
+static void
+del_debug_xt(ucell xt)
+{
+    struct debug_xt *debug_xt_item, *tmp_xt_item;
+
+    /* Handle the case where the xt is at the head of the list */
+    if (debug_xt_list->xt_docol == xt) {
+        tmp_xt_item = debug_xt_list;
+        debug_xt_list = debug_xt_list->next;
+        free(tmp_xt_item);
+
+        return;
+    }
+
+    /* Otherwise find this xt in the linked list and remove it */
+    for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+         debug_xt_item = debug_xt_item->next) {
+        if (debug_xt_item->next->xt_docol == xt) {
+            tmp_xt_item = debug_xt_item->next;
+            debug_xt_item->next = debug_xt_item->next->next;
+            free(tmp_xt_item);
+        }
+    }
+
+    /* If the list is now empty, indicate debug mode change */
+    if (debug_xt_list->next == NULL) {
+        interruptforth |= FORTH_INTSTAT_DBG;
+    }
+}
+
+static void
+do_source_dbg(struct debug_xt *debug_xt_item)
+{
+    /* Forth source debugger implementation */
+    char k, done = 0;
+
+    /* Display current dstack */
+    display_dbg_dstack();
+    printf_console("\n");
+
+    fstrncpy(xtname, lfa2nfa(read_ucell(cell2pointer(PC)) - sizeof(cell)), MAXNFALEN);
+    printf_console("%p: %s ", cell2pointer(PC), xtname);
+
+    /* If in trace mode, we just carry on */
+    if (debug_xt_item->mode == DEBUG_MODE_TRACE) {
+        return;
+    }
+
+    /* Otherwise in step mode, prompt for a keypress */
+    k = getchar_console();
+
+    /* Only proceed if done is true */
+    while (!done) {
+        switch (k) {
+
+        case ' ':
+        case '\n':
+            /* Perform a single step */
+            done = 1;
+            break;
+
+        case 'u':
+        case 'U':
+            /* Up - unmark current word for debug, mark its caller for
+             * debugging and finish executing current word */
+
+            /* Since this word could alter the rstack during its execution,
+             * we only know the caller when (semis) is called for this xt.
+             * Hence we mark the xt as a special DEBUG_MODE_STEPUP which
+             * means we run as normal, but schedule the xt for deletion
+             * at its corresponding (semis) word when we know the rstack
+             * will be set to its final parent value */
+            debug_xt_item->mode = DEBUG_MODE_STEPUP;
+            done = 1;
+            break;
+
+        case 'd':
+        case 'D':
+            /* Down - mark current word for debug and step into it */
+            done = add_debug_xt(read_ucell(cell2pointer(PC)));
+            if (!done) {
+                k = getchar_console();
+            }
+            break;
+
+        case 't':
+        case 'T':
+            /* Trace mode */
+            debug_xt_item->mode = DEBUG_MODE_TRACE;
+            done = 1;
+            break;
+
+        case 'r':
+        case 'R':
+            /* Display rstack */
+            display_dbg_rstack();
+            done = 0;
+            k = getchar_console();
+            break;
+
+        case 'f':
+        case 'F':
+            /* Start subordinate Forth interpreter */
+            PUSHR(PC - sizeof(cell));
+            PC = findword("outer-interpreter") + sizeof(ucell);
+
+            /* Save rstack position for when we return */
+            dbgrstackcnt = rstackcnt;
+            done = 1;
+            break;
+
+        default:
+            /* Display debug banner */
+            printf_console(DEBUG_BANNER);
+            k = getchar_console();
+        }
+    }
+}
+
+static void docol_dbg(void)
+{                               /* DOCOL */
+    struct debug_xt *debug_xt_item;
+
+    PUSHR(PC);
+    PC = read_ucell(cell2pointer(PC));
+
+    /* If current xt is in our debug xt list, display word name */
+    debug_xt_item = debug_xt_list;
+    while (debug_xt_item->next) {
+        if (debug_xt_item->xt_docol == PC) {
+            fstrncpy(xtname, lfa2nfa(PC - sizeof(cell)), MAXNFALEN);
+            printf_console("\n: %s ", xtname);
+
+            /* Step mode is the default */
+            debug_xt_item->mode = DEBUG_MODE_STEP;
+        }
+
+        debug_xt_item = debug_xt_item->next;
+    }
+
+    dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC - sizeof(cell))));
+}
+
+static void semis_dbg(void)
+{
+    struct debug_xt *debug_xt_item, *debug_xt_up = NULL;
+
+    /* If current semis is in our debug xt list, disable debug mode */
+    debug_xt_item = debug_xt_list;
+    while (debug_xt_item->next) {
+        if (debug_xt_item->xt_semis == PC) {
+            if (debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+                /* Handle the normal case */
+                fstrncpy(xtname, lfa2nfa(debug_xt_item->xt_docol - sizeof(cell)), MAXNFALEN);
+                printf_console("\n[ Finished %s ] ", xtname);
+
+                /* Reset to step mode in case we were in trace mode */
+                debug_xt_item->mode = DEBUG_MODE_STEP;
+            } else {
+                /* This word requires execution of the debugger "Up"
+                 * semantics. However we can't do this here since we
+                 * are iterating through the debug list, and we need
+                 * to change it. So we do it afterwards.
+                 */
+                debug_xt_up = debug_xt_item;
+            }
+        }
+
+        debug_xt_item = debug_xt_item->next;
+    }
+
+    /* Execute debugger "Up" semantics if required */
+    if (debug_xt_up) {
+        /* Only add the parent word if it is not within the trampoline */
+        if (rstack[rstackcnt] != (cell)pointer2cell(&trampoline[1])) {
+            del_debug_xt(debug_xt_up->xt_docol);
+            add_debug_xt(findxtfromcell(rstack[rstackcnt]));
+
+            fstrncpy(xtname, lfa2nfa(findxtfromcell(rstack[rstackcnt]) - sizeof(cell)), MAXNFALEN);
+            printf_console("\n[ Up to %s ] ", xtname);
+        } else {
+            fstrncpy(xtname, lfa2nfa(findxtfromcell(debug_xt_up->xt_docol) - sizeof(cell)), MAXNFALEN);
+            printf_console("\n[ Finished %s (Unable to go up, hit trampoline) ] ", xtname);
+
+            del_debug_xt(debug_xt_up->xt_docol);
+        }
+
+        debug_xt_up = NULL;
+    }
+
+    PC = POPR();
+}
+
+static inline void next_dbg(void)
+{
+    struct debug_xt *debug_xt_item;
+    void (*tokenp) (void);
+
+    PC += sizeof(ucell);
+
+    /* If the PC lies within a debug range, run the source debugger */
+    debug_xt_item = debug_xt_list;
+    while (debug_xt_item->next) {
+        if (PC >= debug_xt_item->xt_docol && PC <= debug_xt_item->xt_semis &&
+            debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+            do_source_dbg(debug_xt_item);
+        }
+
+        debug_xt_item = debug_xt_item->next;
+    }
+
+    dbg_interp_printk("next_dbg: PC is now %x\n", PC);
+
+    /* Intercept DOCOL and SEMIS and redirect to debug versions */
+    if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOCOL) {
+        tokenp = docol_dbg;
+        tokenp();
+    } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOSEMIS) {
+        tokenp = semis_dbg;
+        tokenp();
+    } else {
+        /* Otherwise process as normal */
+        processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+    }
+}
+
+static void
+do_debug_xt(void)
+{
+    ucell xt = POP();
+
+    /* Add to the debug list */
+    if (add_debug_xt(xt)) {
+        /* Display debug banner */
+        printf_console(DEBUG_BANNER);
+
+        /* Indicate change to debug mode */
+        interruptforth |= FORTH_INTSTAT_DBG;
+    }
+}
+
+static void
+do_debug_off(void)
+{
+    /* Empty the debug xt linked list */
+    while (debug_xt_list->next != NULL) {
+        del_debug_xt(debug_xt_list->xt_docol);
+    }
+}
+
+/*
+ * Forth primitives needed to set up
+ * all the words described in IEEE1275-1994.
+ */
+
 /*
  *  dup         ( x -- x x )
  */
@@ -1019,3 +1847,120 @@
 {
 	PUSH(rstack[rstackcnt - 2]);
 }
+
+/* words[] is a function array of all native code functions used by
+ * the dictionary, i.e. CFAs and primitives.
+ * Any change here needs a matching change in the primitive word's
+ * name list that is kept for bootstrapping in kernel/bootstrap.c
+ *
+ * NOTE: THIS LIST SHALL NOT CHANGE (EXCEPT MANDATORY ADDITIONS AT
+ * THE END). ANY OTHER CHANGE WILL BREAK COMPATIBILITY TO OLDER
+ * BINARY DICTIONARIES.
+ */
+static forth_word * const words[] = {
+    /*
+     * CFAs and special words
+     */
+    semis,
+    docol,
+    lit,
+    docon,
+    dovar,
+    dodefer,
+    dodoes,
+    dodo,
+    doisdo,
+    doloop,
+    doplusloop,
+    doival,
+    doivar,
+    doidefer,
+
+    /*
+     * primitives
+     */
+    fdup,                   /* dup     */
+    twodup,                 /* 2dup    */
+    isdup,                  /* ?dup    */
+    over,                   /* over    */
+    twoover,                /* 2over   */
+    pick,                   /* pick    */
+    drop,                   /* drop    */
+    twodrop,                /* 2drop   */
+    nip,                    /* nip     */
+    roll,                   /* roll    */
+    rot,                    /* rot     */
+    minusrot,               /* -rot    */
+    swap,                   /* swap    */
+    twoswap,                /* 2swap   */
+    tor,                    /* >r      */
+    rto,                    /* r>      */
+    rfetch,                 /* r@      */
+    depth,                  /* depth   */
+    depthwrite,             /* depth!  */
+    rdepth,                 /* rdepth  */
+    rdepthwrite,            /* rdepth! */
+    plus,                   /* +       */
+    minus,                  /* -       */
+    mult,                   /* *       */
+    umult,                  /* u*      */
+    mudivmod,               /* mu/mod  */
+    forthabs,               /* abs     */
+    negate,                 /* negate  */
+    max,                    /* max     */
+    min,                    /* min     */
+    lshift,                 /* lshift  */
+    rshift,                 /* rshift  */
+    rshifta,                /* >>a     */
+    and,                    /* and     */
+    or,                     /* or      */
+    xor,                    /* xor     */
+    invert,                 /* invert  */
+    dplus,                  /* d+      */
+    dminus,                 /* d-      */
+    mmult,                  /* m*      */
+    ummult,                 /* um*     */
+    fetch,                  /* @       */
+    cfetch,                 /* c@      */
+    wfetch,                 /* w@      */
+    lfetch,                 /* l@      */
+    store,                  /* !       */
+    plusstore,              /* +!      */
+    cstore,                 /* c!      */
+    wstore,                 /* w!      */
+    lstore,                 /* l!      */
+    equals,                 /* =       */
+    greater,                /* >       */
+    less,                   /* <       */
+    ugreater,               /* u>      */
+    uless,                  /* u<      */
+    spfetch,                /* sp@     */
+    fmove,                  /* move    */
+    ffill,                  /* fill    */
+    emit,                   /* emit    */
+    iskey,                  /* key?    */
+    key,                    /* key     */
+    execute,                /* execute */
+    here,                   /* here    */
+    herewrite,              /* here!   */
+    dobranch,               /* dobranch     */
+    docbranch,              /* do?branch    */
+    unalignedwordread,      /* unaligned-w@ */
+    unalignedwordwrite,     /* unaligned-w! */
+    unalignedlongread,      /* unaligned-l@ */
+    unalignedlongwrite,     /* unaligned-l! */
+    iocfetch,               /* ioc@    */
+    iowfetch,               /* iow@    */
+    iolfetch,               /* iol@    */
+    iocstore,               /* ioc!    */
+    iowstore,               /* iow!    */
+    iolstore,               /* iol!    */
+    loop_i,                 /* i       */
+    loop_j,                 /* j       */
+    call,                   /* call    */
+    sysdebug,               /* sys-debug */
+    do_include,             /* $include */
+    do_encode_file,         /* $encode-file */
+    do_debug_xt,            /* (debug  */
+    do_debug_off,           /* (debug-off) */
+};



More information about the OpenBIOS mailing list