Annotation of qemu/roms/openbios/kernel/forth.c, revision 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.