1 /* tag: C implementation of all forth primitives,
2 * internal words, inner interpreter and such
4 * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
11 #include "sysinclude.h"
12 #include "kernel/stack.h"
13 #include "kernel/kernel.h"
17 * cross platform abstraction
23 #include "libc/vsprintf.h"
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
35 typedef void forth_word(void);
37 static forth_word
* const words
[];
39 volatile int interruptforth
= 0;
41 #define DEBUG_MODE_NONE 0
42 #define DEBUG_MODE_STEP 1
43 #define DEBUG_MODE_TRACE 2
44 #define DEBUG_MODE_STEPUP 3
46 #define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n"
48 /* Empty linked list of debug xts */
53 struct debug_xt
*next
;
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
;
59 /* Static buffer for xt name */
60 char xtname
[MAXNFALEN
];
63 /* instead of pointing to an explicit 0 variable we
64 * point behind the pointer.
66 static ucell t
[] = { 0, 0, 0, 0 };
67 static ucell
*trampoline
= t
;
70 * Code Field Address (CFA) definitions (DOCOL and the like)
75 init_trampoline(trampoline
);
79 #ifndef CONFIG_DEBUG_INTERPRETER
80 #define dbg_interp_printk( a... ) do { } while(0)
82 #define dbg_interp_printk( a... ) printk( a )
85 #ifndef CONFIG_DEBUG_INTERNAL
86 #define dbg_internal_printk( a... ) do { } while(0)
88 #define dbg_internal_printk( a... ) printk( a )
92 void init_trampoline(ucell
*tramp
)
96 tramp
[2] = target_ucell(pointer2cell(tramp
) + 3 * sizeof(ucell
));
100 static inline void processxt(ucell xt
)
102 void (*tokenp
) (void);
104 dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC
, xt
);
109 static void docol(void)
112 PC
= read_ucell(cell2pointer(PC
));
114 dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC
- sizeof(cell
)) ));
117 static void semis(void)
122 static inline void next(void)
126 dbg_interp_printk("next: PC is now %x\n", PC
);
127 processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)))));
130 static inline void next_dbg(void);
132 int enterforth(xt_t xt
)
134 ucell
*_cfa
= (ucell
*)cell2pointer(xt
);
137 if (read_ucell(_cfa
) != DOCOL
) {
138 trampoline
[1] = target_ucell(xt
);
147 interruptforth
= FORTH_INTSTAT_CLR
;
150 PC
= pointer2cell(_cfa
);
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");
159 while (rstackcnt
> tmp
&& !interruptforth
) {
160 dbg_interp_printk("enterforth: NEXT_DBG\n");
165 /* Always clear the debug mode change flag */
166 interruptforth
= interruptforth
& (~FORTH_INTSTAT_DBG
);
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.
175 if (rstackcnt
!= tmp
) {
176 printk("EXCEPTION DETECTED!\n");
179 return rstackcnt
!= tmp
;
182 /* called inline thus a slightly different behaviour */
183 static void lit(void)
186 PUSH(read_ucell(cell2pointer(PC
)));
187 dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC
)));
190 static void docon(void)
192 ucell tmp
= read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)) + sizeof(ucell
)));
194 dbg_interp_printk("docon: PC=%x, value=%x\n", PC
, tmp
);
197 static void dovar(void)
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
);
204 static void dobranch(void)
205 { /* unconditional branch */
207 PC
+= read_cell(cell2pointer(PC
));
210 static void docbranch(void)
211 { /* conditional branch */
214 dbg_internal_printk(" ?branch: end loop\n");
216 dbg_internal_printk(" ?branch: follow branch\n");
217 PC
+= read_cell(cell2pointer(PC
));
222 static void execute(void)
224 ucell address
= POP();
225 dbg_interp_printk("execute: %x\n", address
);
228 trampoline
[1] = target_ucell(address
);
229 PC
= pointer2cell(trampoline
);
233 * call ( ... function-ptr -- ??? )
235 static void call(void)
238 printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n");
241 void (*funcptr
) (void);
242 funcptr
=(void *)cell2pointer(POP());
243 dbg_interp_printk("call: %x", funcptr
);
249 * sys-debug ( errno -- )
252 static void sysdebug(void)
262 static void dodoes(void)
264 ucell data
= read_ucell(cell2pointer(PC
)) + (2 * sizeof(ucell
));
265 ucell word
= read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)) + sizeof(ucell
)));
267 dbg_interp_printk("DODOES data=%x word=%x\n", data
, word
);
275 static void dodefer(void)
280 static void dodo(void)
282 cell startval
, endval
;
290 static void doisdo(void)
292 cell startval
, endval
, offset
;
299 if (startval
== endval
) {
300 offset
= read_cell(cell2pointer(PC
));
308 static void doloop(void)
310 cell offset
, startval
, endval
;
312 startval
= POPR() + 1;
317 if (startval
< endval
) {
318 offset
= read_cell(cell2pointer(PC
));
326 static void doplusloop(void)
329 cell increment
, startval
, endval
, offset
;
336 low
= (ucell
) startval
;
337 startval
+= increment
;
341 if (increment
>= 0) {
342 high
= (ucell
) startval
;
345 low
= (ucell
) startval
;
348 if (endval
- (low
+ 1) >= high
- low
) {
349 offset
= read_cell(cell2pointer(PC
));
358 * instance handling CFAs
361 static ucell
get_myself(void)
363 static ucell
*myselfptr
= NULL
;
364 if (myselfptr
== NULL
) {
365 myselfptr
= (ucell
*)cell2pointer(findword("my-self")) + 1;
367 ucell
*myself
= (ucell
*)cell2pointer(*myselfptr
);
368 return (myself
!= NULL
) ? *myself
: 0;
371 static void doivar(void)
373 ucell r
, *p
= (ucell
*)(*(ucell
*) cell2pointer(PC
) + sizeof(ucell
));
374 ucell ibase
= get_myself();
376 dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p
[0], p
[1], ibase
);
378 r
= ibase
? ibase
+ p
[0] : pointer2cell(&p
[2]);
382 static void doival(void)
384 ucell r
, *p
= (ucell
*)(*(ucell
*) cell2pointer(PC
) + sizeof(ucell
));
385 ucell ibase
= get_myself();
387 dbg_interp_printk("ivar, offset: %d size: %d\n", p
[0], p
[1] );
389 r
= ibase
? ibase
+ p
[0] : pointer2cell(&p
[2]);
390 PUSH( *(ucell
*)cell2pointer(r
) );
393 static void doidefer(void)
395 ucell
*p
= (ucell
*)(*(ucell
*) cell2pointer(PC
) + sizeof(ucell
));
396 ucell ibase
= get_myself();
398 dbg_interp_printk("doidefer, offset: %d size: %d\n", p
[0], p
[1] );
401 PC
= ibase
? ibase
+ p
[0] : pointer2cell(&p
[2]);
405 static void noinstances(void)
407 printk("Opening devices is not supported during bootstrap. Sorry.\n");
410 #define doivar noinstances
411 #define doival noinstances
412 #define doidefer noinstances
416 * $include / $encode-file
420 string_relay(void (*func
)(const char *))
423 char *name
, *p
= (char*)cell2pointer(POP());
424 name
= malloc(len
+ 1);
425 memcpy(name
, p
, len
);
431 #define string_relay(dummy) do { DROP(); DROP(); } while(0)
437 string_relay(&include_file
);
441 do_encode_file( void )
443 string_relay(&encode_file
);
447 * Debug support functions
451 int printf_console(const char *fmt
, ...)
460 i
= vsnprintf(buf
, sizeof(buf
), fmt
, args
);
463 /* Push to the Forth interpreter for console output */
466 PUSH(pointer2cell(buf
));
467 PUSH((int)strlen(buf
));
468 trampoline
[1] = findword("type");
471 PC
= pointer2cell(trampoline
);
473 while (rstackcnt
> tmp
) {
474 dbg_interp_printk("printf_console: NEXT\n");
482 int getchar_console(void)
486 /* Push to the Forth interpreter for console output */
489 trampoline
[1] = findword("key");
492 PC
= pointer2cell(trampoline
);
494 while (rstackcnt
> tmp
) {
495 dbg_interp_printk("getchar_console: NEXT\n");
503 display_dbg_dstack(void)
505 /* Display dstack contents between parentheses */
508 if (dstackcnt
== 0) {
509 printf_console(" ( Empty ) ");
512 printf_console(" ( ");
513 for (i
= 1; i
<= dstackcnt
; i
++) {
517 printf_console("%" FMT_CELL_x
, dstack
[i
]);
519 printf_console(" ) ");
524 display_dbg_rstack(void)
526 /* Display rstack contents between parentheses */
529 if (rstackcnt
== 0) {
530 printf_console(" ( Empty ) ");
533 printf_console("\nR: ( ");
534 for (i
= 1; i
<= rstackcnt
; i
++) {
538 printf_console("%" FMT_CELL_x
, rstack
[i
]);
540 printf_console(" ) \n");
545 add_debug_xt(ucell xt
)
547 struct debug_xt
*debug_xt_item
;
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");
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
) {
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() */
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
;
575 /* Indicate debug mode change */
576 interruptforth
|= FORTH_INTSTAT_DBG
;
583 del_debug_xt(ucell xt
)
585 struct debug_xt
*debug_xt_item
, *tmp_xt_item
;
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
;
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
;
606 /* If the list is now empty, indicate debug mode change */
607 if (debug_xt_list
->next
== NULL
) {
608 interruptforth
|= FORTH_INTSTAT_DBG
;
613 do_source_dbg(struct debug_xt
*debug_xt_item
)
615 /* Forth source debugger implementation */
618 /* Display current dstack */
619 display_dbg_dstack();
620 printf_console("\n");
622 fstrncpy(xtname
, lfa2nfa(read_ucell(cell2pointer(PC
)) - sizeof(cell
)), MAXNFALEN
);
623 printf_console("%p: %s ", cell2pointer(PC
), xtname
);
625 /* If in trace mode, we just carry on */
626 if (debug_xt_item
->mode
== DEBUG_MODE_TRACE
) {
630 /* Otherwise in step mode, prompt for a keypress */
631 k
= getchar_console();
633 /* Only proceed if done is true */
639 /* Perform a single step */
645 /* Up - unmark current word for debug, mark its caller for
646 * debugging and finish executing current word */
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
;
660 /* Down - mark current word for debug and step into it */
661 done
= add_debug_xt(read_ucell(cell2pointer(PC
)));
663 k
= getchar_console();
670 debug_xt_item
->mode
= DEBUG_MODE_TRACE
;
677 display_dbg_rstack();
679 k
= getchar_console();
684 /* Start subordinate Forth interpreter */
685 PUSHR(PC
- sizeof(cell
));
686 PC
= findword("outer-interpreter") + sizeof(ucell
);
688 /* Save rstack position for when we return */
689 dbgrstackcnt
= rstackcnt
;
694 /* Display debug banner */
695 printf_console(DEBUG_BANNER
);
696 k
= getchar_console();
701 static void docol_dbg(void)
703 struct debug_xt
*debug_xt_item
;
706 PC
= read_ucell(cell2pointer(PC
));
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
);
715 /* Step mode is the default */
716 debug_xt_item
->mode
= DEBUG_MODE_STEP
;
719 debug_xt_item
= debug_xt_item
->next
;
722 dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC
- sizeof(cell
))));
725 static void semis_dbg(void)
727 struct debug_xt
*debug_xt_item
, *debug_xt_up
= NULL
;
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
);
738 /* Reset to step mode in case we were in trace mode */
739 debug_xt_item
->mode
= DEBUG_MODE_STEP
;
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.
746 debug_xt_up
= debug_xt_item
;
750 debug_xt_item
= debug_xt_item
->next
;
753 /* Execute debugger "Up" semantics if required */
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
]));
760 fstrncpy(xtname
, lfa2nfa(findxtfromcell(rstack
[rstackcnt
]) - sizeof(cell
)), MAXNFALEN
);
761 printf_console("\n[ Up to %s ] ", xtname
);
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
);
766 del_debug_xt(debug_xt_up
->xt_docol
);
775 static inline void next_dbg(void)
777 struct debug_xt
*debug_xt_item
;
778 void (*tokenp
) (void);
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
);
790 debug_xt_item
= debug_xt_item
->next
;
793 dbg_interp_printk("next_dbg: PC is now %x\n", PC
);
795 /* Intercept DOCOL and SEMIS and redirect to debug versions */
796 if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)))) == DOCOL
) {
799 } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)))) == DOSEMIS
) {
803 /* Otherwise process as normal */
804 processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC
)))));
813 /* Add to the debug list */
814 if (add_debug_xt(xt
)) {
815 /* Display debug banner */
816 printf_console(DEBUG_BANNER
);
818 /* Indicate change to debug mode */
819 interruptforth
|= FORTH_INTSTAT_DBG
;
826 /* Empty the debug xt linked list */
827 while (debug_xt_list
->next
!= NULL
) {
828 del_debug_xt(debug_xt_list
->xt_docol
);
833 * Forth primitives needed to set up
834 * all the words described in IEEE1275-1994.
841 static void fdup(void)
843 const cell tmp
= GETTOS();
849 * 2dup ( x1 x2 -- x1 x2 x1 x2 )
852 static void twodup(void)
854 cell tmp
= GETITEM(1);
862 * ?dup ( x -- 0 | x x )
865 static void isdup(void)
867 const cell tmp
= GETTOS();
874 * over ( x y -- x y x )
877 static void over(void)
879 const cell tmp
= GETITEM(1);
885 * 2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
888 static void twoover(void)
890 const cell tmp
= GETITEM(3);
891 const cell tmp2
= GETITEM(2);
897 * pick ( xu ... x1 x0 u -- xu ... x1 x0 xu )
900 static void pick(void)
902 const cell u
= POP();
903 if (dstackcnt
>= u
) {
904 ucell tmp
= dstack
[dstackcnt
- u
];
916 static void drop(void)
925 static void twodrop(void)
933 * nip ( x1 x2 -- x2 )
936 static void nip(void)
938 const cell tmp
= POP();
945 * roll ( xu ... x1 x0 u -- xu-1... x1 x0 xu )
948 static void roll(void)
950 const cell u
= POP();
951 if (dstackcnt
>= u
) {
953 const cell xu
= dstack
[dstackcnt
- u
];
954 for (i
= dstackcnt
- u
; i
< dstackcnt
; i
++) {
955 dstack
[i
] = dstack
[i
+ 1];
957 dstack
[dstackcnt
] = xu
;
965 * rot ( x1 x2 x3 -- x2 x3 x1 )
968 static void rot(void)
970 const cell tmp
= POP();
971 const cell tmp2
= POP();
972 const cell tmp3
= POP();
980 * -rot ( x1 x2 x3 -- x3 x1 x2 )
983 static void minusrot(void)
985 const cell tmp
= POP();
986 const cell tmp2
= POP();
987 const cell tmp3
= POP();
995 * swap ( x1 x2 -- x2 x1 )
998 static void swap(void)
1000 const cell tmp
= POP();
1001 const cell tmp2
= POP();
1008 * 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
1011 static void twoswap(void)
1013 const cell tmp
= POP();
1014 const cell tmp2
= POP();
1015 const cell tmp3
= POP();
1016 const cell tmp4
= POP();
1025 * >r ( x -- ) (R: -- x )
1028 static void tor(void)
1031 #ifdef CONFIG_DEBUG_RSTACK
1032 printk(" >R: %x\n", tmp
);
1039 * r> ( -- x ) (R: x -- )
1042 static void rto(void)
1045 #ifdef CONFIG_DEBUG_RSTACK
1046 printk(" R>: %x\n", tmp
);
1053 * r@ ( -- x ) (R: x -- x )
1056 static void rfetch(void)
1066 static void depth(void)
1068 const cell tmp
= dstackcnt
;
1074 * depth! ( ... u -- x1 x2 .. xu )
1077 static void depthwrite(void)
1088 static void rdepth(void)
1090 const cell tmp
= rstackcnt
;
1096 * rdepth! ( u -- ) ( R: ... -- x1 x2 .. xu )
1099 static void rdepthwrite(void)
1107 * + ( nu1 nu2 -- sum )
1110 static void plus(void)
1112 cell tmp
= POP() + POP();
1118 * - ( nu1 nu2 -- diff )
1121 static void minus(void)
1123 const cell nu2
= POP();
1124 const cell nu1
= POP();
1130 * * ( nu1 nu2 -- prod )
1133 static void mult(void)
1135 const cell nu2
= POP();
1136 const cell nu1
= POP();
1142 * u* ( u1 u2 -- prod )
1145 static void umult(void)
1147 const ucell tmp
= (ucell
) POP() * (ucell
) POP();
1153 * mu/mod ( n1 n2 -- rem quot.l quot.h )
1156 static void mudivmod(void)
1158 const ucell b
= POP();
1159 const ducell a
= DPOP();
1160 #ifdef NEED_FAKE_INT128_T
1162 fprintf(stderr
, "mudivmod called (0x%016llx %016llx / 0x%016llx)\n",
1184 static void forthabs(void)
1186 const cell tmp
= GETTOS();
1195 * negate ( n1 -- n2 )
1198 static void negate(void)
1200 const cell tmp
= POP();
1206 * max ( n1 n2 -- n1|n2 )
1209 static void max(void)
1211 const cell tmp
= POP();
1212 const cell tmp2
= POP();
1213 PUSH((tmp
> tmp2
) ? tmp
: tmp2
);
1218 * min ( n1 n2 -- n1|n2 )
1221 static void min(void)
1223 const cell tmp
= POP();
1224 const cell tmp2
= POP();
1225 PUSH((tmp
< tmp2
) ? tmp
: tmp2
);
1230 * lshift ( x1 u -- x2 )
1233 static void lshift(void)
1235 const ucell u
= POP();
1236 const ucell x1
= POP();
1242 * rshift ( x1 u -- x2 )
1245 static void rshift(void)
1247 const ucell u
= POP();
1248 const ucell x1
= POP();
1254 * >>a ( x1 u -- x2 ) ??
1257 static void rshifta(void)
1259 const cell u
= POP();
1260 const cell x1
= POP();
1266 * and ( x1 x2 -- x3 )
1269 static void and(void)
1271 const cell x1
= POP();
1272 const cell x2
= POP();
1278 * or ( x1 x2 -- x3 )
1281 static void or(void)
1283 const cell x1
= POP();
1284 const cell x2
= POP();
1290 * xor ( x1 x2 -- x3 )
1293 static void xor(void)
1295 const cell x1
= POP();
1296 const cell x2
= POP();
1302 * invert ( x1 -- x2 )
1305 static void invert(void)
1307 const cell x1
= POP();
1313 * d+ ( d1 d2 -- d.sum )
1316 static void dplus(void)
1318 const dcell d2
= DPOP();
1319 const dcell d1
= DPOP();
1320 #ifdef NEED_FAKE_INT128_T
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
);
1329 c
.lo
= d1
.lo
+ d2
.lo
;
1338 * d- ( d1 d2 -- d.diff )
1341 static void dminus(void)
1343 const dcell d2
= DPOP();
1344 const dcell d1
= DPOP();
1345 #ifdef NEED_FAKE_INT128_T
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
);
1354 c
.lo
= d1
.lo
- d2
.lo
;
1366 static void mmult(void)
1368 const cell u2
= POP();
1369 const cell u1
= POP();
1370 #ifdef NEED_FAKE_INT128_T
1373 if (0) { // XXX How to detect overflow?
1374 fprintf(stderr
, "mmult called (%016llx * 0x%016llx)\n", u1
, u2
);
1381 DPUSH((dcell
) u1
* u2
);
1387 * um* ( u1 u2 -- d.prod )
1390 static void ummult(void)
1392 const ucell u2
= POP();
1393 const ucell u1
= POP();
1394 #ifdef NEED_FAKE_INT128_T
1397 if (0) { // XXX How to detect overflow?
1398 fprintf(stderr
, "ummult called (%016llx * 0x%016llx)\n", u1
, u2
);
1405 DPUSH((ducell
) u1
* u2
);
1414 static void fetch(void)
1416 const ucell
*aaddr
= (ucell
*)cell2pointer(POP());
1417 PUSH(read_ucell(aaddr
));
1422 * c@ ( addr -- byte )
1425 static void cfetch(void)
1427 const u8
*aaddr
= (u8
*)cell2pointer(POP());
1428 PUSH(read_byte(aaddr
));
1436 static void wfetch(void)
1438 const u16
*aaddr
= (u16
*)cell2pointer(POP());
1439 PUSH(read_word(aaddr
));
1444 * l@ ( qaddr -- quad )
1447 static void lfetch(void)
1449 const u32
*aaddr
= (u32
*)cell2pointer(POP());
1450 PUSH(read_long(aaddr
));
1458 static void store(void)
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
);
1465 write_ucell(aaddr
,x
);
1470 * +! ( nu a-addr -- )
1473 static void plusstore(void)
1475 const ucell
*aaddr
= (ucell
*)cell2pointer(POP());
1476 const cell nu
= POP();
1477 write_cell(aaddr
,read_cell(aaddr
)+nu
);
1482 * c! ( byte addr -- )
1485 static void cstore(void)
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
);
1492 write_byte(aaddr
, byte
);
1500 static void wstore(void)
1502 const u16
*aaddr
= (u16
*)cell2pointer(POP());
1503 const u16 word
= POP();
1504 write_word(aaddr
, word
);
1509 * l! ( quad qaddr -- )
1512 static void lstore(void)
1514 const u32
*aaddr
= (u32
*)cell2pointer(POP());
1515 const u32 longval
= POP();
1516 write_long(aaddr
, longval
);
1521 * = ( x1 x2 -- equal? )
1524 static void equals(void)
1526 cell tmp
= (POP() == POP());
1532 * > ( n1 n2 -- greater? )
1535 static void greater(void)
1537 cell tmp
= ((cell
) POP() < (cell
) POP());
1543 * < ( n1 n2 -- less? )
1546 static void less(void)
1548 cell tmp
= ((cell
) POP() > (cell
) POP());
1554 * u> ( u1 u2 -- unsigned-greater? )
1557 static void ugreater(void)
1559 cell tmp
= ((ucell
) POP() < (ucell
) POP());
1565 * u< ( u1 u2 -- unsigned-less? )
1568 static void uless(void)
1570 cell tmp
= ((ucell
) POP() > (ucell
) POP());
1576 * sp@ ( -- stack-pointer )
1579 static void spfetch(void)
1581 // FIXME this can only work if the stack pointer
1583 ucell tmp
= pointer2cell(&(dstack
[dstackcnt
]));
1589 * move ( src-addr dest-addr len -- )
1592 static void fmove(void)
1594 ucell count
= POP();
1595 void *dest
= (void *)cell2pointer(POP());
1596 const void *src
= (const void *)cell2pointer(POP());
1597 memmove(dest
, src
, count
);
1602 * fill ( addr len byte -- )
1605 static void ffill(void)
1607 ucell value
= POP();
1608 ucell count
= POP();
1609 void *src
= (void *)cell2pointer(POP());
1610 memset(src
, value
, count
);
1615 * unaligned-w@ ( addr -- w )
1618 static void unalignedwordread(void)
1620 const unsigned char *addr
= (const unsigned char *) cell2pointer(POP());
1621 PUSH(unaligned_read_word(addr
));
1626 * unaligned-w! ( w addr -- )
1629 static void unalignedwordwrite(void)
1631 const unsigned char *addr
= (const unsigned char *) cell2pointer(POP());
1633 unaligned_write_word(addr
, w
);
1638 * unaligned-l@ ( addr -- quad )
1641 static void unalignedlongread(void)
1643 const unsigned char *addr
= (const unsigned char *) cell2pointer(POP());
1644 PUSH(unaligned_read_long(addr
));
1649 * unaligned-l! ( quad addr -- )
1652 static void unalignedlongwrite(void)
1654 unsigned char *addr
= (unsigned char *) cell2pointer(POP());
1656 unaligned_write_long(addr
, l
);
1660 * here ( -- dictionary-pointer )
1663 static void here(void)
1665 PUSH(pointer2cell(dict
) + dicthead
);
1666 #ifdef CONFIG_DEBUG_INTERNAL
1667 printk("here: %x\n", pointer2cell(dict
) + dicthead
);
1672 * here! ( new-dict-pointer -- )
1675 static void herewrite(void)
1677 ucell tmp
= POP(); /* converted pointer */
1678 dicthead
= tmp
- pointer2cell(dict
);
1679 #ifdef CONFIG_DEBUG_INTERNAL
1680 printk("here!: new value: %x\n", tmp
);
1683 if (dictlimit
&& dicthead
>= dictlimit
) {
1684 printk("Dictionary space overflow:"
1685 " dicthead=" FMT_ucellx
1686 " dictlimit=" FMT_ucellx
1688 dicthead
, dictlimit
);
1697 static void emit(void)
1703 put_outputbyte(tmp
);
1709 * key? ( -- pressed? )
1712 static void iskey(void)
1714 PUSH((cell
) availchar());
1722 static void key(void)
1724 while (!availchar());
1726 PUSH(get_inputbyte());
1734 * ioc@ ( reg -- val )
1737 static void iocfetch(void)
1750 * iow@ ( reg -- val )
1753 static void iowfetch(void)
1765 * iol@ ( reg -- val )
1768 static void iolfetch(void)
1781 * ioc! ( val reg -- )
1784 static void iocstore(void)
1799 * iow! ( val reg -- )
1802 static void iowstore(void)
1817 * iol! ( val reg -- )
1820 static void iolstore(void)
1837 static void loop_i(void)
1839 PUSH(rstack
[rstackcnt
]);
1846 static void loop_j(void)
1848 PUSH(rstack
[rstackcnt
- 2]);
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
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.
1860 static forth_word
* const words
[] = {
1862 * CFAs and special words
1886 twoover
, /* 2over */
1889 twodrop
, /* 2drop */
1893 minusrot
, /* -rot */
1895 twoswap
, /* 2swap */
1900 depthwrite
, /* depth! */
1901 rdepth
, /* rdepth */
1902 rdepthwrite
, /* rdepth! */
1907 mudivmod
, /* mu/mod */
1909 negate
, /* negate */
1912 lshift
, /* lshift */
1913 rshift
, /* rshift */
1918 invert
, /* invert */
1943 execute
, /* execute */
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! */
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) */