Annotation of qemu/roms/openbios/kernel/forth.c, revision 1.1.1.1

1.1       root        1: /* tag: C implementation of all forth primitives,
                      2:  * internal words, inner interpreter and such
                      3:  *
                      4:  * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
                      5:  *
                      6:  * See the file "COPYING" for further information about
                      7:  * the copyright and warranty status of this work.
                      8:  */
                      9: 
                     10: #include "config.h"
                     11: #include "sysinclude.h"
                     12: #include "kernel/stack.h"
                     13: #include "kernel/kernel.h"
                     14: #include "dict.h"
                     15: 
                     16: /*
                     17:  * cross platform abstraction
                     18:  */
                     19: 
                     20: #include "cross.h"
                     21: 
                     22: #ifndef FCOMPILER
                     23: #include "libc/vsprintf.h"
                     24: #else
                     25: #include <stdarg.h>
                     26: #endif
                     27: 
                     28: /*
                     29:  * execution works as follows:
                     30:  *  - PC is pushed on return stack
                     31:  *  - PC is set to new CFA
                     32:  *  - address pointed by CFA is executed by CPU
                     33:  */
                     34: 
                     35: typedef void forth_word(void);
                     36: 
                     37: static forth_word * const words[];
                     38: ucell PC;
                     39: volatile int interruptforth = 0;
                     40: 
                     41: #define DEBUG_MODE_NONE 0
                     42: #define DEBUG_MODE_STEP 1
                     43: #define DEBUG_MODE_TRACE 2
                     44: #define DEBUG_MODE_STEPUP 3
                     45: 
                     46: #define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n"
                     47: 
                     48: /* Empty linked list of debug xts */
                     49: struct debug_xt {
                     50:     ucell xt_docol;
                     51:     ucell xt_semis;
                     52:     int mode;
                     53:     struct debug_xt *next;
                     54: };
                     55: 
                     56: static struct debug_xt debug_xt_eol = { (ucell)0, (ucell)0, 0, NULL};
                     57: static struct debug_xt *debug_xt_list = &debug_xt_eol;
                     58: 
                     59: /* Static buffer for xt name */
                     60: char xtname[MAXNFALEN];
                     61: 
                     62: #ifndef FCOMPILER
                     63: /* instead of pointing to an explicit 0 variable we
                     64:  * point behind the pointer.
                     65:  */
                     66: static ucell t[] = { 0, 0, 0, 0 };
                     67: static ucell *trampoline = t;
                     68: 
                     69: /*
                     70:  * Code Field Address (CFA) definitions (DOCOL and the like)
                     71:  */
                     72: 
                     73: void forth_init(void)
                     74: {
                     75:     init_trampoline(trampoline);
                     76: }
                     77: #endif
                     78: 
                     79: #ifndef CONFIG_DEBUG_INTERPRETER
                     80: #define dbg_interp_printk( a... )       do { } while(0)
                     81: #else
                     82: #define dbg_interp_printk( a... )       printk( a )
                     83: #endif
                     84: 
                     85: #ifndef CONFIG_DEBUG_INTERNAL
                     86: #define dbg_internal_printk( a... )     do { } while(0)
                     87: #else
                     88: #define dbg_internal_printk( a... )     printk( a )
                     89: #endif
                     90: 
                     91: 
                     92: void init_trampoline(ucell *tramp)
                     93: {
                     94:     tramp[0] = DOCOL;
                     95:     tramp[1] = 0;
                     96:     tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell));
                     97:     tramp[3] = 0;
                     98: }
                     99: 
                    100: static inline void processxt(ucell xt)
                    101: {
                    102:     void (*tokenp) (void);
                    103: 
                    104:     dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC, xt);
                    105:     tokenp = words[xt];
                    106:     tokenp();
                    107: }
                    108: 
                    109: static void docol(void)
                    110: {                               /* DOCOL */
                    111:     PUSHR(PC);
                    112:     PC = read_ucell(cell2pointer(PC));
                    113: 
                    114:     dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC - sizeof(cell)) ));
                    115: }
                    116: 
                    117: static void semis(void)
                    118: {
                    119:     PC = POPR();
                    120: }
                    121: 
                    122: static inline void next(void)
                    123: {
                    124:     PC += sizeof(ucell);
                    125: 
                    126:     dbg_interp_printk("next: PC is now %x\n", PC);
                    127:     processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
                    128: }
                    129: 
                    130: static inline void next_dbg(void);
                    131: 
                    132: int enterforth(xt_t xt)
                    133: {
                    134:     ucell *_cfa = (ucell*)cell2pointer(xt);
                    135:     cell tmp;
                    136: 
                    137:     if (read_ucell(_cfa) != DOCOL) {
                    138:         trampoline[1] = target_ucell(xt);
                    139:         _cfa = trampoline;
                    140:     }
                    141: 
                    142:     if (rstackcnt < 0) {
                    143:         rstackcnt = 0;
                    144:     }
                    145: 
                    146:     tmp = rstackcnt;
                    147:     interruptforth = FORTH_INTSTAT_CLR;
                    148: 
                    149:     PUSHR(PC);
                    150:     PC = pointer2cell(_cfa);
                    151: 
                    152:     while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) {
                    153:         if (debug_xt_list->next == NULL) {
                    154:             while (rstackcnt > tmp && !interruptforth) {
                    155:                 dbg_interp_printk("enterforth: NEXT\n");
                    156:                 next();
                    157:             }
                    158:         } else {
                    159:             while (rstackcnt > tmp && !interruptforth) {
                    160:                 dbg_interp_printk("enterforth: NEXT_DBG\n");
                    161:                 next_dbg();
                    162:             }
                    163:         }
                    164: 
                    165:         /* Always clear the debug mode change flag */
                    166:         interruptforth = interruptforth & (~FORTH_INTSTAT_DBG);
                    167:     }
                    168: 
                    169: #if 0
                    170:     /* return true if we took an exception. The caller should normally
                    171:      * handle exceptions by returning immediately since the throw
                    172:      * is supposed to abort the execution of this C-code too.
                    173:      */
                    174: 
                    175:     if (rstackcnt != tmp) {
                    176:         printk("EXCEPTION DETECTED!\n");
                    177:     }
                    178: #endif
                    179:     return rstackcnt != tmp;
                    180: }
                    181: 
                    182: /* called inline thus a slightly different behaviour */
                    183: static void lit(void)
                    184: {                               /* LIT */
                    185:     PC += sizeof(cell);
                    186:     PUSH(read_ucell(cell2pointer(PC)));
                    187:     dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC)));
                    188: }
                    189: 
                    190: static void docon(void)
                    191: {                               /* DOCON */
                    192:     ucell tmp = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
                    193:     PUSH(tmp);
                    194:     dbg_interp_printk("docon: PC=%x, value=%x\n", PC, tmp);
                    195: }
                    196: 
                    197: static void dovar(void)
                    198: {                               /* DOVAR */
                    199:     ucell tmp = read_ucell(cell2pointer(PC)) + sizeof(ucell);
                    200:     PUSH(tmp);              /* returns address to variable */
                    201:     dbg_interp_printk("dovar: PC: %x, %x\n", PC, tmp);
                    202: }
                    203: 
                    204: static void dobranch(void)
                    205: {                               /* unconditional branch */
                    206:     PC += sizeof(cell);
                    207:     PC += read_cell(cell2pointer(PC));
                    208: }
                    209: 
                    210: static void docbranch(void)
                    211: {                               /* conditional branch */
                    212:     PC += sizeof(cell);
                    213:     if (POP()) {
                    214:         dbg_internal_printk("  ?branch: end loop\n");
                    215:     } else {
                    216:         dbg_internal_printk("  ?branch: follow branch\n");
                    217:         PC += read_cell(cell2pointer(PC));
                    218:     }
                    219: }
                    220: 
                    221: 
                    222: static void execute(void)
                    223: {                               /* EXECUTE */
                    224:     ucell address = POP();
                    225:     dbg_interp_printk("execute: %x\n", address);
                    226: 
                    227:     PUSHR(PC);
                    228:     trampoline[1] = target_ucell(address);
                    229:     PC = pointer2cell(trampoline);
                    230: }
                    231: 
                    232: /*
                    233:  * call ( ... function-ptr -- ??? )
                    234:  */
                    235: static void call(void)
                    236: {
                    237: #ifdef FCOMPILER
                    238:     printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n");
                    239:     exit(1);
                    240: #else
                    241:     void (*funcptr) (void);
                    242:     funcptr=(void *)cell2pointer(POP());
                    243:     dbg_interp_printk("call: %x", funcptr);
                    244:     funcptr();
                    245: #endif
                    246: }
                    247: 
                    248: /*
                    249:  * sys-debug ( errno -- )
                    250:  */
                    251: 
                    252: static void sysdebug(void)
                    253: {
                    254: #ifdef FCOMPILER
                    255:     cell errorno=POP();
                    256:     exception(errorno);
                    257: #else
                    258:     (void) POP();
                    259: #endif
                    260: }
                    261: 
                    262: static void dodoes(void)
                    263: {                               /* DODOES */
                    264:     ucell data = read_ucell(cell2pointer(PC)) + (2 * sizeof(ucell));
                    265:     ucell word = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
                    266: 
                    267:     dbg_interp_printk("DODOES data=%x word=%x\n", data, word);
                    268: 
                    269:     PUSH(data);
                    270:     PUSH(word);
                    271: 
                    272:     execute();
                    273: }
                    274: 
                    275: static void dodefer(void)
                    276: {
                    277:     docol();
                    278: }
                    279: 
                    280: static void dodo(void)
                    281: {
                    282:     cell startval, endval;
                    283:     startval = POP();
                    284:     endval = POP();
                    285: 
                    286:     PUSHR(endval);
                    287:     PUSHR(startval);
                    288: }
                    289: 
                    290: static void doisdo(void)
                    291: {
                    292:     cell startval, endval, offset;
                    293: 
                    294:     startval = POP();
                    295:     endval = POP();
                    296: 
                    297:     PC += sizeof(cell);
                    298: 
                    299:     if (startval == endval) {
                    300:         offset = read_cell(cell2pointer(PC));
                    301:         PC += offset;
                    302:     } else {
                    303:         PUSHR(endval);
                    304:         PUSHR(startval);
                    305:     }
                    306: }
                    307: 
                    308: static void doloop(void)
                    309: {
                    310:     cell offset, startval, endval;
                    311: 
                    312:     startval = POPR() + 1;
                    313:     endval = POPR();
                    314: 
                    315:     PC += sizeof(cell);
                    316: 
                    317:     if (startval < endval) {
                    318:         offset = read_cell(cell2pointer(PC));
                    319:         PC += offset;
                    320:         PUSHR(endval);
                    321:         PUSHR(startval);
                    322:     }
                    323: 
                    324: }
                    325: 
                    326: static void doplusloop(void)
                    327: {
                    328:     ucell high, low;
                    329:     cell increment, startval, endval, offset;
                    330: 
                    331:     increment = POP();
                    332: 
                    333:     startval = POPR();
                    334:     endval = POPR();
                    335: 
                    336:     low = (ucell) startval;
                    337:     startval += increment;
                    338: 
                    339:     PC += sizeof(cell);
                    340: 
                    341:     if (increment >= 0) {
                    342:         high = (ucell) startval;
                    343:     } else {
                    344:         high = low;
                    345:         low = (ucell) startval;
                    346:     }
                    347: 
                    348:     if (endval - (low + 1) >= high - low) {
                    349:         offset = read_cell(cell2pointer(PC));
                    350:         PC += offset;
                    351: 
                    352:         PUSHR(endval);
                    353:         PUSHR(startval);
                    354:     }
                    355: }
                    356: 
                    357: /*
                    358:  *  instance handling CFAs
                    359:  */
                    360: #ifndef FCOMPILER
                    361: static ucell get_myself(void)
                    362: {
                    363:     static ucell *myselfptr = NULL;
                    364:     if (myselfptr == NULL) {
                    365:         myselfptr = (ucell*)cell2pointer(findword("my-self")) + 1;
                    366:     }
                    367:     ucell *myself = (ucell*)cell2pointer(*myselfptr);
                    368:     return (myself != NULL) ? *myself : 0;
                    369: }
                    370: 
                    371: static void doivar(void)
                    372: {
                    373:     ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
                    374:     ucell ibase = get_myself();
                    375: 
                    376:     dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p[0], p[1], ibase );
                    377: 
                    378:     r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
                    379:     PUSH( r );
                    380: }
                    381: 
                    382: static void doival(void)
                    383: {
                    384:     ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
                    385:     ucell ibase = get_myself();
                    386: 
                    387:     dbg_interp_printk("ivar, offset: %d size: %d\n", p[0], p[1] );
                    388: 
                    389:     r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
                    390:     PUSH( *(ucell *)cell2pointer(r) );
                    391: }
                    392: 
                    393: static void doidefer(void)
                    394: {
                    395:     ucell *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
                    396:     ucell ibase = get_myself();
                    397: 
                    398:     dbg_interp_printk("doidefer, offset: %d size: %d\n", p[0], p[1] );
                    399: 
                    400:     PUSHR(PC);
                    401:     PC = ibase ? ibase + p[0] : pointer2cell(&p[2]);
                    402:     PC -= sizeof(ucell);
                    403: }
                    404: #else
                    405: static void noinstances(void)
                    406: {
                    407:     printk("Opening devices is not supported during bootstrap. Sorry.\n");
                    408:     exit(1);
                    409: }
                    410: #define doivar   noinstances
                    411: #define doival   noinstances
                    412: #define doidefer noinstances
                    413: #endif
                    414: 
                    415: /*
                    416:  * $include / $encode-file
                    417:  */
                    418: #ifdef FCOMPILER
                    419: static void
                    420: string_relay(void (*func)(const char *))
                    421: {
                    422:     int len = POP();
                    423:     char *name, *p = (char*)cell2pointer(POP());
                    424:     name = malloc(len + 1);
                    425:     memcpy(name, p, len);
                    426:     name[len] = 0;
                    427:     (*func)(name);
                    428:     free(name);
                    429: }
                    430: #else
                    431: #define string_relay(dummy) do { DROP(); DROP(); } while(0)
                    432: #endif
                    433: 
                    434: static void
                    435: do_include(void)
                    436: {
                    437:     string_relay(&include_file);
                    438: }
                    439: 
                    440: static void
                    441: do_encode_file( void )
                    442: {
                    443:     string_relay(&encode_file);
                    444: }
                    445: 
                    446: /*
                    447:  * Debug support functions
                    448:  */
                    449: 
                    450: static
                    451: int printf_console(const char *fmt, ...)
                    452: {
                    453:     cell tmp;
                    454: 
                    455:     char buf[512];
                    456:     va_list args;
                    457:     int i;
                    458: 
                    459:     va_start(args, fmt);
                    460:     i = vsnprintf(buf, sizeof(buf), fmt, args);
                    461:     va_end(args);
                    462: 
                    463:     /* Push to the Forth interpreter for console output */
                    464:     tmp = rstackcnt;
                    465: 
                    466:     PUSH(pointer2cell(buf));
                    467:     PUSH((int)strlen(buf));
                    468:     trampoline[1] = findword("type");
                    469: 
                    470:     PUSHR(PC);
                    471:     PC = pointer2cell(trampoline);
                    472: 
                    473:     while (rstackcnt > tmp) {
                    474:         dbg_interp_printk("printf_console: NEXT\n");
                    475:         next();
                    476:     }
                    477: 
                    478:     return i;
                    479: }
                    480: 
                    481: static
                    482: int getchar_console(void)
                    483: {
                    484:     cell tmp;
                    485: 
                    486:     /* Push to the Forth interpreter for console output */
                    487:     tmp = rstackcnt;
                    488: 
                    489:     trampoline[1] = findword("key");
                    490: 
                    491:     PUSHR(PC);
                    492:     PC = pointer2cell(trampoline);
                    493: 
                    494:     while (rstackcnt > tmp) {
                    495:         dbg_interp_printk("getchar_console: NEXT\n");
                    496:         next();
                    497:     }
                    498: 
                    499:     return POP();
                    500: }
                    501: 
                    502: static void
                    503: display_dbg_dstack(void)
                    504: {
                    505:     /* Display dstack contents between parentheses */
                    506:     int i;
                    507: 
                    508:     if (dstackcnt == 0) {
                    509:         printf_console(" ( Empty ) ");
                    510:         return;
                    511:     } else {
                    512:         printf_console(" ( ");
                    513:         for (i = 1; i <= dstackcnt; i++) {
                    514:             if (i != 1) {
                    515:                 printf_console(" ");
                    516:             }
                    517:             printf_console("%" FMT_CELL_x, dstack[i]);
                    518:         }
                    519:         printf_console(" ) ");
                    520:     }
                    521: }
                    522: 
                    523: static void
                    524: display_dbg_rstack(void)
                    525: {
                    526:     /* Display rstack contents between parentheses */
                    527:     int i;
                    528: 
                    529:     if (rstackcnt == 0) {
                    530:         printf_console(" ( Empty ) ");
                    531:         return;
                    532:     } else {
                    533:         printf_console("\nR: ( ");
                    534:         for (i = 1; i <= rstackcnt; i++) {
                    535:             if (i != 1) {
                    536:                 printf_console(" ");
                    537:             }
                    538:             printf_console("%" FMT_CELL_x, rstack[i]);
                    539:         }
                    540:         printf_console(" ) \n");
                    541:     }
                    542: }
                    543: 
                    544: static int
                    545: add_debug_xt(ucell xt)
                    546: {
                    547:     struct debug_xt *debug_xt_item;
                    548: 
                    549:     /* If the xt CFA isn't DOCOL then issue a warning and do nothing */
                    550:     if (read_ucell(cell2pointer(xt)) != DOCOL) {
                    551:         printf_console("\nprimitive words cannot be debugged\n");
                    552:         return 0;
                    553:     }
                    554: 
                    555:     /* If this xt is already in the list, do nothing but indicate success */
                    556:     for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
                    557:          debug_xt_item = debug_xt_item->next)
                    558:         if (debug_xt_item->xt_docol == xt) {
                    559:             return 1;
                    560:         }
                    561: 
                    562:     /* We already have the CFA (PC) indicating the starting cell of
                    563:        the word, however we also need the ending cell too (we cannot
                    564:        rely on the rstack as it can be arbitrarily changed by a forth
                    565:        word). Hence the use of findsemis() */
                    566: 
                    567:     /* Otherwise add to the head of the linked list */
                    568:     debug_xt_item = malloc(sizeof(struct debug_xt));
                    569:     debug_xt_item->xt_docol = xt;
                    570:     debug_xt_item->xt_semis = findsemis(xt);
                    571:     debug_xt_item->mode = DEBUG_MODE_NONE;
                    572:     debug_xt_item->next = debug_xt_list;
                    573:     debug_xt_list = debug_xt_item;
                    574: 
                    575:     /* Indicate debug mode change */
                    576:     interruptforth |= FORTH_INTSTAT_DBG;
                    577: 
                    578:     /* Success */
                    579:     return 1;
                    580: }
                    581: 
                    582: static void
                    583: del_debug_xt(ucell xt)
                    584: {
                    585:     struct debug_xt *debug_xt_item, *tmp_xt_item;
                    586: 
                    587:     /* Handle the case where the xt is at the head of the list */
                    588:     if (debug_xt_list->xt_docol == xt) {
                    589:         tmp_xt_item = debug_xt_list;
                    590:         debug_xt_list = debug_xt_list->next;
                    591:         free(tmp_xt_item);
                    592: 
                    593:         return;
                    594:     }
                    595: 
                    596:     /* Otherwise find this xt in the linked list and remove it */
                    597:     for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
                    598:          debug_xt_item = debug_xt_item->next) {
                    599:         if (debug_xt_item->next->xt_docol == xt) {
                    600:             tmp_xt_item = debug_xt_item->next;
                    601:             debug_xt_item->next = debug_xt_item->next->next;
                    602:             free(tmp_xt_item);
                    603:         }
                    604:     }
                    605: 
                    606:     /* If the list is now empty, indicate debug mode change */
                    607:     if (debug_xt_list->next == NULL) {
                    608:         interruptforth |= FORTH_INTSTAT_DBG;
                    609:     }
                    610: }
                    611: 
                    612: static void
                    613: do_source_dbg(struct debug_xt *debug_xt_item)
                    614: {
                    615:     /* Forth source debugger implementation */
                    616:     char k, done = 0;
                    617: 
                    618:     /* Display current dstack */
                    619:     display_dbg_dstack();
                    620:     printf_console("\n");
                    621: 
                    622:     fstrncpy(xtname, lfa2nfa(read_ucell(cell2pointer(PC)) - sizeof(cell)), MAXNFALEN);
                    623:     printf_console("%p: %s ", cell2pointer(PC), xtname);
                    624: 
                    625:     /* If in trace mode, we just carry on */
                    626:     if (debug_xt_item->mode == DEBUG_MODE_TRACE) {
                    627:         return;
                    628:     }
                    629: 
                    630:     /* Otherwise in step mode, prompt for a keypress */
                    631:     k = getchar_console();
                    632: 
                    633:     /* Only proceed if done is true */
                    634:     while (!done) {
                    635:         switch (k) {
                    636: 
                    637:         case ' ':
                    638:         case '\n':
                    639:             /* Perform a single step */
                    640:             done = 1;
                    641:             break;
                    642: 
                    643:         case 'u':
                    644:         case 'U':
                    645:             /* Up - unmark current word for debug, mark its caller for
                    646:              * debugging and finish executing current word */
                    647: 
                    648:             /* Since this word could alter the rstack during its execution,
                    649:              * we only know the caller when (semis) is called for this xt.
                    650:              * Hence we mark the xt as a special DEBUG_MODE_STEPUP which
                    651:              * means we run as normal, but schedule the xt for deletion
                    652:              * at its corresponding (semis) word when we know the rstack
                    653:              * will be set to its final parent value */
                    654:             debug_xt_item->mode = DEBUG_MODE_STEPUP;
                    655:             done = 1;
                    656:             break;
                    657: 
                    658:         case 'd':
                    659:         case 'D':
                    660:             /* Down - mark current word for debug and step into it */
                    661:             done = add_debug_xt(read_ucell(cell2pointer(PC)));
                    662:             if (!done) {
                    663:                 k = getchar_console();
                    664:             }
                    665:             break;
                    666: 
                    667:         case 't':
                    668:         case 'T':
                    669:             /* Trace mode */
                    670:             debug_xt_item->mode = DEBUG_MODE_TRACE;
                    671:             done = 1;
                    672:             break;
                    673: 
                    674:         case 'r':
                    675:         case 'R':
                    676:             /* Display rstack */
                    677:             display_dbg_rstack();
                    678:             done = 0;
                    679:             k = getchar_console();
                    680:             break;
                    681: 
                    682:         case 'f':
                    683:         case 'F':
                    684:             /* Start subordinate Forth interpreter */
                    685:             PUSHR(PC - sizeof(cell));
                    686:             PC = findword("outer-interpreter") + sizeof(ucell);
                    687: 
                    688:             /* Save rstack position for when we return */
                    689:             dbgrstackcnt = rstackcnt;
                    690:             done = 1;
                    691:             break;
                    692: 
                    693:         default:
                    694:             /* Display debug banner */
                    695:             printf_console(DEBUG_BANNER);
                    696:             k = getchar_console();
                    697:         }
                    698:     }
                    699: }
                    700: 
                    701: static void docol_dbg(void)
                    702: {                               /* DOCOL */
                    703:     struct debug_xt *debug_xt_item;
                    704: 
                    705:     PUSHR(PC);
                    706:     PC = read_ucell(cell2pointer(PC));
                    707: 
                    708:     /* If current xt is in our debug xt list, display word name */
                    709:     debug_xt_item = debug_xt_list;
                    710:     while (debug_xt_item->next) {
                    711:         if (debug_xt_item->xt_docol == PC) {
                    712:             fstrncpy(xtname, lfa2nfa(PC - sizeof(cell)), MAXNFALEN);
                    713:             printf_console("\n: %s ", xtname);
                    714: 
                    715:             /* Step mode is the default */
                    716:             debug_xt_item->mode = DEBUG_MODE_STEP;
                    717:         }
                    718: 
                    719:         debug_xt_item = debug_xt_item->next;
                    720:     }
                    721: 
                    722:     dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC - sizeof(cell))));
                    723: }
                    724: 
                    725: static void semis_dbg(void)
                    726: {
                    727:     struct debug_xt *debug_xt_item, *debug_xt_up = NULL;
                    728: 
                    729:     /* If current semis is in our debug xt list, disable debug mode */
                    730:     debug_xt_item = debug_xt_list;
                    731:     while (debug_xt_item->next) {
                    732:         if (debug_xt_item->xt_semis == PC) {
                    733:             if (debug_xt_item->mode != DEBUG_MODE_STEPUP) {
                    734:                 /* Handle the normal case */
                    735:                 fstrncpy(xtname, lfa2nfa(debug_xt_item->xt_docol - sizeof(cell)), MAXNFALEN);
                    736:                 printf_console("\n[ Finished %s ] ", xtname);
                    737: 
                    738:                 /* Reset to step mode in case we were in trace mode */
                    739:                 debug_xt_item->mode = DEBUG_MODE_STEP;
                    740:             } else {
                    741:                 /* This word requires execution of the debugger "Up"
                    742:                  * semantics. However we can't do this here since we
                    743:                  * are iterating through the debug list, and we need
                    744:                  * to change it. So we do it afterwards.
                    745:                  */
                    746:                 debug_xt_up = debug_xt_item;
                    747:             }
                    748:         }
                    749: 
                    750:         debug_xt_item = debug_xt_item->next;
                    751:     }
                    752: 
                    753:     /* Execute debugger "Up" semantics if required */
                    754:     if (debug_xt_up) {
                    755:         /* Only add the parent word if it is not within the trampoline */
                    756:         if (rstack[rstackcnt] != (cell)pointer2cell(&trampoline[1])) {
                    757:             del_debug_xt(debug_xt_up->xt_docol);
                    758:             add_debug_xt(findxtfromcell(rstack[rstackcnt]));
                    759: 
                    760:             fstrncpy(xtname, lfa2nfa(findxtfromcell(rstack[rstackcnt]) - sizeof(cell)), MAXNFALEN);
                    761:             printf_console("\n[ Up to %s ] ", xtname);
                    762:         } else {
                    763:             fstrncpy(xtname, lfa2nfa(findxtfromcell(debug_xt_up->xt_docol) - sizeof(cell)), MAXNFALEN);
                    764:             printf_console("\n[ Finished %s (Unable to go up, hit trampoline) ] ", xtname);
                    765: 
                    766:             del_debug_xt(debug_xt_up->xt_docol);
                    767:         }
                    768: 
                    769:         debug_xt_up = NULL;
                    770:     }
                    771: 
                    772:     PC = POPR();
                    773: }
                    774: 
                    775: static inline void next_dbg(void)
                    776: {
                    777:     struct debug_xt *debug_xt_item;
                    778:     void (*tokenp) (void);
                    779: 
                    780:     PC += sizeof(ucell);
                    781: 
                    782:     /* If the PC lies within a debug range, run the source debugger */
                    783:     debug_xt_item = debug_xt_list;
                    784:     while (debug_xt_item->next) {
                    785:         if (PC >= debug_xt_item->xt_docol && PC <= debug_xt_item->xt_semis &&
                    786:             debug_xt_item->mode != DEBUG_MODE_STEPUP) {
                    787:             do_source_dbg(debug_xt_item);
                    788:         }
                    789: 
                    790:         debug_xt_item = debug_xt_item->next;
                    791:     }
                    792: 
                    793:     dbg_interp_printk("next_dbg: PC is now %x\n", PC);
                    794: 
                    795:     /* Intercept DOCOL and SEMIS and redirect to debug versions */
                    796:     if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOCOL) {
                    797:         tokenp = docol_dbg;
                    798:         tokenp();
                    799:     } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOSEMIS) {
                    800:         tokenp = semis_dbg;
                    801:         tokenp();
                    802:     } else {
                    803:         /* Otherwise process as normal */
                    804:         processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
                    805:     }
                    806: }
                    807: 
                    808: static void
                    809: do_debug_xt(void)
                    810: {
                    811:     ucell xt = POP();
                    812: 
                    813:     /* Add to the debug list */
                    814:     if (add_debug_xt(xt)) {
                    815:         /* Display debug banner */
                    816:         printf_console(DEBUG_BANNER);
                    817: 
                    818:         /* Indicate change to debug mode */
                    819:         interruptforth |= FORTH_INTSTAT_DBG;
                    820:     }
                    821: }
                    822: 
                    823: static void
                    824: do_debug_off(void)
                    825: {
                    826:     /* Empty the debug xt linked list */
                    827:     while (debug_xt_list->next != NULL) {
                    828:         del_debug_xt(debug_xt_list->xt_docol);
                    829:     }
                    830: }
                    831: 
                    832: /*
                    833:  * Forth primitives needed to set up
                    834:  * all the words described in IEEE1275-1994.
                    835:  */
                    836: 
                    837: /*
                    838:  *  dup         ( x -- x x )
                    839:  */
                    840: 
                    841: static void fdup(void)
                    842: {
                    843:        const cell tmp = GETTOS();
                    844:        PUSH(tmp);
                    845: }
                    846: 
                    847: 
                    848: /*
                    849:  *  2dup        ( x1 x2 -- x1 x2 x1 x2 )
                    850:  */
                    851: 
                    852: static void twodup(void)
                    853: {
                    854:        cell tmp = GETITEM(1);
                    855:        PUSH(tmp);
                    856:        tmp = GETITEM(1);
                    857:        PUSH(tmp);
                    858: }
                    859: 
                    860: 
                    861: /*
                    862:  *  ?dup        ( x -- 0 | x x )
                    863:  */
                    864: 
                    865: static void isdup(void)
                    866: {
                    867:        const cell tmp = GETTOS();
                    868:        if (tmp)
                    869:                PUSH(tmp);
                    870: }
                    871: 
                    872: 
                    873: /*
                    874:  *  over        ( x y -- x y x )
                    875:  */
                    876: 
                    877: static void over(void)
                    878: {
                    879:        const cell tmp = GETITEM(1);
                    880:        PUSH(tmp);
                    881: }
                    882: 
                    883: 
                    884: /*
                    885:  *  2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
                    886:  */
                    887: 
                    888: static void twoover(void)
                    889: {
                    890:        const cell tmp = GETITEM(3);
                    891:        const cell tmp2 = GETITEM(2);
                    892:        PUSH(tmp);
                    893:        PUSH(tmp2);
                    894: }
                    895: 
                    896: /*
                    897:  *  pick        ( xu ... x1 x0 u -- xu ... x1 x0 xu )
                    898:  */
                    899: 
                    900: static void pick(void)
                    901: {
                    902:        const cell u = POP();
                    903:        if (dstackcnt >= u) {
                    904:                ucell tmp = dstack[dstackcnt - u];
                    905:                PUSH(tmp);
                    906:        } else {
                    907:                /* underrun */
                    908:        }
                    909: }
                    910: 
                    911: 
                    912: /*
                    913:  *  drop        ( x --  )
                    914:  */
                    915: 
                    916: static void drop(void)
                    917: {
                    918:        POP();
                    919: }
                    920: 
                    921: /*
                    922:  *  2drop       ( x1 x2 --  )
                    923:  */
                    924: 
                    925: static void twodrop(void)
                    926: {
                    927:        POP();
                    928:        POP();
                    929: }
                    930: 
                    931: 
                    932: /*
                    933:  *  nip         ( x1 x2 -- x2 )
                    934:  */
                    935: 
                    936: static void nip(void)
                    937: {
                    938:        const cell tmp = POP();
                    939:        POP();
                    940:        PUSH(tmp);
                    941: }
                    942: 
                    943: 
                    944: /*
                    945:  *  roll        ( xu ... x1 x0 u -- xu-1... x1 x0 xu )
                    946:  */
                    947: 
                    948: static void roll(void)
                    949: {
                    950:        const cell u = POP();
                    951:        if (dstackcnt >= u) {
                    952:                int i;
                    953:                const cell xu = dstack[dstackcnt - u];
                    954:                for (i = dstackcnt - u; i < dstackcnt; i++) {
                    955:                        dstack[i] = dstack[i + 1];
                    956:                }
                    957:                dstack[dstackcnt] = xu;
                    958:        } else {
                    959:                /* Stack underrun */
                    960:        }
                    961: }
                    962: 
                    963: 
                    964: /*
                    965:  *  rot         ( x1 x2 x3 -- x2 x3 x1 )
                    966:  */
                    967: 
                    968: static void rot(void)
                    969: {
                    970:        const cell tmp = POP();
                    971:        const cell tmp2 = POP();
                    972:        const cell tmp3 = POP();
                    973:        PUSH(tmp2);
                    974:        PUSH(tmp);
                    975:        PUSH(tmp3);
                    976: }
                    977: 
                    978: 
                    979: /*
                    980:  *  -rot        ( x1 x2 x3 -- x3 x1 x2 )
                    981:  */
                    982: 
                    983: static void minusrot(void)
                    984: {
                    985:        const cell tmp = POP();
                    986:        const cell tmp2 = POP();
                    987:        const cell tmp3 = POP();
                    988:        PUSH(tmp);
                    989:        PUSH(tmp3);
                    990:        PUSH(tmp2);
                    991: }
                    992: 
                    993: 
                    994: /*
                    995:  *  swap        ( x1 x2 -- x2 x1 )
                    996:  */
                    997: 
                    998: static void swap(void)
                    999: {
                   1000:        const cell tmp = POP();
                   1001:        const cell tmp2 = POP();
                   1002:        PUSH(tmp);
                   1003:        PUSH(tmp2);
                   1004: }
                   1005: 
                   1006: 
                   1007: /*
                   1008:  *  2swap       ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
                   1009:  */
                   1010: 
                   1011: static void twoswap(void)
                   1012: {
                   1013:        const cell tmp = POP();
                   1014:        const cell tmp2 = POP();
                   1015:        const cell tmp3 = POP();
                   1016:        const cell tmp4 = POP();
                   1017:        PUSH(tmp2);
                   1018:        PUSH(tmp);
                   1019:        PUSH(tmp4);
                   1020:        PUSH(tmp3);
                   1021: }
                   1022: 
                   1023: 
                   1024: /*
                   1025:  *  >r          ( x -- ) (R: -- x )
                   1026:  */
                   1027: 
                   1028: static void tor(void)
                   1029: {
                   1030:        ucell tmp = POP();
                   1031: #ifdef CONFIG_DEBUG_RSTACK
                   1032:        printk("  >R: %x\n", tmp);
                   1033: #endif
                   1034:        PUSHR(tmp);
                   1035: }
                   1036: 
                   1037: 
                   1038: /*
                   1039:  *  r>          ( -- x ) (R: x -- )
                   1040:  */
                   1041: 
                   1042: static void rto(void)
                   1043: {
                   1044:        ucell tmp = POPR();
                   1045: #ifdef CONFIG_DEBUG_RSTACK
                   1046:        printk("  R>: %x\n", tmp);
                   1047: #endif
                   1048:        PUSH(tmp);
                   1049: }
                   1050: 
                   1051: 
                   1052: /*
                   1053:  *  r@          ( -- x ) (R: x -- x )
                   1054:  */
                   1055: 
                   1056: static void rfetch(void)
                   1057: {
                   1058:        PUSH(GETTORS());
                   1059: }
                   1060: 
                   1061: 
                   1062: /*
                   1063:  *  depth       (  -- u )
                   1064:  */
                   1065: 
                   1066: static void depth(void)
                   1067: {
                   1068:        const cell tmp = dstackcnt;
                   1069:        PUSH(tmp);
                   1070: }
                   1071: 
                   1072: 
                   1073: /*
                   1074:  *  depth!      ( ... u --  x1 x2 .. xu )
                   1075:  */
                   1076: 
                   1077: static void depthwrite(void)
                   1078: {
                   1079:        ucell tmp = POP();
                   1080:        dstackcnt = tmp;
                   1081: }
                   1082: 
                   1083: 
                   1084: /*
                   1085:  *  rdepth      (  -- u )
                   1086:  */
                   1087: 
                   1088: static void rdepth(void)
                   1089: {
                   1090:        const cell tmp = rstackcnt;
                   1091:        PUSH(tmp);
                   1092: }
                   1093: 
                   1094: 
                   1095: /*
                   1096:  *  rdepth!     ( u --  ) ( R: ... -- x1 x2 .. xu )
                   1097:  */
                   1098: 
                   1099: static void rdepthwrite(void)
                   1100: {
                   1101:        ucell tmp = POP();
                   1102:        rstackcnt = tmp;
                   1103: }
                   1104: 
                   1105: 
                   1106: /*
                   1107:  *  +           ( nu1 nu2 -- sum )
                   1108:  */
                   1109: 
                   1110: static void plus(void)
                   1111: {
                   1112:        cell tmp = POP() + POP();
                   1113:        PUSH(tmp);
                   1114: }
                   1115: 
                   1116: 
                   1117: /*
                   1118:  *  -           ( nu1 nu2 -- diff )
                   1119:  */
                   1120: 
                   1121: static void minus(void)
                   1122: {
                   1123:        const cell nu2 = POP();
                   1124:        const cell nu1 = POP();
                   1125:        PUSH(nu1 - nu2);
                   1126: }
                   1127: 
                   1128: 
                   1129: /*
                   1130:  *  *           ( nu1 nu2 -- prod )
                   1131:  */
                   1132: 
                   1133: static void mult(void)
                   1134: {
                   1135:        const cell nu2 = POP();
                   1136:        const cell nu1 = POP();
                   1137:        PUSH(nu1 * nu2);
                   1138: }
                   1139: 
                   1140: 
                   1141: /*
                   1142:  *  u*          ( u1 u2 -- prod )
                   1143:  */
                   1144: 
                   1145: static void umult(void)
                   1146: {
                   1147:        const ucell tmp = (ucell) POP() * (ucell) POP();
                   1148:        PUSH(tmp);
                   1149: }
                   1150: 
                   1151: 
                   1152: /*
                   1153:  *  mu/mod      ( n1 n2 -- rem quot.l quot.h )
                   1154:  */
                   1155: 
                   1156: static void mudivmod(void)
                   1157: {
                   1158:        const ucell b = POP();
                   1159:        const ducell a = DPOP();
                   1160: #ifdef NEED_FAKE_INT128_T
                   1161:         if (a.hi != 0) {
                   1162:             fprintf(stderr, "mudivmod called (0x%016llx %016llx / 0x%016llx)\n",
                   1163:                     a.hi, a.lo, b);
                   1164:             exit(-1);
                   1165:         } else {
                   1166:             ducell c;
                   1167: 
                   1168:             PUSH(a.lo % b);
                   1169:             c.hi = 0;
                   1170:             c.lo = a.lo / b;
                   1171:             DPUSH(c);
                   1172:         }
                   1173: #else
                   1174:        PUSH(a % b);
                   1175:        DPUSH(a / b);
                   1176: #endif
                   1177: }
                   1178: 
                   1179: 
                   1180: /*
                   1181:  *  abs         ( n -- u )
                   1182:  */
                   1183: 
                   1184: static void forthabs(void)
                   1185: {
                   1186:        const cell tmp = GETTOS();
                   1187:        if (tmp < 0) {
                   1188:                POP();
                   1189:                PUSH(-tmp);
                   1190:        }
                   1191: }
                   1192: 
                   1193: 
                   1194: /*
                   1195:  *  negate      ( n1 -- n2 )
                   1196:  */
                   1197: 
                   1198: static void negate(void)
                   1199: {
                   1200:        const cell tmp = POP();
                   1201:        PUSH(-tmp);
                   1202: }
                   1203: 
                   1204: 
                   1205: /*
                   1206:  *  max         ( n1 n2 -- n1|n2 )
                   1207:  */
                   1208: 
                   1209: static void max(void)
                   1210: {
                   1211:        const cell tmp = POP();
                   1212:        const cell tmp2 = POP();
                   1213:        PUSH((tmp > tmp2) ? tmp : tmp2);
                   1214: }
                   1215: 
                   1216: 
                   1217: /*
                   1218:  *  min         ( n1 n2 -- n1|n2 )
                   1219:  */
                   1220: 
                   1221: static void min(void)
                   1222: {
                   1223:        const cell tmp = POP();
                   1224:        const cell tmp2 = POP();
                   1225:        PUSH((tmp < tmp2) ? tmp : tmp2);
                   1226: }
                   1227: 
                   1228: 
                   1229: /*
                   1230:  *  lshift      ( x1 u -- x2 )
                   1231:  */
                   1232: 
                   1233: static void lshift(void)
                   1234: {
                   1235:        const ucell u = POP();
                   1236:        const ucell x1 = POP();
                   1237:        PUSH(x1 << u);
                   1238: }
                   1239: 
                   1240: 
                   1241: /*
                   1242:  *  rshift      ( x1 u -- x2 )
                   1243:  */
                   1244: 
                   1245: static void rshift(void)
                   1246: {
                   1247:        const ucell u = POP();
                   1248:        const ucell x1 = POP();
                   1249:        PUSH(x1 >> u);
                   1250: }
                   1251: 
                   1252: 
                   1253: /*
                   1254:  *  >>a         ( x1 u -- x2 ) ??
                   1255:  */
                   1256: 
                   1257: static void rshifta(void)
                   1258: {
                   1259:        const cell u = POP();
                   1260:        const cell x1 = POP();
                   1261:        PUSH(x1 >> u);
                   1262: }
                   1263: 
                   1264: 
                   1265: /*
                   1266:  *  and         ( x1 x2 -- x3 )
                   1267:  */
                   1268: 
                   1269: static void and(void)
                   1270: {
                   1271:        const cell x1 = POP();
                   1272:        const cell x2 = POP();
                   1273:        PUSH(x1 & x2);
                   1274: }
                   1275: 
                   1276: 
                   1277: /*
                   1278:  *  or          ( x1 x2 -- x3 )
                   1279:  */
                   1280: 
                   1281: static void or(void)
                   1282: {
                   1283:        const cell x1 = POP();
                   1284:        const cell x2 = POP();
                   1285:        PUSH(x1 | x2);
                   1286: }
                   1287: 
                   1288: 
                   1289: /*
                   1290:  *  xor         ( x1 x2 -- x3 )
                   1291:  */
                   1292: 
                   1293: static void xor(void)
                   1294: {
                   1295:        const cell x1 = POP();
                   1296:        const cell x2 = POP();
                   1297:        PUSH(x1 ^ x2);
                   1298: }
                   1299: 
                   1300: 
                   1301: /*
                   1302:  *  invert      ( x1 -- x2 )
                   1303:  */
                   1304: 
                   1305: static void invert(void)
                   1306: {
                   1307:        const cell x1 = POP();
                   1308:        PUSH(x1 ^ -1);
                   1309: }
                   1310: 
                   1311: 
                   1312: /*
                   1313:  *  d+          ( d1 d2 -- d.sum )
                   1314:  */
                   1315: 
                   1316: static void dplus(void)
                   1317: {
                   1318:        const dcell d2 = DPOP();
                   1319:        const dcell d1 = DPOP();
                   1320: #ifdef NEED_FAKE_INT128_T
                   1321:         ducell c;
                   1322: 
                   1323:         if (d1.hi != 0 || d2.hi != 0) {
                   1324:             fprintf(stderr, "dplus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
                   1325:                     d1.hi, d1.lo, d2.hi, d2.lo);
                   1326:             exit(-1);
                   1327:         }
                   1328:         c.hi = 0;
                   1329:         c.lo = d1.lo + d2.lo;
                   1330:         DPUSH(c);
                   1331: #else
                   1332:        DPUSH(d1 + d2);
                   1333: #endif
                   1334: }
                   1335: 
                   1336: 
                   1337: /*
                   1338:  *  d-          ( d1 d2 -- d.diff )
                   1339:  */
                   1340: 
                   1341: static void dminus(void)
                   1342: {
                   1343:        const dcell d2 = DPOP();
                   1344:        const dcell d1 = DPOP();
                   1345: #ifdef NEED_FAKE_INT128_T
                   1346:         ducell c;
                   1347: 
                   1348:         if (d1.hi != 0 || d2.hi != 0) {
                   1349:             fprintf(stderr, "dminus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
                   1350:                     d1.hi, d1.lo, d2.hi, d2.lo);
                   1351:             exit(-1);
                   1352:         }
                   1353:         c.hi = 0;
                   1354:         c.lo = d1.lo - d2.lo;
                   1355:         DPUSH(c);
                   1356: #else
                   1357:        DPUSH(d1 - d2);
                   1358: #endif
                   1359: }
                   1360: 
                   1361: 
                   1362: /*
                   1363:  *  m*          ( ?? --  )
                   1364:  */
                   1365: 
                   1366: static void mmult(void)
                   1367: {
                   1368:        const cell u2 = POP();
                   1369:        const cell u1 = POP();
                   1370: #ifdef NEED_FAKE_INT128_T
                   1371:         ducell c;
                   1372: 
                   1373:         if (0) { // XXX How to detect overflow?
                   1374:             fprintf(stderr, "mmult called (%016llx * 0x%016llx)\n", u1, u2);
                   1375:             exit(-1);
                   1376:         }
                   1377:         c.hi = 0;
                   1378:         c.lo = u1 * u2;
                   1379:         DPUSH(c);
                   1380: #else
                   1381:        DPUSH((dcell) u1 * u2);
                   1382: #endif
                   1383: }
                   1384: 
                   1385: 
                   1386: /*
                   1387:  *  um*         ( u1 u2 -- d.prod )
                   1388:  */
                   1389: 
                   1390: static void ummult(void)
                   1391: {
                   1392:        const ucell u2 = POP();
                   1393:        const ucell u1 = POP();
                   1394: #ifdef NEED_FAKE_INT128_T
                   1395:         ducell c;
                   1396: 
                   1397:         if (0) { // XXX How to detect overflow?
                   1398:             fprintf(stderr, "ummult called (%016llx * 0x%016llx)\n", u1, u2);
                   1399:             exit(-1);
                   1400:         }
                   1401:         c.hi = 0;
                   1402:         c.lo = u1 * u2;
                   1403:         DPUSH(c);
                   1404: #else
                   1405:        DPUSH((ducell) u1 * u2);
                   1406: #endif
                   1407: }
                   1408: 
                   1409: 
                   1410: /*
                   1411:  *  @           ( a-addr -- x )
                   1412:  */
                   1413: 
                   1414: static void fetch(void)
                   1415: {
                   1416:        const ucell *aaddr = (ucell *)cell2pointer(POP());
                   1417:        PUSH(read_ucell(aaddr));
                   1418: }
                   1419: 
                   1420: 
                   1421: /*
                   1422:  *  c@          ( addr -- byte )
                   1423:  */
                   1424: 
                   1425: static void cfetch(void)
                   1426: {
                   1427:        const u8 *aaddr = (u8 *)cell2pointer(POP());
                   1428:        PUSH(read_byte(aaddr));
                   1429: }
                   1430: 
                   1431: 
                   1432: /*
                   1433:  *  w@          ( waddr -- w )
                   1434:  */
                   1435: 
                   1436: static void wfetch(void)
                   1437: {
                   1438:        const u16 *aaddr = (u16 *)cell2pointer(POP());
                   1439:        PUSH(read_word(aaddr));
                   1440: }
                   1441: 
                   1442: 
                   1443: /*
                   1444:  *  l@          ( qaddr -- quad )
                   1445:  */
                   1446: 
                   1447: static void lfetch(void)
                   1448: {
                   1449:        const u32 *aaddr = (u32 *)cell2pointer(POP());
                   1450:        PUSH(read_long(aaddr));
                   1451: }
                   1452: 
                   1453: 
                   1454: /*
                   1455:  *  !           ( x a-addr -- )
                   1456:  */
                   1457: 
                   1458: static void store(void)
                   1459: {
                   1460:        const ucell *aaddr = (ucell *)cell2pointer(POP());
                   1461:        const ucell x = POP();
                   1462: #ifdef CONFIG_DEBUG_INTERNAL
                   1463:        printk("!: %lx : %lx -> %lx\n", aaddr, read_ucell(aaddr), x);
                   1464: #endif
                   1465:        write_ucell(aaddr,x);
                   1466: }
                   1467: 
                   1468: 
                   1469: /*
                   1470:  *  +!          ( nu a-addr -- )
                   1471:  */
                   1472: 
                   1473: static void plusstore(void)
                   1474: {
                   1475:        const ucell *aaddr = (ucell *)cell2pointer(POP());
                   1476:        const cell nu = POP();
                   1477:        write_cell(aaddr,read_cell(aaddr)+nu);
                   1478: }
                   1479: 
                   1480: 
                   1481: /*
                   1482:  *  c!          ( byte addr -- )
                   1483:  */
                   1484: 
                   1485: static void cstore(void)
                   1486: {
                   1487:        const u8 *aaddr = (u8 *)cell2pointer(POP());
                   1488:        const ucell byte = POP();
                   1489: #ifdef CONFIG_DEBUG_INTERNAL
                   1490:        printk("c!: %x = %x\n", aaddr, byte);
                   1491: #endif
                   1492:        write_byte(aaddr, byte);
                   1493: }
                   1494: 
                   1495: 
                   1496: /*
                   1497:  *  w!          ( w waddr -- )
                   1498:  */
                   1499: 
                   1500: static void wstore(void)
                   1501: {
                   1502:        const u16 *aaddr = (u16 *)cell2pointer(POP());
                   1503:        const u16 word = POP();
                   1504:        write_word(aaddr, word);
                   1505: }
                   1506: 
                   1507: 
                   1508: /*
                   1509:  *  l!          ( quad qaddr -- )
                   1510:  */
                   1511: 
                   1512: static void lstore(void)
                   1513: {
                   1514:        const u32 *aaddr = (u32 *)cell2pointer(POP());
                   1515:        const u32 longval = POP();
                   1516:        write_long(aaddr, longval);
                   1517: }
                   1518: 
                   1519: 
                   1520: /*
                   1521:  *  =           ( x1 x2 -- equal? )
                   1522:  */
                   1523: 
                   1524: static void equals(void)
                   1525: {
                   1526:        cell tmp = (POP() == POP());
                   1527:        PUSH(-tmp);
                   1528: }
                   1529: 
                   1530: 
                   1531: /*
                   1532:  *  >           ( n1 n2 -- greater? )
                   1533:  */
                   1534: 
                   1535: static void greater(void)
                   1536: {
                   1537:        cell tmp = ((cell) POP() < (cell) POP());
                   1538:        PUSH(-tmp);
                   1539: }
                   1540: 
                   1541: 
                   1542: /*
                   1543:  *  <           ( n1 n2 -- less? )
                   1544:  */
                   1545: 
                   1546: static void less(void)
                   1547: {
                   1548:        cell tmp = ((cell) POP() > (cell) POP());
                   1549:        PUSH(-tmp);
                   1550: }
                   1551: 
                   1552: 
                   1553: /*
                   1554:  *  u>          ( u1 u2 -- unsigned-greater? )
                   1555:  */
                   1556: 
                   1557: static void ugreater(void)
                   1558: {
                   1559:        cell tmp = ((ucell) POP() < (ucell) POP());
                   1560:        PUSH(-tmp);
                   1561: }
                   1562: 
                   1563: 
                   1564: /*
                   1565:  *  u<          ( u1 u2 -- unsigned-less? )
                   1566:  */
                   1567: 
                   1568: static void uless(void)
                   1569: {
                   1570:        cell tmp = ((ucell) POP() > (ucell) POP());
                   1571:        PUSH(-tmp);
                   1572: }
                   1573: 
                   1574: 
                   1575: /*
                   1576:  *  sp@         (  -- stack-pointer )
                   1577:  */
                   1578: 
                   1579: static void spfetch(void)
                   1580: {
                   1581:        // FIXME this can only work if the stack pointer
                   1582:        // is within range.
                   1583:        ucell tmp = pointer2cell(&(dstack[dstackcnt]));
                   1584:        PUSH(tmp);
                   1585: }
                   1586: 
                   1587: 
                   1588: /*
                   1589:  *  move        ( src-addr dest-addr len -- )
                   1590:  */
                   1591: 
                   1592: static void fmove(void)
                   1593: {
                   1594:        ucell count = POP();
                   1595:        void *dest = (void *)cell2pointer(POP());
                   1596:        const void *src = (const void *)cell2pointer(POP());
                   1597:        memmove(dest, src, count);
                   1598: }
                   1599: 
                   1600: 
                   1601: /*
                   1602:  *  fill        ( addr len byte -- )
                   1603:  */
                   1604: 
                   1605: static void ffill(void)
                   1606: {
                   1607:        ucell value = POP();
                   1608:        ucell count = POP();
                   1609:        void *src = (void *)cell2pointer(POP());
                   1610:        memset(src, value, count);
                   1611: }
                   1612: 
                   1613: 
                   1614: /*
                   1615:  *  unaligned-w@  ( addr -- w )
                   1616:  */
                   1617: 
                   1618: static void unalignedwordread(void)
                   1619: {
                   1620:        const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
                   1621:        PUSH(unaligned_read_word(addr));
                   1622: }
                   1623: 
                   1624: 
                   1625: /*
                   1626:  *  unaligned-w!  ( w addr -- )
                   1627:  */
                   1628: 
                   1629: static void unalignedwordwrite(void)
                   1630: {
                   1631:        const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
                   1632:        u16 w = POP();
                   1633:        unaligned_write_word(addr, w);
                   1634: }
                   1635: 
                   1636: 
                   1637: /*
                   1638:  *  unaligned-l@  ( addr -- quad )
                   1639:  */
                   1640: 
                   1641: static void unalignedlongread(void)
                   1642: {
                   1643:        const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
                   1644:        PUSH(unaligned_read_long(addr));
                   1645: }
                   1646: 
                   1647: 
                   1648: /*
                   1649:  *  unaligned-l!  ( quad addr -- )
                   1650:  */
                   1651: 
                   1652: static void unalignedlongwrite(void)
                   1653: {
                   1654:        unsigned char *addr = (unsigned char *) cell2pointer(POP());
                   1655:        u32 l = POP();
                   1656:        unaligned_write_long(addr, l);
                   1657: }
                   1658: 
                   1659: /*
                   1660:  *  here        (  -- dictionary-pointer )
                   1661:  */
                   1662: 
                   1663: static void here(void)
                   1664: {
                   1665:        PUSH(pointer2cell(dict) + dicthead);
                   1666: #ifdef CONFIG_DEBUG_INTERNAL
                   1667:        printk("here: %x\n", pointer2cell(dict) + dicthead);
                   1668: #endif
                   1669: }
                   1670: 
                   1671: /*
                   1672:  *  here!       ( new-dict-pointer -- )
                   1673:  */
                   1674: 
                   1675: static void herewrite(void)
                   1676: {
                   1677:        ucell tmp = POP(); /* converted pointer */
                   1678:        dicthead = tmp - pointer2cell(dict);
                   1679: #ifdef CONFIG_DEBUG_INTERNAL
                   1680:        printk("here!: new value: %x\n", tmp);
                   1681: #endif
                   1682: 
                   1683:        if (dictlimit && dicthead >= dictlimit) {
                   1684:            printk("Dictionary space overflow:"
                   1685:                    " dicthead=" FMT_ucellx
                   1686:                    " dictlimit=" FMT_ucellx
                   1687:                    "\n",
                   1688:                    dicthead, dictlimit);
                   1689:        }
                   1690: }
                   1691: 
                   1692: 
                   1693: /*
                   1694:  *   emit       ( char --  )
                   1695:  */
                   1696: 
                   1697: static void emit(void)
                   1698: {
                   1699:        cell tmp = POP();
                   1700: #ifndef FCOMPILER
                   1701:        putchar(tmp);
                   1702: #else
                   1703:                put_outputbyte(tmp);
                   1704: #endif
                   1705: }
                   1706: 
                   1707: 
                   1708: /*
                   1709:  *   key?       (  -- pressed? )
                   1710:  */
                   1711: 
                   1712: static void iskey(void)
                   1713: {
                   1714:        PUSH((cell) availchar());
                   1715: }
                   1716: 
                   1717: 
                   1718: /*
                   1719:  *   key        (  -- char )
                   1720:  */
                   1721: 
                   1722: static void key(void)
                   1723: {
                   1724:        while (!availchar());
                   1725: #ifdef FCOMPILER
                   1726:        PUSH(get_inputbyte());
                   1727: #else
                   1728:        PUSH(getchar());
                   1729: #endif
                   1730: }
                   1731: 
                   1732: 
                   1733: /*
                   1734:  *   ioc@       ( reg -- val )
                   1735:  */
                   1736: 
                   1737: static void iocfetch(void)
                   1738: {
                   1739: #ifndef FCOMPILER
                   1740:        cell reg = POP();
                   1741:        PUSH(inb(reg));
                   1742: #else
                   1743:         (void)POP();
                   1744:         PUSH(0);
                   1745: #endif
                   1746: }
                   1747: 
                   1748: 
                   1749: /*
                   1750:  *   iow@       ( reg -- val )
                   1751:  */
                   1752: 
                   1753: static void iowfetch(void)
                   1754: {
                   1755: #ifndef FCOMPILER
                   1756:        cell reg = POP();
                   1757:        PUSH(inw(reg));
                   1758: #else
                   1759:         (void)POP();
                   1760:         PUSH(0);
                   1761: #endif
                   1762: }
                   1763: 
                   1764: /*
                   1765:  *   iol@       ( reg -- val )
                   1766:  */
                   1767: 
                   1768: static void iolfetch(void)
                   1769: {
                   1770: #ifndef FCOMPILER
                   1771:        cell reg = POP();
                   1772:        PUSH(inl(reg));
                   1773: #else
                   1774:         (void)POP();
                   1775:         PUSH(0);
                   1776: #endif
                   1777: }
                   1778: 
                   1779: 
                   1780: /*
                   1781:  *   ioc!       ( val reg --  )
                   1782:  */
                   1783: 
                   1784: static void iocstore(void)
                   1785: {
                   1786: #ifndef FCOMPILER
                   1787:        cell reg = POP();
                   1788:        cell val = POP();
                   1789: 
                   1790:        outb(reg, val);
                   1791: #else
                   1792:         (void)POP();
                   1793:         (void)POP();
                   1794: #endif
                   1795: }
                   1796: 
                   1797: 
                   1798: /*
                   1799:  *   iow!       ( val reg --  )
                   1800:  */
                   1801: 
                   1802: static void iowstore(void)
                   1803: {
                   1804: #ifndef FCOMPILER
                   1805:        cell reg = POP();
                   1806:        cell val = POP();
                   1807: 
                   1808:        outw(reg, val);
                   1809: #else
                   1810:         (void)POP();
                   1811:         (void)POP();
                   1812: #endif
                   1813: }
                   1814: 
                   1815: 
                   1816: /*
                   1817:  *   iol!       ( val reg --  )
                   1818:  */
                   1819: 
                   1820: static void iolstore(void)
                   1821: {
                   1822: #ifndef FCOMPILER
                   1823:        ucell reg = POP();
                   1824:        ucell val = POP();
                   1825: 
                   1826:        outl(reg, val);
                   1827: #else
                   1828:         (void)POP();
                   1829:         (void)POP();
                   1830: #endif
                   1831: }
                   1832: 
                   1833: /*
                   1834:  *   i         ( -- i )
                   1835:  */
                   1836: 
                   1837: static void loop_i(void)
                   1838: {
                   1839:        PUSH(rstack[rstackcnt]);
                   1840: }
                   1841: 
                   1842: /*
                   1843:  *   j         ( -- i )
                   1844:  */
                   1845: 
                   1846: static void loop_j(void)
                   1847: {
                   1848:        PUSH(rstack[rstackcnt - 2]);
                   1849: }
                   1850: 
                   1851: /* words[] is a function array of all native code functions used by
                   1852:  * the dictionary, i.e. CFAs and primitives.
                   1853:  * Any change here needs a matching change in the primitive word's
                   1854:  * name list that is kept for bootstrapping in kernel/bootstrap.c
                   1855:  *
                   1856:  * NOTE: THIS LIST SHALL NOT CHANGE (EXCEPT MANDATORY ADDITIONS AT
                   1857:  * THE END). ANY OTHER CHANGE WILL BREAK COMPATIBILITY TO OLDER
                   1858:  * BINARY DICTIONARIES.
                   1859:  */
                   1860: static forth_word * const words[] = {
                   1861:     /*
                   1862:      * CFAs and special words
                   1863:      */
                   1864:     semis,
                   1865:     docol,
                   1866:     lit,
                   1867:     docon,
                   1868:     dovar,
                   1869:     dodefer,
                   1870:     dodoes,
                   1871:     dodo,
                   1872:     doisdo,
                   1873:     doloop,
                   1874:     doplusloop,
                   1875:     doival,
                   1876:     doivar,
                   1877:     doidefer,
                   1878: 
                   1879:     /*
                   1880:      * primitives
                   1881:      */
                   1882:     fdup,                   /* dup     */
                   1883:     twodup,                 /* 2dup    */
                   1884:     isdup,                  /* ?dup    */
                   1885:     over,                   /* over    */
                   1886:     twoover,                /* 2over   */
                   1887:     pick,                   /* pick    */
                   1888:     drop,                   /* drop    */
                   1889:     twodrop,                /* 2drop   */
                   1890:     nip,                    /* nip     */
                   1891:     roll,                   /* roll    */
                   1892:     rot,                    /* rot     */
                   1893:     minusrot,               /* -rot    */
                   1894:     swap,                   /* swap    */
                   1895:     twoswap,                /* 2swap   */
                   1896:     tor,                    /* >r      */
                   1897:     rto,                    /* r>      */
                   1898:     rfetch,                 /* r@      */
                   1899:     depth,                  /* depth   */
                   1900:     depthwrite,             /* depth!  */
                   1901:     rdepth,                 /* rdepth  */
                   1902:     rdepthwrite,            /* rdepth! */
                   1903:     plus,                   /* +       */
                   1904:     minus,                  /* -       */
                   1905:     mult,                   /* *       */
                   1906:     umult,                  /* u*      */
                   1907:     mudivmod,               /* mu/mod  */
                   1908:     forthabs,               /* abs     */
                   1909:     negate,                 /* negate  */
                   1910:     max,                    /* max     */
                   1911:     min,                    /* min     */
                   1912:     lshift,                 /* lshift  */
                   1913:     rshift,                 /* rshift  */
                   1914:     rshifta,                /* >>a     */
                   1915:     and,                    /* and     */
                   1916:     or,                     /* or      */
                   1917:     xor,                    /* xor     */
                   1918:     invert,                 /* invert  */
                   1919:     dplus,                  /* d+      */
                   1920:     dminus,                 /* d-      */
                   1921:     mmult,                  /* m*      */
                   1922:     ummult,                 /* um*     */
                   1923:     fetch,                  /* @       */
                   1924:     cfetch,                 /* c@      */
                   1925:     wfetch,                 /* w@      */
                   1926:     lfetch,                 /* l@      */
                   1927:     store,                  /* !       */
                   1928:     plusstore,              /* +!      */
                   1929:     cstore,                 /* c!      */
                   1930:     wstore,                 /* w!      */
                   1931:     lstore,                 /* l!      */
                   1932:     equals,                 /* =       */
                   1933:     greater,                /* >       */
                   1934:     less,                   /* <       */
                   1935:     ugreater,               /* u>      */
                   1936:     uless,                  /* u<      */
                   1937:     spfetch,                /* sp@     */
                   1938:     fmove,                  /* move    */
                   1939:     ffill,                  /* fill    */
                   1940:     emit,                   /* emit    */
                   1941:     iskey,                  /* key?    */
                   1942:     key,                    /* key     */
                   1943:     execute,                /* execute */
                   1944:     here,                   /* here    */
                   1945:     herewrite,              /* here!   */
                   1946:     dobranch,               /* dobranch     */
                   1947:     docbranch,              /* do?branch    */
                   1948:     unalignedwordread,      /* unaligned-w@ */
                   1949:     unalignedwordwrite,     /* unaligned-w! */
                   1950:     unalignedlongread,      /* unaligned-l@ */
                   1951:     unalignedlongwrite,     /* unaligned-l! */
                   1952:     iocfetch,               /* ioc@    */
                   1953:     iowfetch,               /* iow@    */
                   1954:     iolfetch,               /* iol@    */
                   1955:     iocstore,               /* ioc!    */
                   1956:     iowstore,               /* iow!    */
                   1957:     iolstore,               /* iol!    */
                   1958:     loop_i,                 /* i       */
                   1959:     loop_j,                 /* j       */
                   1960:     call,                   /* call    */
                   1961:     sysdebug,               /* sys-debug */
                   1962:     do_include,             /* $include */
                   1963:     do_encode_file,         /* $encode-file */
                   1964:     do_debug_xt,            /* (debug  */
                   1965:     do_debug_off,           /* (debug-off) */
                   1966: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.