|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.