Add patch from Aleksej for 64 bit cells on 32 bit system.
[debian/pforth] / csrc / pf_inner.c
1 /* @(#) pf_inner.c 98/03/16 1.7 */\r
2 /***************************************************************\r
3 ** Inner Interpreter for Forth based on 'C'\r
4 **\r
5 ** Author: Phil Burk\r
6 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom\r
7 **\r
8 ** The pForth software code is dedicated to the public domain,\r
9 ** and any third party may reproduce, distribute and modify\r
10 ** the pForth software code or any derivative works thereof\r
11 ** without any compensation or license.  The pForth software\r
12 ** code is provided on an "as is" basis without any warranty\r
13 ** of any kind, including, without limitation, the implied\r
14 ** warranties of merchantability and fitness for a particular\r
15 ** purpose and their equivalents under the laws of any jurisdiction.\r
16 **\r
17 ****************************************************************\r
18 **\r
19 ** 940502 PLB Creation.\r
20 ** 940505 PLB More macros.\r
21 ** 940509 PLB Moved all stack stuff into pfCatch.\r
22 ** 941014 PLB Converted to flat secondary strusture.\r
23 ** 941027 rdg added casts to ID_SP_FETCH, ID_RP_FETCH, \r
24 **             and ID_HERE for armcc\r
25 ** 941130 PLB Made w@ unsigned\r
26 **\r
27 ***************************************************************/\r
28 \r
29 #include "pf_all.h"\r
30 \r
31 #ifdef WIN32\r
32 #include <crtdbg.h>\r
33 #endif\r
34 \r
35 #define SYSTEM_LOAD_FILE "system.fth"\r
36 \r
37 /***************************************************************\r
38 ** Macros for data stack access.\r
39 ** TOS is cached in a register in pfCatch.\r
40 ***************************************************************/\r
41 \r
42 #define STKPTR   (DataStackPtr)\r
43 #define M_POP    (*(STKPTR++))\r
44 #define M_PUSH(n) {*(--(STKPTR)) = (cell_t) (n);}\r
45 #define M_STACK(n) (STKPTR[n])\r
46 \r
47 #define TOS      (TopOfStack)\r
48 #define PUSH_TOS M_PUSH(TOS)\r
49 #define M_DUP    PUSH_TOS;\r
50 #define M_DROP   { TOS = M_POP; }\r
51 \r
52 \r
53 /***************************************************************\r
54 ** Macros for Floating Point stack access.\r
55 ***************************************************************/\r
56 #ifdef PF_SUPPORT_FP\r
57 #define FP_STKPTR   (FloatStackPtr)\r
58 #define M_FP_SPZERO (gCurrentTask->td_FloatStackBase)\r
59 #define M_FP_POP    (*(FP_STKPTR++))\r
60 #define M_FP_PUSH(n) {*(--(FP_STKPTR)) = (PF_FLOAT) (n);}\r
61 #define M_FP_STACK(n) (FP_STKPTR[n])\r
62 \r
63 #define FP_TOS      (fpTopOfStack)\r
64 #define PUSH_FP_TOS M_FP_PUSH(FP_TOS)\r
65 #define M_FP_DUP    PUSH_FP_TOS;\r
66 #define M_FP_DROP   { FP_TOS = M_FP_POP; }\r
67 #endif\r
68 \r
69 /***************************************************************\r
70 ** Macros for return stack access.\r
71 ***************************************************************/\r
72 \r
73 #define TORPTR (ReturnStackPtr)\r
74 #define M_R_DROP {TORPTR++;}\r
75 #define M_R_POP (*(TORPTR++))\r
76 #define M_R_PICK(n) (TORPTR[n])\r
77 #define M_R_PUSH(n) {*(--(TORPTR)) = (cell_t) (n);}\r
78 \r
79 /***************************************************************\r
80 ** Misc Forth macros\r
81 ***************************************************************/\r
82                         \r
83 #define M_BRANCH   { InsPtr = (cell_t *) (((uint8_t *) InsPtr) + READ_CELL_DIC(InsPtr)); }\r
84 \r
85 /* Cache top of data stack like in JForth. */\r
86 #ifdef PF_SUPPORT_FP\r
87 #define LOAD_REGISTERS \\r
88         { \\r
89                 STKPTR = gCurrentTask->td_StackPtr; \\r
90                 TOS = M_POP; \\r
91                 FP_STKPTR = gCurrentTask->td_FloatStackPtr; \\r
92                 FP_TOS = M_FP_POP; \\r
93                 TORPTR = gCurrentTask->td_ReturnPtr; \\r
94          }\r
95          \r
96 #define SAVE_REGISTERS \\r
97         { \\r
98                 gCurrentTask->td_ReturnPtr = TORPTR; \\r
99                 M_PUSH( TOS ); \\r
100                 gCurrentTask->td_StackPtr = STKPTR; \\r
101                 M_FP_PUSH( FP_TOS ); \\r
102                 gCurrentTask->td_FloatStackPtr = FP_STKPTR; \\r
103          }\r
104          \r
105 #else\r
106 /* Cache top of data stack like in JForth. */\r
107 #define LOAD_REGISTERS \\r
108         { \\r
109                 STKPTR = gCurrentTask->td_StackPtr; \\r
110                 TOS = M_POP; \\r
111                 TORPTR = gCurrentTask->td_ReturnPtr; \\r
112          }\r
113          \r
114 #define SAVE_REGISTERS \\r
115         { \\r
116                 gCurrentTask->td_ReturnPtr = TORPTR; \\r
117                 M_PUSH( TOS ); \\r
118                 gCurrentTask->td_StackPtr = STKPTR; \\r
119          }\r
120 #endif\r
121 \r
122 #define M_DOTS \\r
123         SAVE_REGISTERS; \\r
124         ffDotS( ); \\r
125         LOAD_REGISTERS;\r
126         \r
127 #define DO_VAR(varname) { PUSH_TOS; TOS = (cell_t) &varname; }\r
128 \r
129 #ifdef PF_SUPPORT_FP\r
130 #define M_THROW(err) \\r
131         { \\r
132                 ExceptionReturnCode = (ThrowCode)(err); \\r
133                 TORPTR = InitialReturnStack; /* Will cause return to 'C' */ \\r
134                 STKPTR = InitialDataStack; \\r
135                 FP_STKPTR = InitialFloatStack; \\r
136         }\r
137 #else\r
138 #define M_THROW(err) \\r
139         { \\r
140                 ExceptionReturnCode = (err); \\r
141                 TORPTR = InitialReturnStack; /* Will cause return to 'C' */ \\r
142                 STKPTR = InitialDataStack; \\r
143         }\r
144 #endif\r
145 \r
146 /***************************************************************\r
147 ** Other macros\r
148 ***************************************************************/\r
149 \r
150 #define BINARY_OP( op ) { TOS = M_POP op TOS; }\r
151 #define endcase break\r
152                 \r
153 #if defined(PF_NO_SHELL) || !defined(PF_SUPPORT_TRACE)\r
154         #define TRACENAMES /* no names */\r
155 #else\r
156 /* Display name of executing routine. */\r
157 static void TraceNames( ExecToken Token, cell_t Level )\r
158 {\r
159         char *DebugName;\r
160         cell_t i;\r
161         \r
162         if( ffTokenToName( Token, &DebugName ) )\r
163         {\r
164                 cell_t NumSpaces;\r
165                 if( gCurrentTask->td_OUT > 0 ) EMIT_CR;\r
166                 EMIT( '>' );\r
167                 for( i=0; i<Level; i++ )\r
168                 {\r
169                         MSG( "  " );\r
170                 }\r
171                 TypeName( DebugName );\r
172 /* Space out to column N then .S */\r
173                 NumSpaces = 30 - gCurrentTask->td_OUT;\r
174                 for( i=0; i < NumSpaces; i++ )\r
175                 {\r
176                         EMIT( ' ' );\r
177                 }\r
178                 ffDotS();\r
179 /* No longer needed?            gCurrentTask->td_OUT = 0; */ /* !!! Hack for ffDotS() */\r
180                 \r
181         }\r
182         else\r
183         {\r
184                 MSG_NUM_H("Couldn't find Name for ", Token);\r
185         }\r
186 }\r
187 \r
188 #define TRACENAMES \\r
189         if( (gVarTraceLevel > Level) ) \\r
190         { SAVE_REGISTERS; TraceNames( Token, Level ); LOAD_REGISTERS; }\r
191 #endif /* PF_NO_SHELL */\r
192 \r
193 /* Use local copy of CODE_BASE for speed. */\r
194 #define LOCAL_CODEREL_TO_ABS( a ) ((cell_t *) (((cell_t) a) + CodeBase))\r
195 \r
196 static const char *pfSelectFileModeCreate( int fam );\r
197 static const char *pfSelectFileModeOpen( int fam );\r
198 \r
199 /**************************************************************/\r
200 static const char *pfSelectFileModeCreate( int fam )\r
201 {\r
202         const char *famText = NULL;\r
203         switch( fam )\r
204         {\r
205         case (PF_FAM_WRITE_ONLY + PF_FAM_BINARY_FLAG):\r
206                 famText = PF_FAM_BIN_CREATE_WO;\r
207                 break;\r
208         case (PF_FAM_READ_WRITE + PF_FAM_BINARY_FLAG):\r
209                 famText = PF_FAM_BIN_CREATE_RW;\r
210                 break;\r
211         case PF_FAM_WRITE_ONLY:\r
212                 famText = PF_FAM_CREATE_WO;\r
213                 break;\r
214         case PF_FAM_READ_WRITE:\r
215                 famText = PF_FAM_CREATE_RW;\r
216                 break;\r
217         default:\r
218                 famText = "illegal";\r
219                 break;\r
220         }\r
221         return famText;\r
222 }\r
223 \r
224 /**************************************************************/\r
225 static const char *pfSelectFileModeOpen( int fam )\r
226 {\r
227         const char *famText = NULL;\r
228         switch( fam )\r
229         {\r
230         case (PF_FAM_READ_ONLY + PF_FAM_BINARY_FLAG):\r
231                 famText = PF_FAM_BIN_OPEN_RO;\r
232                 break;\r
233         case (PF_FAM_WRITE_ONLY + PF_FAM_BINARY_FLAG):\r
234                 famText = PF_FAM_BIN_CREATE_WO;\r
235                 break;\r
236         case (PF_FAM_READ_WRITE + PF_FAM_BINARY_FLAG):\r
237                 famText = PF_FAM_BIN_OPEN_RW;\r
238                 break;\r
239         case PF_FAM_READ_ONLY:\r
240                 famText = PF_FAM_OPEN_RO;\r
241                 break;\r
242         case PF_FAM_WRITE_ONLY:\r
243                 famText = PF_FAM_CREATE_WO;\r
244                 break;\r
245         case PF_FAM_READ_WRITE:\r
246         default:\r
247                 famText = PF_FAM_OPEN_RW;\r
248                 break;\r
249         }\r
250         return famText;\r
251 }\r
252 \r
253 /**************************************************************/\r
254 int pfCatch( ExecToken XT )\r
255 {\r
256         register cell_t  TopOfStack;    /* Cache for faster execution. */\r
257         register cell_t *DataStackPtr;\r
258         register cell_t *ReturnStackPtr;\r
259         register cell_t *InsPtr = NULL;\r
260         register cell_t  Token;\r
261         cell_t           Scratch;\r
262         \r
263 #ifdef PF_SUPPORT_FP\r
264         PF_FLOAT       fpTopOfStack;\r
265         PF_FLOAT      *FloatStackPtr;\r
266         PF_FLOAT       fpScratch;\r
267         PF_FLOAT       fpTemp;\r
268         PF_FLOAT      *InitialFloatStack;\r
269 #endif\r
270 #ifdef PF_SUPPORT_TRACE\r
271         cell_t Level = 0;\r
272 #endif\r
273         cell_t        *LocalsPtr = NULL;\r
274         cell_t         Temp;\r
275         cell_t        *InitialReturnStack;\r
276         cell_t        *InitialDataStack;\r
277         cell_t         FakeSecondary[2];\r
278         char          *CharPtr;\r
279         cell_t        *CellPtr;\r
280         FileStream    *FileID;\r
281         uint8_t         *CodeBase = CODE_BASE;\r
282         ThrowCode      ExceptionReturnCode = 0;\r
283         \r
284 /* FIXME\r
285         gExecutionDepth += 1;\r
286         PRT(("pfCatch( 0x%x ), depth = %d\n", XT, gExecutionDepth ));\r
287 */\r
288 \r
289 /*\r
290 ** Initialize FakeSecondary this way to avoid having stuff in the data section,\r
291 ** which is not supported for some embedded system loaders.\r
292 */\r
293         FakeSecondary[0] = 0;\r
294         FakeSecondary[1] = ID_EXIT; /* For EXECUTE */\r
295 \r
296 /* Move data from task structure to registers for speed. */\r
297         LOAD_REGISTERS;\r
298 \r
299 /* Save initial stack depths for THROW */\r
300         InitialReturnStack = TORPTR;\r
301         InitialDataStack   = STKPTR ;\r
302 #ifdef PF_SUPPORT_FP\r
303         InitialFloatStack  = FP_STKPTR;\r
304 #endif\r
305 \r
306         Token = XT;\r
307 \r
308         do\r
309         {\r
310 DBUG(("pfCatch: Token = 0x%x\n", Token ));\r
311 \r
312 /* --------------------------------------------------------------- */\r
313 /* If secondary, thread down code tree until we hit a primitive. */\r
314                 while( !IsTokenPrimitive( Token ) )\r
315                 {\r
316 #ifdef PF_SUPPORT_TRACE\r
317                         if((gVarTraceFlags & TRACE_INNER) )\r
318                         {\r
319                                 MSG("pfCatch: Secondary Token = 0x");\r
320                                 ffDotHex(Token);\r
321                                 MSG_NUM_H(", InsPtr = 0x", InsPtr);\r
322                         }\r
323                         TRACENAMES;\r
324 #endif\r
325 \r
326 /* Save IP on return stack like a JSR. */\r
327                         M_R_PUSH( InsPtr );\r
328                         \r
329 /* Convert execution token to absolute address. */\r
330                         InsPtr = (cell_t *) ( LOCAL_CODEREL_TO_ABS(Token) );\r
331 \r
332 /* Fetch token at IP. */\r
333                         Token = READ_CELL_DIC(InsPtr++);\r
334                         \r
335 #ifdef PF_SUPPORT_TRACE\r
336 /* Bump level for trace display */\r
337                         Level++;\r
338 #endif\r
339                 }\r
340 \r
341                 \r
342 #ifdef PF_SUPPORT_TRACE\r
343                 TRACENAMES;\r
344 #endif\r
345                         \r
346 /* Execute primitive Token. */\r
347                 switch( Token )\r
348                 {\r
349                         \r
350         /* Pop up a level in Forth inner interpreter.\r
351         ** Used to implement semicolon.\r
352         ** Put first in switch because ID_EXIT==0 */\r
353                 case ID_EXIT:\r
354                         InsPtr = ( cell_t *) M_R_POP;\r
355 #ifdef PF_SUPPORT_TRACE\r
356                         Level--;\r
357 #endif\r
358                         endcase;\r
359                                                 \r
360                 case ID_1MINUS:  TOS--; endcase;\r
361                         \r
362                 case ID_1PLUS:   TOS++; endcase;\r
363                         \r
364 #ifndef PF_NO_SHELL\r
365                 case ID_2LITERAL:\r
366                         ff2Literal( TOS, M_POP );\r
367                         M_DROP;\r
368                         endcase;\r
369 #endif  /* !PF_NO_SHELL */\r
370 \r
371                 case ID_2LITERAL_P:\r
372 /* hi part stored first, put on top of stack */\r
373                         PUSH_TOS;\r
374                         TOS = READ_CELL_DIC(InsPtr++);\r
375                         M_PUSH(READ_CELL_DIC(InsPtr++));\r
376                         endcase;\r
377                         \r
378                 case ID_2MINUS:  TOS -= 2; endcase;\r
379                         \r
380                 case ID_2PLUS:   TOS += 2; endcase;\r
381                 \r
382                 \r
383                 case ID_2OVER:  /* ( a b c d -- a b c d a b ) */\r
384                         PUSH_TOS;\r
385                         Scratch = M_STACK(3);\r
386                         M_PUSH(Scratch);\r
387                         TOS = M_STACK(3);\r
388                         endcase;\r
389                         \r
390                 case ID_2SWAP:  /* ( a b c d -- c d a b ) */\r
391                         Scratch = M_STACK(0);    /* c */\r
392                         M_STACK(0) = M_STACK(2); /* a */\r
393                         M_STACK(2) = Scratch;    /* c */\r
394                         Scratch = TOS;           /* d */\r
395                         TOS = M_STACK(1);        /* b */\r
396                         M_STACK(1) = Scratch;    /* d */\r
397                         endcase;\r
398                         \r
399                 case ID_2DUP:   /* ( a b -- a b a b ) */\r
400                         PUSH_TOS;\r
401                         Scratch = M_STACK(1);\r
402                         M_PUSH(Scratch);\r
403                         endcase;\r
404                         \r
405                 case ID_2_R_FETCH:\r
406                         PUSH_TOS;\r
407                         M_PUSH( (*(TORPTR+1)) );\r
408                         TOS = (*(TORPTR));\r
409                         endcase;\r
410 \r
411                 case ID_2_R_FROM:\r
412                         PUSH_TOS;\r
413                         TOS = M_R_POP;\r
414                         M_PUSH( M_R_POP );\r
415                         endcase;\r
416 \r
417                 case ID_2_TO_R:\r
418                         M_R_PUSH( M_POP );\r
419                         M_R_PUSH( TOS );\r
420                         M_DROP;\r
421                         endcase;\r
422                 \r
423                 case ID_ACCEPT_P: /* ( c-addr +n1 -- +n2 ) */\r
424                         CharPtr = (char *) M_POP;\r
425                         TOS = ioAccept( CharPtr, TOS );\r
426                         endcase;\r
427                         \r
428 #ifndef PF_NO_SHELL\r
429                 case ID_ALITERAL:\r
430                         ffALiteral( ABS_TO_CODEREL(TOS) );\r
431                         M_DROP;\r
432                         endcase;\r
433 #endif  /* !PF_NO_SHELL */\r
434 \r
435                 case ID_ALITERAL_P:\r
436                         PUSH_TOS;\r
437                         TOS = (cell_t) LOCAL_CODEREL_TO_ABS( READ_CELL_DIC(InsPtr++) );\r
438                         endcase;\r
439                         \r
440 /* Allocate some extra and put validation identifier at base */\r
441 #define PF_MEMORY_VALIDATOR  (0xA81B4D69)\r
442                 case ID_ALLOCATE:\r
443                         /* Allocate at least one cell's worth because we clobber first cell. */\r
444                         if ( TOS < sizeof(cell_t) )\r
445                         {\r
446                                 Temp = sizeof(cell_t);\r
447                         }\r
448                         else\r
449                         {\r
450                                 Temp = TOS;\r
451                         }\r
452                         /* Allocate extra cells worth because we store validation info. */\r
453                         CellPtr = (cell_t *) pfAllocMem( Temp + sizeof(cell_t) );\r
454                         if( CellPtr )\r
455                         {\r
456 /* This was broken into two steps because different compilers incremented\r
457 ** CellPtr before or after the XOR step. */\r
458                                 Temp = (cell_t)CellPtr ^ PF_MEMORY_VALIDATOR;\r
459                                 *CellPtr++ = Temp;\r
460                                 M_PUSH( (cell_t) CellPtr );\r
461                                 TOS = 0;\r
462                         }\r
463                         else\r
464                         {\r
465                                 M_PUSH( 0 );\r
466                                 TOS = -1;  /* FIXME Fix error code. */\r
467                         }\r
468                         endcase;\r
469 \r
470                 case ID_AND:     BINARY_OP( & ); endcase;\r
471                 \r
472                 case ID_ARSHIFT:     BINARY_OP( >> ); endcase;  /* Arithmetic right shift */\r
473                 \r
474                 case ID_BODY_OFFSET:\r
475                         PUSH_TOS;\r
476                         TOS = CREATE_BODY_OFFSET;\r
477                         endcase;\r
478                         \r
479 /* Branch is followed by an offset relative to address of offset. */\r
480                 case ID_BRANCH:\r
481 DBUGX(("Before Branch: IP = 0x%x\n", InsPtr ));\r
482                         M_BRANCH;\r
483 DBUGX(("After Branch: IP = 0x%x\n", InsPtr ));\r
484                         endcase;\r
485 \r
486                 case ID_BYE:\r
487                         M_THROW( THROW_BYE );\r
488                         endcase;\r
489 \r
490                 case ID_BAIL:\r
491                         MSG("Emergency exit.\n");\r
492                         EXIT(1);\r
493                         endcase;\r
494                 \r
495                 case ID_CATCH:\r
496                         Scratch = TOS;\r
497                         TOS = M_POP;\r
498                         SAVE_REGISTERS;\r
499                         Scratch = pfCatch( Scratch );\r
500                         LOAD_REGISTERS;\r
501                         M_PUSH( TOS );\r
502                         TOS = Scratch;\r
503                         endcase;\r
504 \r
505                 case ID_CALL_C:\r
506                         SAVE_REGISTERS;\r
507                         Scratch = READ_CELL_DIC(InsPtr++);\r
508                         CallUserFunction( Scratch & 0xFFFF,\r
509                                 (Scratch >> 31) & 1,\r
510                                 (Scratch >> 24) & 0x7F );\r
511                         LOAD_REGISTERS;\r
512                         endcase;\r
513                                 \r
514                 /* Support 32/64 bit operation. */\r
515                 case ID_CELL:\r
516                                 M_PUSH( TOS );\r
517                                 TOS = sizeof(cell_t);\r
518                                 endcase;\r
519                                 \r
520                 case ID_CELLS:\r
521                                 TOS = TOS * sizeof(cell_t);\r
522                                 endcase;\r
523                                 \r
524                 case ID_CFETCH:   TOS = *((uint8_t *) TOS); endcase;\r
525 \r
526                 case ID_CMOVE: /* ( src dst n -- ) */\r
527                         {\r
528                                 register char *DstPtr = (char *) M_POP; /* dst */\r
529                                 CharPtr = (char *) M_POP;    /* src */\r
530                                 for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ )\r
531                                 {\r
532                                         *DstPtr++ = *CharPtr++;\r
533                                 }\r
534                                 M_DROP;\r
535                         }\r
536                         endcase;\r
537                         \r
538                 case ID_CMOVE_UP: /* ( src dst n -- ) */\r
539                         {\r
540                                 register char *DstPtr = ((char *) M_POP) + TOS; /* dst */\r
541                                 CharPtr = ((char *) M_POP) + TOS;;    /* src */\r
542                                 for( Scratch=0; (ucell_t) Scratch < (ucell_t) TOS ; Scratch++ )\r
543                                 {\r
544                                         *(--DstPtr) = *(--CharPtr);\r
545                                 }\r
546                                 M_DROP;\r
547                         }\r
548                         endcase;\r
549                 \r
550 #ifndef PF_NO_SHELL\r
551                 case ID_COLON:\r
552                         SAVE_REGISTERS;\r
553                         ffColon( );\r
554                         LOAD_REGISTERS;\r
555                         endcase;\r
556                 case ID_COLON_P:  /* ( $name xt -- ) */\r
557                         CreateDicEntry( TOS, (char *) M_POP, 0 );\r
558                         M_DROP;\r
559                         endcase;\r
560 #endif  /* !PF_NO_SHELL */\r
561 \r
562                 case ID_COMPARE:\r
563                         {\r
564                                 const char *s1, *s2;\r
565                                 cell_t len1;\r
566                                 s2 = (const char *) M_POP;\r
567                                 len1 = M_POP;\r
568                                 s1 = (const char *) M_POP;\r
569                                 TOS = ffCompare( s1, len1, s2, TOS );\r
570                         }\r
571                         endcase;\r
572                         \r
573 /* ( a b -- flag , Comparisons ) */\r
574                 case ID_COMP_EQUAL:\r
575                         TOS = ( TOS == M_POP ) ? FTRUE : FFALSE ;\r
576                         endcase;\r
577                 case ID_COMP_NOT_EQUAL:\r
578                         TOS = ( TOS != M_POP ) ? FTRUE : FFALSE ;\r
579                         endcase;\r
580                 case ID_COMP_GREATERTHAN:\r
581                         TOS = ( M_POP > TOS ) ? FTRUE : FFALSE ;\r
582                         endcase;\r
583                 case ID_COMP_LESSTHAN:\r
584                         TOS = (  M_POP < TOS ) ? FTRUE : FFALSE ;\r
585                         endcase;\r
586                 case ID_COMP_U_GREATERTHAN:\r
587                         TOS = ( ((ucell_t)M_POP) > ((ucell_t)TOS) ) ? FTRUE : FFALSE ;\r
588                         endcase;\r
589                 case ID_COMP_U_LESSTHAN:\r
590                         TOS = ( ((ucell_t)M_POP) < ((ucell_t)TOS) ) ? FTRUE : FFALSE ;\r
591                         endcase;\r
592                 case ID_COMP_ZERO_EQUAL:\r
593                         TOS = ( TOS == 0 ) ? FTRUE : FFALSE ;\r
594                         endcase;\r
595                 case ID_COMP_ZERO_NOT_EQUAL:\r
596                         TOS = ( TOS != 0 ) ? FTRUE : FALSE ;\r
597                         endcase;\r
598                 case ID_COMP_ZERO_GREATERTHAN:\r
599                         TOS = ( TOS > 0 ) ? FTRUE : FFALSE ;\r
600                         endcase;\r
601                 case ID_COMP_ZERO_LESSTHAN:\r
602                         TOS = ( TOS < 0 ) ? FTRUE : FFALSE ;\r
603                         endcase;\r
604                         \r
605                 case ID_CR:\r
606                         EMIT_CR;\r
607                         endcase;\r
608                 \r
609 #ifndef PF_NO_SHELL\r
610                 case ID_CREATE:\r
611                         SAVE_REGISTERS;\r
612                         ffCreate();\r
613                         LOAD_REGISTERS;\r
614                         endcase;\r
615 #endif  /* !PF_NO_SHELL */\r
616 \r
617                 case ID_CREATE_P:\r
618                         PUSH_TOS;\r
619 /* Put address of body on stack.  Insptr points after code start. */\r
620                         TOS = (cell_t) ((char *)InsPtr - sizeof(cell_t) + CREATE_BODY_OFFSET );\r
621                         endcase;\r
622         \r
623                 case ID_CSTORE: /* ( c caddr -- ) */\r
624                         *((uint8_t *) TOS) = (uint8_t) M_POP;\r
625                         M_DROP;\r
626                         endcase;\r
627 \r
628 /* Double precision add. */\r
629                 case ID_D_PLUS:  /* D+ ( al ah bl bh -- sl sh ) */ \r
630                         {\r
631                                 register ucell_t ah,al,bl,sh,sl;\r
632 #define bh TOS\r
633                                 bl = M_POP;\r
634                                 ah = M_POP;\r
635                                 al = M_POP;\r
636                                 sh = 0;\r
637                                 sl = al + bl;\r
638                                 if( sl < bl ) sh = 1; /* Carry */\r
639                                 sh += ah + bh;\r
640                                 M_PUSH( sl );\r
641                                 TOS = sh;\r
642 #undef bh\r
643                         }\r
644                         endcase;\r
645         \r
646 /* Double precision subtract. */\r
647                 case ID_D_MINUS:  /* D- ( al ah bl bh -- sl sh ) */ \r
648                         {\r
649                                 register ucell_t ah,al,bl,sh,sl;\r
650 #define bh TOS\r
651                                 bl = M_POP;\r
652                                 ah = M_POP;\r
653                                 al = M_POP;\r
654                                 sh = 0;\r
655                                 sl = al - bl;\r
656                                 if( al < bl ) sh = 1; /* Borrow */\r
657                                 sh = ah - bh - sh;\r
658                                 M_PUSH( sl );\r
659                                 TOS = sh;\r
660 #undef bh\r
661                         }\r
662                         endcase;\r
663                         \r
664 /* Assume 8-bit char and calculate cell width. */\r
665 #define NBITS ((sizeof(ucell_t)) * 8)\r
666 /* Define half the number of bits in a cell. */\r
667 #define HNBITS (NBITS / 2)\r
668 /* Assume two-complement arithmetic to calculate lower half. */\r
669 #define LOWER_HALF(n) ((n) & (((ucell_t)1 << HNBITS) - 1))\r
670 #define HIGH_BIT ((ucell_t)1 << (NBITS - 1))\r
671 \r
672 /* Perform cell*cell bit multiply for a 2 cell result, by factoring into half cell quantities.\r
673  * Using an improved algorithm suggested by Steve Green.\r
674  * Converted to 64-bit by Aleksej Saushev.\r
675  */\r
676                 case ID_D_UMTIMES:  /* UM* ( a b -- lo hi ) */ \r
677                         {\r
678                                 ucell_t ahi, alo, bhi, blo; /* input parts */\r
679                                 ucell_t lo, hi, temp;\r
680 /* Get values from stack. */\r
681                                 ahi = M_POP;\r
682                                 bhi = TOS;\r
683 /* Break into hi and lo 16 bit parts. */\r
684                                 alo = LOWER_HALF(ahi);\r
685                                 ahi = ahi >> HNBITS;\r
686                                 blo = LOWER_HALF(bhi);\r
687                                 bhi = bhi >> HNBITS;\r
688 \r
689                                 lo = 0;\r
690                                 hi = 0;\r
691 /* higher part: ahi * bhi */\r
692                                 hi += ahi * bhi;\r
693 /* middle (overlapping) part: ahi * blo */\r
694                                 temp = ahi * blo;\r
695                                 lo += LOWER_HALF(temp);\r
696                                 hi += temp >> HNBITS;\r
697 /* middle (overlapping) part: alo * bhi  */\r
698                                 temp = alo * bhi;\r
699                                 lo += LOWER_HALF(temp);\r
700                                 hi += temp >> HNBITS;\r
701 /* lower part: alo * blo */\r
702                                 temp = alo * blo;\r
703 /* its higher half overlaps with middle's lower half: */\r
704                                 lo += temp >> HNBITS;\r
705 /* process carry: */\r
706                                 hi += lo >> HNBITS;\r
707                                 lo = LOWER_HALF(lo);\r
708 /* combine lower part of result: */\r
709                                 lo = (lo << HNBITS) + LOWER_HALF(temp);\r
710 \r
711                                 M_PUSH( lo );\r
712                                 TOS = hi;\r
713                         }\r
714                         endcase;\r
715                         \r
716 /* Perform cell*cell bit multiply for 2 cell result, using shift and add. */\r
717                 case ID_D_MTIMES:  /* M* ( a b -- pl ph ) */ \r
718                         {\r
719                                 ucell_t ahi, alo, bhi, blo; /* input parts */\r
720                                 ucell_t lo, hi, temp;\r
721                                 int sg;\r
722 /* Get values from stack. */\r
723                                 ahi = M_POP;\r
724                                 bhi = TOS;\r
725 \r
726 /* Calculate product sign: */\r
727                                 sg = ((cell_t)(ahi ^ bhi) < 0);\r
728 /* Take absolute values and reduce to um* */\r
729                                 if ((cell_t)ahi < 0) ahi = (ucell_t)(-ahi);\r
730                                 if ((cell_t)bhi < 0) bhi = (ucell_t)(-bhi);\r
731 \r
732 /* Break into hi and lo 16 bit parts. */\r
733                                 alo = LOWER_HALF(ahi);\r
734                                 ahi = ahi >> HNBITS;\r
735                                 blo = LOWER_HALF(bhi);\r
736                                 bhi = bhi >> HNBITS;\r
737 \r
738                                 lo = 0;\r
739                                 hi = 0;\r
740 /* higher part: ahi * bhi */\r
741                                 hi += ahi * bhi;\r
742 /* middle (overlapping) part: ahi * blo */\r
743                                 temp = ahi * blo;\r
744                                 lo += LOWER_HALF(temp);\r
745                                 hi += temp >> HNBITS;\r
746 /* middle (overlapping) part: alo * bhi  */\r
747                                 temp = alo * bhi;\r
748                                 lo += LOWER_HALF(temp);\r
749                                 hi += temp >> HNBITS;\r
750 /* lower part: alo * blo */\r
751                                 temp = alo * blo;\r
752 /* its higher half overlaps with middle's lower half: */\r
753                                 lo += temp >> HNBITS;\r
754 /* process carry: */\r
755                                 hi += lo >> HNBITS;\r
756                                 lo = LOWER_HALF(lo);\r
757 /* combine lower part of result: */\r
758                                 lo = (lo << HNBITS) + LOWER_HALF(temp);\r
759 \r
760 /* Negate product if one operand negative. */\r
761                                 if(sg)\r
762                                 {\r
763                                         /* lo = (ucell_t)(- lo); */\r
764                                         lo = ~lo + 1;\r
765                                         hi = ~hi + ((lo == 0) ? 1 : 0);\r
766                                 }\r
767 \r
768                                 M_PUSH( lo );\r
769                                 TOS = hi;\r
770                         }\r
771                         endcase;\r
772 \r
773 #define DULT(du1l,du1h,du2l,du2h) ( (du2h<du1h) ? FALSE : ( (du2h==du1h) ? (du1l<du2l) : TRUE) )\r
774 /* Perform 2 cell by 1 cell divide for 1 cell result and remainder, using shift and subtract. */\r
775                 case ID_D_UMSMOD:  /* UM/MOD ( al ah bdiv -- rem q ) */ \r
776                         {\r
777                                 ucell_t ah,al, q,di, bl,bh, sl,sh;\r
778                                 ah = M_POP;\r
779                                 al = M_POP;\r
780                                 bh = TOS;\r
781                                 bl = 0;\r
782                                 q = 0;\r
783                                 for( di=0; di<NBITS; di++ )\r
784                                 {\r
785                                         if( !DULT(al,ah,bl,bh) )\r
786                                         {\r
787                                                 sh = 0;\r
788                                                 sl = al - bl;\r
789                                                 if( al < bl ) sh = 1; /* Borrow */\r
790                                                 sh = ah - bh - sh;\r
791                                                 ah = sh;\r
792                                                 al = sl;\r
793                                                 q |= 1;\r
794                                         }\r
795                                         q = q << 1;\r
796                                         bl = (bl >> 1) | (bh << (NBITS-1));\r
797                                         bh = bh >> 1;\r
798                                 }\r
799                                 if( !DULT(al,ah,bl,bh) )\r
800                                 {\r
801                                 \r
802                                         al = al - bl;\r
803                                         q |= 1;\r
804                                 }\r
805                                 M_PUSH( al );  /* rem */\r
806                                 TOS = q;\r
807                         }\r
808                         endcase;\r
809 \r
810 /* Perform 2 cell by 1 cell divide for 2 cell result and remainder, using shift and subtract. */\r
811                 case ID_D_MUSMOD:  /* MU/MOD ( al am bdiv -- rem ql qh ) */ \r
812                         {\r
813                                 register ucell_t ah,am,al,ql,qh,di;\r
814 #define bdiv ((ucell_t)TOS)\r
815                                 ah = 0;\r
816                                 am = M_POP;\r
817                                 al = M_POP;\r
818                                 qh = ql = 0;\r
819                                 for( di=0; di<2*NBITS; di++ )\r
820                                 {\r
821                                         if( bdiv <= ah )\r
822                                         {\r
823                                                 ah = ah - bdiv;\r
824                                                 ql |= 1;\r
825                                         }\r
826                                         qh = (qh << 1) | (ql >> (NBITS-1));\r
827                                         ql = ql << 1;\r
828                                         ah = (ah << 1) | (am >> (NBITS-1));\r
829                                         am = (am << 1) | (al >> (NBITS-1));\r
830                                         al = al << 1;\r
831 DBUG(("XX ah,m,l = 0x%8x,%8x,%8x - qh,l = 0x%8x,%8x\n", ah,am,al, qh,ql ));\r
832                                 }\r
833                                 if( bdiv <= ah )\r
834                                 {\r
835                                         ah = ah - bdiv;\r
836                                         ql |= 1;\r
837                                 }\r
838                                 M_PUSH( ah ); /* rem */\r
839                                 M_PUSH( ql );\r
840                                 TOS = qh;\r
841 #undef bdiv\r
842                         }\r
843                         endcase;\r
844 \r
845 #ifndef PF_NO_SHELL\r
846                 case ID_DEFER:\r
847                         ffDefer( );\r
848                         endcase;\r
849 #endif  /* !PF_NO_SHELL */\r
850 \r
851                 case ID_DEFER_P:\r
852                         endcase;\r
853 \r
854                 case ID_DEPTH:\r
855                         PUSH_TOS;\r
856                         TOS = gCurrentTask->td_StackBase - STKPTR;\r
857                         endcase;\r
858                         \r
859                 case ID_DIVIDE:     BINARY_OP( / ); endcase;\r
860                         \r
861                 case ID_DOT:\r
862                         ffDot( TOS );\r
863                         M_DROP;\r
864                         endcase;\r
865                         \r
866                 case ID_DOTS:\r
867                         M_DOTS;\r
868                         endcase;\r
869                         \r
870                 case ID_DROP:  M_DROP; endcase;\r
871                         \r
872                 case ID_DUMP:\r
873                         Scratch = M_POP;\r
874                         DumpMemory( (char *) Scratch, TOS );\r
875                         M_DROP;\r
876                         endcase;\r
877 \r
878                 case ID_DUP:   M_DUP; endcase;\r
879                 \r
880                 case ID_DO_P: /* ( limit start -- ) ( R: -- start limit ) */\r
881                         M_R_PUSH( TOS );\r
882                         M_R_PUSH( M_POP );\r
883                         M_DROP;\r
884                         endcase;\r
885                         \r
886                 case ID_EOL:    /* ( -- end_of_line_char ) */\r
887                         PUSH_TOS;\r
888                         TOS = (cell_t) '\n';\r
889                         endcase;\r
890                         \r
891                 case ID_ERRORQ_P:  /* ( flag num -- , quit if flag true ) */\r
892                         Scratch = TOS;\r
893                         M_DROP;\r
894                         if(TOS)\r
895                         {\r
896                                 M_THROW(Scratch);\r
897                         }\r
898                         else\r
899                         {\r
900                                 M_DROP;\r
901                         }\r
902                         endcase;\r
903                         \r
904                 case ID_EMIT_P:\r
905                         EMIT( (char) TOS );\r
906                         M_DROP;\r
907                         endcase;\r
908                         \r
909                 case ID_EXECUTE:\r
910 /* Save IP on return stack like a JSR. */\r
911                         M_R_PUSH( InsPtr );\r
912 #ifdef PF_SUPPORT_TRACE\r
913 /* Bump level for trace. */\r
914                         Level++;\r
915 #endif\r
916                         if( IsTokenPrimitive( TOS ) )\r
917                         {\r
918                                 WRITE_CELL_DIC( (cell_t *) &FakeSecondary[0], TOS);   /* Build a fake secondary and execute it. */\r
919                                 InsPtr = &FakeSecondary[0];\r
920                         }\r
921                         else\r
922                         {\r
923                                 InsPtr = (cell_t *) LOCAL_CODEREL_TO_ABS(TOS);\r
924                         }\r
925                         M_DROP;\r
926                         endcase;\r
927                         \r
928                 case ID_FETCH:\r
929 #if (defined(PF_BIG_ENDIAN_DIC) || defined(PF_LITTLE_ENDIAN_DIC))\r
930                         if( IN_DICS( TOS ) )\r
931                         {\r
932                                 TOS = (cell_t) READ_CELL_DIC((cell_t *)TOS);\r
933                         }\r
934                         else\r
935                         {\r
936                                 TOS = *((cell_t *)TOS);\r
937                         }\r
938 #else\r
939                         TOS = *((cell_t *)TOS);\r
940 #endif\r
941                         endcase;\r
942                 \r
943                 case ID_FILE_CREATE: /* ( c-addr u fam -- fid ior ) */\r
944 /* Build NUL terminated name string. */\r
945                         Scratch = M_POP; /* u */\r
946                         Temp = M_POP;    /* caddr */\r
947                         if( Scratch < TIB_SIZE-2 )\r
948                         {\r
949                                 const char *famText = pfSelectFileModeCreate( TOS );\r
950                                 pfCopyMemory( gScratch, (char *) Temp, (ucell_t) Scratch );\r
951                                 gScratch[Scratch] = '\0';\r
952                                 DBUG(("Create file = %s with famTxt %s\n", gScratch, famText ));\r
953                                 FileID = sdOpenFile( gScratch, famText );\r
954                                 TOS = ( FileID == NULL ) ? -1 : 0 ;\r
955                                 M_PUSH( (cell_t) FileID );\r
956                         }\r
957                         else\r
958                         {\r
959                                 ERR("Filename too large for name buffer.\n");\r
960                                 M_PUSH( 0 );\r
961                                 TOS = -2;\r
962                         }\r
963                         endcase;\r
964 \r
965                 case ID_FILE_OPEN: /* ( c-addr u fam -- fid ior ) */\r
966 /* Build NUL terminated name string. */\r
967                         Scratch = M_POP; /* u */\r
968                         Temp = M_POP;    /* caddr */\r
969                         if( Scratch < TIB_SIZE-2 )\r
970                         {\r
971                                 const char *famText = pfSelectFileModeOpen( TOS );\r
972                                 pfCopyMemory( gScratch, (char *) Temp, (ucell_t) Scratch );\r
973                                 gScratch[Scratch] = '\0';\r
974                                 DBUG(("Open file = %s\n", gScratch ));\r
975                                 FileID = sdOpenFile( gScratch, famText );\r
976 \r
977                                 TOS = ( FileID == NULL ) ? -1 : 0 ;\r
978                                 M_PUSH( (cell_t) FileID );\r
979                         }\r
980                         else\r
981                         {\r
982                                 ERR("Filename too large for name buffer.\n");\r
983                                 M_PUSH( 0 );\r
984                                 TOS = -2;\r
985                         }\r
986                         endcase;\r
987                         \r
988                 case ID_FILE_CLOSE: /* ( fid -- ior ) */\r
989                         TOS = sdCloseFile( (FileStream *) TOS );\r
990                         endcase;\r
991                                 \r
992                 case ID_FILE_READ: /* ( addr len fid -- u2 ior ) */\r
993                         FileID = (FileStream *) TOS;\r
994                         Scratch = M_POP;\r
995                         CharPtr = (char *) M_POP;\r
996                         Temp = sdReadFile( CharPtr, 1, Scratch, FileID );\r
997                         M_PUSH(Temp);\r
998                         TOS = 0;\r
999                         endcase;\r
1000                                 \r
1001                 case ID_FILE_SIZE: /* ( fid -- ud ior ) */\r
1002 /* Determine file size by seeking to end and returning position. */\r
1003                         FileID = (FileStream *) TOS;\r
1004                         Scratch = sdTellFile( FileID );\r
1005                         sdSeekFile( FileID, 0, PF_SEEK_END );\r
1006                         M_PUSH( sdTellFile( FileID ));\r
1007                         sdSeekFile( FileID, Scratch, PF_SEEK_SET );\r
1008                         TOS = (Scratch < 0) ? -4 : 0 ; /* !!! err num */\r
1009                         endcase;\r
1010 \r
1011                 case ID_FILE_WRITE: /* ( addr len fid -- ior ) */\r
1012                         FileID = (FileStream *) TOS;\r
1013                         Scratch = M_POP;\r
1014                         CharPtr = (char *) M_POP;\r
1015                         Temp = sdWriteFile( CharPtr, 1, Scratch, FileID );\r
1016                         TOS = (Temp != Scratch) ? -3 : 0;\r
1017                         endcase;\r
1018 \r
1019                 case ID_FILE_REPOSITION: /* ( pos fid -- ior ) */\r
1020                         FileID = (FileStream *) TOS;\r
1021                         Scratch = M_POP;\r
1022                         TOS = sdSeekFile( FileID, Scratch, PF_SEEK_SET );\r
1023                         endcase;\r
1024 \r
1025                 case ID_FILE_POSITION: /* ( pos fid -- ior ) */\r
1026                         M_PUSH( sdTellFile( (FileStream *) TOS ));\r
1027                         TOS = 0;\r
1028                         endcase;\r
1029 \r
1030                 case ID_FILE_RO: /* (  -- fam ) */\r
1031                         PUSH_TOS;\r
1032                         TOS = PF_FAM_READ_ONLY;\r
1033                         endcase;\r
1034                                 \r
1035                 case ID_FILE_RW: /* ( -- fam ) */\r
1036                         PUSH_TOS;\r
1037                         TOS = PF_FAM_READ_WRITE;\r
1038                         endcase;\r
1039 \r
1040                 case ID_FILE_WO: /* ( -- fam ) */\r
1041                         PUSH_TOS;\r
1042                         TOS = PF_FAM_WRITE_ONLY;\r
1043                         endcase;\r
1044 \r
1045                 case ID_FILE_BIN: /* ( -- fam ) */\r
1046                         TOS = TOS | PF_FAM_BINARY_FLAG;\r
1047                         endcase;\r
1048                                 \r
1049                 case ID_FILL: /* ( caddr num charval -- ) */\r
1050                         {\r
1051                                 register char *DstPtr;\r
1052                                 Temp = M_POP;    /* num */\r
1053                                 DstPtr = (char *) M_POP; /* dst */\r
1054                                 for( Scratch=0; (ucell_t) Scratch < (ucell_t) Temp ; Scratch++ )\r
1055                                 {\r
1056                                         *DstPtr++ = (char) TOS;\r
1057                                 }\r
1058                                 M_DROP;\r
1059                         }\r
1060                         endcase;\r
1061                         \r
1062 #ifndef PF_NO_SHELL\r
1063                 case ID_FIND:  /* ( $addr -- $addr 0 | xt +-1 ) */\r
1064                         TOS = ffFind( (char *) TOS, (ExecToken *) &Temp );\r
1065                         M_PUSH( Temp );\r
1066                         endcase;\r
1067                         \r
1068                 case ID_FINDNFA:\r
1069                         TOS = ffFindNFA( (const ForthString *) TOS, (const ForthString **) &Temp );\r
1070                         M_PUSH( (cell_t) Temp );\r
1071                         endcase;\r
1072 #endif  /* !PF_NO_SHELL */\r
1073 \r
1074                 case ID_FLUSHEMIT:\r
1075                         sdTerminalFlush();\r
1076                         endcase;\r
1077                         \r
1078 /* Validate memory before freeing. Clobber validator and first word. */\r
1079                 case ID_FREE:   /* ( addr -- result ) */\r
1080                         if( TOS == 0 )\r
1081                         {\r
1082                                 ERR("FREE passed NULL!\n");\r
1083                                 TOS = -2; /* FIXME error code */\r
1084                         }\r
1085                         else\r
1086                         {\r
1087                                 CellPtr = (cell_t *) TOS;\r
1088                                 CellPtr--;\r
1089                                 if( ((ucell_t)*CellPtr) != ((ucell_t)CellPtr ^ PF_MEMORY_VALIDATOR))\r
1090                                 {\r
1091                                         TOS = -2; /* FIXME error code */\r
1092                                 }\r
1093                                 else\r
1094                                 {\r
1095                                         CellPtr[0] = 0xDeadBeef;\r
1096                                         pfFreeMem((char *)CellPtr);\r
1097                                         TOS = 0;\r
1098                                 }\r
1099                         }\r
1100                         endcase;\r
1101                         \r
1102 #include "pfinnrfp.h"\r
1103 \r
1104                 case ID_HERE:\r
1105                         PUSH_TOS;\r
1106                         TOS = (cell_t)CODE_HERE;\r
1107                         endcase;\r
1108                 \r
1109                 case ID_NUMBERQ_P:   /* ( addr -- 0 | n 1 ) */\r
1110 /* Convert using number converter in 'C'.\r
1111 ** Only supports single precision for bootstrap.\r
1112 */\r
1113                         TOS = (cell_t) ffNumberQ( (char *) TOS, &Temp );\r
1114                         if( TOS == NUM_TYPE_SINGLE)\r
1115                         {\r
1116                                 M_PUSH( Temp );   /* Push single number */\r
1117                         }\r
1118                         endcase;\r
1119                         \r
1120                 case ID_I:  /* ( -- i , DO LOOP index ) */\r
1121                         PUSH_TOS;\r
1122                         TOS = M_R_PICK(1);\r
1123                         endcase;\r
1124 \r
1125 #ifndef PF_NO_SHELL\r
1126                 case ID_INCLUDE_FILE:\r
1127                         FileID = (FileStream *) TOS;\r
1128                         M_DROP;    /* Drop now so that INCLUDE has a clean stack. */\r
1129                         SAVE_REGISTERS;\r
1130                         Scratch = ffIncludeFile( FileID );\r
1131                         LOAD_REGISTERS;\r
1132                         if( Scratch ) M_THROW(Scratch)\r
1133                         endcase;\r
1134 #endif  /* !PF_NO_SHELL */\r
1135                         \r
1136 #ifndef PF_NO_SHELL\r
1137                 case ID_INTERPRET:\r
1138                         SAVE_REGISTERS;\r
1139                         Scratch = ffInterpret();\r
1140                         LOAD_REGISTERS;\r
1141                         if( Scratch ) M_THROW(Scratch)\r
1142                         endcase;\r
1143 #endif  /* !PF_NO_SHELL */\r
1144 \r
1145                 case ID_J:  /* ( -- j , second DO LOOP index ) */\r
1146                         PUSH_TOS;\r
1147                         TOS = M_R_PICK(3);\r
1148                         endcase;\r
1149 \r
1150                 case ID_KEY:\r
1151                         PUSH_TOS;\r
1152                         TOS = ioKey();\r
1153                         endcase;\r
1154                         \r
1155 #ifndef PF_NO_SHELL\r
1156                 case ID_LITERAL:\r
1157                         ffLiteral( TOS );\r
1158                         M_DROP;\r
1159                         endcase;\r
1160 #endif /* !PF_NO_SHELL */\r
1161 \r
1162                 case ID_LITERAL_P:\r
1163                         DBUG(("ID_LITERAL_P: InsPtr = 0x%x, *InsPtr = 0x%x\n", InsPtr, *InsPtr ));\r
1164                         PUSH_TOS;\r
1165                         TOS = READ_CELL_DIC(InsPtr++);\r
1166                         endcase;\r
1167         \r
1168 #ifndef PF_NO_SHELL\r
1169                 case ID_LOCAL_COMPILER: DO_VAR(gLocalCompiler_XT); endcase;\r
1170 #endif /* !PF_NO_SHELL */\r
1171 \r
1172                 case ID_LOCAL_FETCH: /* ( i <local> -- n , fetch from local ) */\r
1173                         TOS = *(LocalsPtr - TOS);\r
1174                         endcase;\r
1175 \r
1176 #define LOCAL_FETCH_N(num) \\r
1177                 case ID_LOCAL_FETCH_##num: /* ( <local> -- n , fetch from local ) */ \\r
1178                         PUSH_TOS; \\r
1179                         TOS = *(LocalsPtr -(num)); \\r
1180                         endcase;\r
1181 \r
1182                 LOCAL_FETCH_N(1);\r
1183                 LOCAL_FETCH_N(2);\r
1184                 LOCAL_FETCH_N(3);\r
1185                 LOCAL_FETCH_N(4);\r
1186                 LOCAL_FETCH_N(5);\r
1187                 LOCAL_FETCH_N(6);\r
1188                 LOCAL_FETCH_N(7);\r
1189                 LOCAL_FETCH_N(8);\r
1190                 \r
1191                 case ID_LOCAL_STORE:  /* ( n i <local> -- , store n in local ) */\r
1192                         *(LocalsPtr - TOS) = M_POP;\r
1193                         M_DROP;\r
1194                         endcase;\r
1195 \r
1196 #define LOCAL_STORE_N(num) \\r
1197                 case ID_LOCAL_STORE_##num:  /* ( n <local> -- , store n in local ) */ \\r
1198                         *(LocalsPtr - (num)) = TOS; \\r
1199                         M_DROP; \\r
1200                         endcase;\r
1201 \r
1202                 LOCAL_STORE_N(1);\r
1203                 LOCAL_STORE_N(2);\r
1204                 LOCAL_STORE_N(3);\r
1205                 LOCAL_STORE_N(4);\r
1206                 LOCAL_STORE_N(5);\r
1207                 LOCAL_STORE_N(6);\r
1208                 LOCAL_STORE_N(7);\r
1209                 LOCAL_STORE_N(8);\r
1210                 \r
1211                 case ID_LOCAL_PLUSSTORE:  /* ( n i <local> -- , add n to local ) */\r
1212                         *(LocalsPtr - TOS) += M_POP;\r
1213                         M_DROP;\r
1214                         endcase;\r
1215                         \r
1216                 case ID_LOCAL_ENTRY: /* ( x0 x1 ... xn n -- ) */\r
1217                 /* create local stack frame */\r
1218                         {\r
1219                                 cell_t i = TOS;\r
1220                                 cell_t *lp;\r
1221                                 DBUG(("LocalEntry: n = %d\n", TOS));\r
1222                                 /* End of locals. Create stack frame */\r
1223                                 DBUG(("LocalEntry: before RP@ = 0x%x, LP = 0x%x\n",\r
1224                                         TORPTR, LocalsPtr));\r
1225                                 M_R_PUSH(LocalsPtr);\r
1226                                 LocalsPtr = TORPTR;\r
1227                                 TORPTR -= TOS;\r
1228                                 DBUG(("LocalEntry: after RP@ = 0x%x, LP = 0x%x\n",\r
1229                                         TORPTR, LocalsPtr));\r
1230                                 lp = TORPTR;\r
1231                                 while(i-- > 0)\r
1232                                 {\r
1233                                         *lp++ = M_POP;    /* Load local vars from stack */\r
1234                                 }\r
1235                                 M_DROP;\r
1236                         }\r
1237                         endcase;\r
1238 \r
1239                 case ID_LOCAL_EXIT: /* cleanup up local stack frame */\r
1240                         DBUG(("LocalExit: before RP@ = 0x%x, LP = 0x%x\n",\r
1241                                 TORPTR, LocalsPtr));\r
1242                         TORPTR = LocalsPtr;\r
1243                         LocalsPtr = (cell_t *) M_R_POP;\r
1244                         DBUG(("LocalExit: after RP@ = 0x%x, LP = 0x%x\n",\r
1245                                 TORPTR, LocalsPtr));\r
1246                         endcase;\r
1247                         \r
1248 #ifndef PF_NO_SHELL\r
1249                 case ID_LOADSYS:\r
1250                         MSG("Load "); MSG(SYSTEM_LOAD_FILE); EMIT_CR;\r
1251                         FileID = sdOpenFile(SYSTEM_LOAD_FILE, "r");\r
1252                         if( FileID )\r
1253                         {\r
1254                                 SAVE_REGISTERS;\r
1255                                 Scratch = ffIncludeFile( FileID );\r
1256                                 LOAD_REGISTERS;\r
1257                                 sdCloseFile( FileID );\r
1258                                 if( Scratch ) M_THROW(Scratch);\r
1259                         }\r
1260                         else\r
1261                         {\r
1262                                  ERR(SYSTEM_LOAD_FILE); ERR(" could not be opened!\n");\r
1263                         }\r
1264                         endcase;\r
1265 #endif  /* !PF_NO_SHELL */\r
1266 \r
1267                 case ID_LEAVE_P: /* ( R: index limit --  ) */\r
1268                         M_R_DROP;\r
1269                         M_R_DROP;\r
1270                         M_BRANCH;\r
1271                         endcase;\r
1272 \r
1273                 case ID_LOOP_P: /* ( R: index limit -- | index limit ) */\r
1274                         Temp = M_R_POP; /* limit */\r
1275                         Scratch = M_R_POP + 1; /* index */\r
1276                         if( Scratch == Temp )\r
1277                         {\r
1278                                 InsPtr++;   /* skip branch offset, exit loop */\r
1279                         }\r
1280                         else\r
1281                         {\r
1282 /* Push index and limit back to R */\r
1283                                 M_R_PUSH( Scratch );\r
1284                                 M_R_PUSH( Temp );\r
1285 /* Branch back to just after (DO) */\r
1286                                 M_BRANCH;\r
1287                         }\r
1288                         endcase;\r
1289                                 \r
1290                 case ID_LSHIFT:     BINARY_OP( << ); endcase;\r
1291                 \r
1292                 case ID_MAX:\r
1293                         Scratch = M_POP;\r
1294                         TOS = ( TOS > Scratch ) ? TOS : Scratch ;\r
1295                         endcase;\r
1296                         \r
1297                 case ID_MIN:\r
1298                         Scratch = M_POP;\r
1299                         TOS = ( TOS < Scratch ) ? TOS : Scratch ;\r
1300                         endcase;\r
1301                         \r
1302                 case ID_MINUS:     BINARY_OP( - ); endcase;\r
1303                         \r
1304 #ifndef PF_NO_SHELL\r
1305                 case ID_NAME_TO_TOKEN:\r
1306                         TOS = (cell_t) NameToToken((ForthString *)TOS);\r
1307                         endcase;\r
1308                         \r
1309                 case ID_NAME_TO_PREVIOUS:\r
1310                         TOS = (cell_t) NameToPrevious((ForthString *)TOS);\r
1311                         endcase;\r
1312 #endif\r
1313                         \r
1314                 case ID_NOOP:\r
1315                         endcase;\r
1316                         \r
1317                 case ID_OR:     BINARY_OP( | ); endcase;\r
1318                 \r
1319                 case ID_OVER:\r
1320                         PUSH_TOS;\r
1321                         TOS = M_STACK(1);\r
1322                         endcase;\r
1323                         \r
1324                 case ID_PICK: /* ( ... n -- sp(n) ) */\r
1325                         TOS = M_STACK(TOS);\r
1326                         endcase;\r
1327 \r
1328                 case ID_PLUS:     BINARY_OP( + ); endcase;\r
1329                 \r
1330                 case ID_PLUS_STORE:   /* ( n addr -- , add n to *addr ) */\r
1331 #if (defined(PF_BIG_ENDIAN_DIC) || defined(PF_LITTLE_ENDIAN_DIC))\r
1332                         if( IN_DICS( TOS ) )\r
1333                         {\r
1334                                 Scratch = READ_CELL_DIC((cell_t *)TOS);\r
1335                                 Scratch += M_POP;\r
1336                                 WRITE_CELL_DIC((cell_t *)TOS,Scratch);\r
1337                         }\r
1338                         else\r
1339                         {\r
1340                                 *((cell_t *)TOS) += M_POP;\r
1341                         }\r
1342 #else\r
1343                         *((cell_t *)TOS) += M_POP;\r
1344 #endif\r
1345                         M_DROP;\r
1346                         endcase;\r
1347 \r
1348                 case ID_PLUSLOOP_P: /* ( delta -- ) ( R: index limit -- | index limit ) */\r
1349                         {\r
1350                                 ucell_t OldIndex, NewIndex, Limit;\r
1351 \r
1352                                 Limit = M_R_POP;\r
1353                                 OldIndex = M_R_POP;\r
1354                                 NewIndex = OldIndex + TOS; /* add TOS to index, not 1 */\r
1355 /* Do indices cross boundary between LIMIT-1 and LIMIT ? */\r
1356                                 if( ( (OldIndex - Limit) & ((Limit-1) - NewIndex) & 0x80000000 ) ||\r
1357                                     ( (NewIndex - Limit) & ((Limit-1) - OldIndex) & 0x80000000 ) )\r
1358                                 {\r
1359                                         InsPtr++;   /* skip branch offset, exit loop */\r
1360                                 }\r
1361                                 else\r
1362                                 {\r
1363 /* Push index and limit back to R */\r
1364                                         M_R_PUSH( NewIndex );\r
1365                                         M_R_PUSH( Limit );\r
1366 /* Branch back to just after (DO) */\r
1367                                         M_BRANCH;\r
1368                                 }\r
1369                                 M_DROP;\r
1370                         }\r
1371                         endcase;\r
1372 \r
1373                 case ID_QDO_P: /* (?DO) ( limit start -- ) ( R: -- start limit ) */\r
1374                         Scratch = M_POP;  /* limit */\r
1375                         if( Scratch == TOS )\r
1376                         {\r
1377 /* Branch to just after (LOOP) */\r
1378                                 M_BRANCH;\r
1379                         }\r
1380                         else\r
1381                         {\r
1382                                 M_R_PUSH( TOS );\r
1383                                 M_R_PUSH( Scratch );\r
1384                                 InsPtr++;   /* skip branch offset, enter loop */\r
1385                         }\r
1386                         M_DROP;\r
1387                         endcase;\r
1388 \r
1389                 case ID_QDUP:     if( TOS ) M_DUP; endcase;\r
1390 \r
1391                 case ID_QTERMINAL:  /* WARNING: Typically not fully implemented! */\r
1392                         PUSH_TOS;\r
1393                         TOS = sdQueryTerminal();\r
1394                         endcase;\r
1395                 \r
1396                 case ID_QUIT_P: /* Stop inner interpreter, go back to user. */\r
1397 #ifdef PF_SUPPORT_TRACE\r
1398                         Level = 0;\r
1399 #endif\r
1400                         M_THROW(THROW_QUIT);\r
1401                         endcase;\r
1402                         \r
1403                 case ID_R_DROP:\r
1404                         M_R_DROP;\r
1405                         endcase;\r
1406 \r
1407                 case ID_R_FETCH:\r
1408                         PUSH_TOS;\r
1409                         TOS = (*(TORPTR));\r
1410                         endcase;\r
1411                 \r
1412                 case ID_R_FROM:\r
1413                         PUSH_TOS;\r
1414                         TOS = M_R_POP;\r
1415                         endcase;\r
1416                         \r
1417                 case ID_REFILL:\r
1418                         PUSH_TOS;\r
1419                         TOS = (ffRefill() > 0) ? FTRUE : FFALSE;\r
1420                         endcase;\r
1421                         \r
1422 /* Resize memory allocated by ALLOCATE. */\r
1423                 case ID_RESIZE:  /* ( addr1 u -- addr2 result ) */\r
1424                         {\r
1425                                 cell_t *Addr1 = (cell_t *) M_POP;\r
1426                                 // Point to validator below users address.\r
1427                                 cell_t *FreePtr = Addr1 - 1;\r
1428                                 if( ((ucell_t)*FreePtr) != ((ucell_t)FreePtr ^ PF_MEMORY_VALIDATOR))\r
1429                                 {\r
1430                                         // 090218 - Fixed bug, was returning zero.\r
1431                                         M_PUSH( Addr1 );\r
1432                                         TOS = -3;\r
1433                                 }\r
1434                                 else\r
1435                                 {\r
1436                                         /* Try to allocate. */\r
1437                                         CellPtr = (cell_t *) pfAllocMem( TOS + sizeof(cell_t) );\r
1438                                         if( CellPtr )\r
1439                                         {\r
1440                                                 /* Copy memory including validation. */\r
1441                                                 pfCopyMemory( (char *) CellPtr, (char *) FreePtr, TOS + sizeof(cell_t) );\r
1442                                                 *CellPtr = (cell_t)(((ucell_t)CellPtr) ^ (ucell_t)PF_MEMORY_VALIDATOR);\r
1443                                                 // 090218 - Fixed bug that was incrementing the address twice. Thanks Reinhold Straub.\r
1444                                                 // Increment past validator to user address.\r
1445                                     M_PUSH( (cell_t) (CellPtr + 1) );\r
1446                                                 TOS = 0; // Result code.\r
1447                                                 // Mark old cell as dead so we can't free it twice.\r
1448                                                 FreePtr[0] = 0xDeadBeef;\r
1449                                                 pfFreeMem((char *) FreePtr);\r
1450                                         }\r
1451                                         else\r
1452                                         {\r
1453                                                 // 090218 - Fixed bug, was returning zero.\r
1454                                                 M_PUSH( Addr1 );\r
1455                                                 TOS = -4;  /* FIXME Fix error code. */\r
1456                                         }\r
1457                                 }\r
1458                         }\r
1459                         endcase;\r
1460                                 \r
1461 /*\r
1462 ** RP@ and RP! are called secondaries so we must\r
1463 ** account for the return address pushed before calling.\r
1464 */\r
1465                 case ID_RP_FETCH:    /* ( -- rp , address of top of return stack ) */\r
1466                         PUSH_TOS;\r
1467                         TOS = (cell_t)TORPTR;  /* value before calling RP@ */\r
1468                         endcase;\r
1469                         \r
1470                 case ID_RP_STORE:    /* ( rp -- , address of top of return stack ) */\r
1471                         TORPTR = (cell_t *) TOS;\r
1472                         M_DROP;\r
1473                         endcase;\r
1474                         \r
1475                 case ID_ROLL: /* ( xu xu-1 xu-1 ... x0 u -- xu-1 xu-1 ... x0 xu ) */\r
1476                         {\r
1477                                 cell_t ri;\r
1478                                 cell_t *srcPtr, *dstPtr;\r
1479                                 Scratch = M_STACK(TOS);\r
1480                                 srcPtr = &M_STACK(TOS-1);\r
1481                                 dstPtr = &M_STACK(TOS);\r
1482                                 for( ri=0; ri<TOS; ri++ )\r
1483                                 {\r
1484                                         *dstPtr-- = *srcPtr--;\r
1485                                 }\r
1486                                 TOS = Scratch;\r
1487                                 STKPTR++;\r
1488                         }\r
1489                         endcase;\r
1490 \r
1491                 case ID_ROT:  /* ( a b c -- b c a ) */\r
1492                         Scratch = M_POP;    /* b */\r
1493                         Temp = M_POP;       /* a */\r
1494                         M_PUSH( Scratch );  /* b */\r
1495                         PUSH_TOS;           /* c */\r
1496                         TOS = Temp;         /* a */\r
1497                         endcase;\r
1498 \r
1499 /* Logical right shift */\r
1500                 case ID_RSHIFT:     { TOS = ((ucell_t)M_POP) >> TOS; } endcase;   \r
1501                 \r
1502 #ifndef PF_NO_SHELL\r
1503                 case ID_SAVE_FORTH_P:   /* ( $name Entry NameSize CodeSize -- err ) */\r
1504                         {\r
1505                                 cell_t NameSize, CodeSize, EntryPoint;\r
1506                                 CodeSize = TOS;\r
1507                                 NameSize = M_POP;\r
1508                                 EntryPoint = M_POP;\r
1509                                 ForthStringToC( gScratch, (char *) M_POP );\r
1510                                 TOS =  ffSaveForth( gScratch, EntryPoint, NameSize, CodeSize );\r
1511                         }\r
1512                         endcase;\r
1513 #endif\r
1514 \r
1515 /* Source     Stack\r
1516 ** EVALUATE    >IN  SourceID=(-1)  1111\r
1517 ** keyboard    >IN  SourceID=(0)   2222\r
1518 ** file        >IN  lineNumber filePos  SourceID=(fileID)\r
1519 */\r
1520                 case ID_SAVE_INPUT:  /* FIXME - finish */\r
1521                         {\r
1522                         }\r
1523                         endcase;\r
1524 \r
1525                 case ID_SP_FETCH:    /* ( -- sp , address of top of stack, sorta ) */\r
1526                         PUSH_TOS;\r
1527                         TOS = (cell_t)STKPTR;\r
1528                         endcase;\r
1529                         \r
1530                 case ID_SP_STORE:    /* ( sp -- , address of top of stack, sorta ) */\r
1531                         STKPTR = (cell_t *) TOS;\r
1532                         M_DROP;\r
1533                         endcase;\r
1534                         \r
1535                 case ID_STORE: /* ( n addr -- , write n to addr ) */\r
1536 #if (defined(PF_BIG_ENDIAN_DIC) || defined(PF_LITTLE_ENDIAN_DIC))\r
1537                         if( IN_DICS( TOS ) )\r
1538                         {\r
1539                                 WRITE_CELL_DIC((cell_t *)TOS,M_POP);\r
1540                         }\r
1541                         else\r
1542                         {\r
1543                                 *((cell_t *)TOS) = M_POP;\r
1544                         }\r
1545 #else\r
1546                         *((cell_t *)TOS) = M_POP;\r
1547 #endif\r
1548                         M_DROP;\r
1549                         endcase;\r
1550 \r
1551                 case ID_SCAN: /* ( addr cnt char -- addr' cnt' ) */\r
1552                         Scratch = M_POP; /* cnt */\r
1553                         Temp = M_POP;    /* addr */\r
1554                         TOS = ffScan( (char *) Temp, Scratch, (char) TOS, &CharPtr );\r
1555                         M_PUSH((cell_t) CharPtr);\r
1556                         endcase;\r
1557                         \r
1558 #ifndef PF_NO_SHELL\r
1559                 case ID_SEMICOLON:\r
1560                         SAVE_REGISTERS;\r
1561                         Scratch = ffSemiColon();\r
1562                         LOAD_REGISTERS;\r
1563                         if( Scratch ) M_THROW( Scratch );\r
1564                         endcase;\r
1565 #endif /* !PF_NO_SHELL */\r
1566                         \r
1567                 case ID_SKIP: /* ( addr cnt char -- addr' cnt' ) */\r
1568                         Scratch = M_POP; /* cnt */\r
1569                         Temp = M_POP;    /* addr */\r
1570                         TOS = ffSkip( (char *) Temp, Scratch, (char) TOS, &CharPtr );\r
1571                         M_PUSH((cell_t) CharPtr);\r
1572                         endcase;\r
1573 \r
1574                 case ID_SOURCE:  /* ( -- c-addr num ) */\r
1575                         PUSH_TOS;\r
1576                         M_PUSH( (cell_t) gCurrentTask->td_SourcePtr );\r
1577                         TOS = (cell_t) gCurrentTask->td_SourceNum;\r
1578                         endcase;\r
1579                         \r
1580                 case ID_SOURCE_SET: /* ( c-addr num -- ) */\r
1581                         gCurrentTask->td_SourcePtr = (char *) M_POP;\r
1582                         gCurrentTask->td_SourceNum = TOS;\r
1583                         M_DROP;\r
1584                         endcase;\r
1585                         \r
1586                 case ID_SOURCE_ID:\r
1587                         PUSH_TOS;\r
1588                         TOS = ffConvertStreamToSourceID( gCurrentTask->td_InputStream ) ;\r
1589                         endcase;\r
1590                         \r
1591                 case ID_SOURCE_ID_POP:\r
1592                         PUSH_TOS;\r
1593                         TOS = ffConvertStreamToSourceID( ffPopInputStream() ) ;\r
1594                         endcase;\r
1595                         \r
1596                 case ID_SOURCE_ID_PUSH:  /* ( source-id -- ) */\r
1597                         TOS = (cell_t)ffConvertSourceIDToStream( TOS );\r
1598                         Scratch = ffPushInputStream((FileStream *) TOS );\r
1599                         if( Scratch )\r
1600                         {\r
1601                                 M_THROW(Scratch);\r
1602                         }\r
1603                         else M_DROP;\r
1604                         endcase;\r
1605                         \r
1606                 case ID_SWAP:\r
1607                         Scratch = TOS;\r
1608                         TOS = *STKPTR;\r
1609                         *STKPTR = Scratch;\r
1610                         endcase;\r
1611                         \r
1612                 case ID_TEST1:\r
1613                         PUSH_TOS;\r
1614                         M_PUSH( 0x11 );\r
1615                         M_PUSH( 0x22 );\r
1616                         TOS = 0x33;\r
1617                         endcase;\r
1618 \r
1619                 case ID_TEST2:\r
1620                         endcase;\r
1621 \r
1622                 case ID_THROW:  /* ( k*x err -- k*x | i*x err , jump to where CATCH was called ) */\r
1623                         if(TOS)\r
1624                         {\r
1625                                 M_THROW(TOS);\r
1626                         }\r
1627                         else M_DROP;\r
1628                         endcase;\r
1629 \r
1630 #ifndef PF_NO_SHELL\r
1631                 case ID_TICK:\r
1632                         PUSH_TOS;\r
1633                         CharPtr = (char *) ffWord( (char) ' ' );\r
1634                         TOS = ffFind( CharPtr, (ExecToken *) &Temp );\r
1635                         if( TOS == 0 )\r
1636                         {\r
1637                                 ERR("' could not find ");\r
1638                                 ioType( (char *) CharPtr+1, *CharPtr );\r
1639                                 M_THROW(-13);\r
1640                         }\r
1641                         else\r
1642                         {\r
1643                                 TOS = Temp;\r
1644                         }\r
1645                         endcase;\r
1646 #endif  /* !PF_NO_SHELL */\r
1647                         \r
1648                 case ID_TIMES: BINARY_OP( * ); endcase;\r
1649                         \r
1650                 case ID_TYPE:\r
1651                         Scratch = M_POP; /* addr */\r
1652                         ioType( (char *) Scratch, TOS );\r
1653                         M_DROP;\r
1654                         endcase;\r
1655 \r
1656                 case ID_TO_R:\r
1657                         M_R_PUSH( TOS );\r
1658                         M_DROP;\r
1659                         endcase;\r
1660 \r
1661                 case ID_VAR_BASE: DO_VAR(gVarBase); endcase;\r
1662                 case ID_VAR_CODE_BASE: DO_VAR(gCurrentDictionary->dic_CodeBase); endcase;\r
1663                 case ID_VAR_CODE_LIMIT: DO_VAR(gCurrentDictionary->dic_CodeLimit); endcase;\r
1664                 case ID_VAR_CONTEXT: DO_VAR(gVarContext); endcase;\r
1665                 case ID_VAR_DP: DO_VAR(gCurrentDictionary->dic_CodePtr.Cell); endcase;\r
1666                 case ID_VAR_ECHO: DO_VAR(gVarEcho); endcase;\r
1667                 case ID_VAR_HEADERS_BASE: DO_VAR(gCurrentDictionary->dic_HeaderBase); endcase;\r
1668                 case ID_VAR_HEADERS_LIMIT: DO_VAR(gCurrentDictionary->dic_HeaderLimit); endcase;\r
1669                 case ID_VAR_HEADERS_PTR: DO_VAR(gCurrentDictionary->dic_HeaderPtr); endcase;\r
1670                 case ID_VAR_NUM_TIB: DO_VAR(gCurrentTask->td_SourceNum); endcase;\r
1671                 case ID_VAR_OUT: DO_VAR(gCurrentTask->td_OUT); endcase;\r
1672                 case ID_VAR_STATE: DO_VAR(gVarState); endcase;\r
1673                 case ID_VAR_TO_IN: DO_VAR(gCurrentTask->td_IN); endcase;\r
1674                 case ID_VAR_TRACE_FLAGS: DO_VAR(gVarTraceFlags); endcase;\r
1675                 case ID_VAR_TRACE_LEVEL: DO_VAR(gVarTraceLevel); endcase;\r
1676                 case ID_VAR_TRACE_STACK: DO_VAR(gVarTraceStack); endcase;\r
1677                 case ID_VAR_RETURN_CODE: DO_VAR(gVarReturnCode); endcase;\r
1678 \r
1679                 case ID_WORD:\r
1680                         TOS = (cell_t) ffWord( (char) TOS );\r
1681                         endcase;\r
1682 \r
1683                 case ID_WORD_FETCH: /* ( waddr -- w ) */\r
1684 #if (defined(PF_BIG_ENDIAN_DIC) || defined(PF_LITTLE_ENDIAN_DIC))\r
1685                         if( IN_DICS( TOS ) )\r
1686                         {\r
1687                                 TOS = (uint16_t) READ_SHORT_DIC((uint16_t *)TOS);\r
1688                         }\r
1689                         else\r
1690                         {\r
1691                                 TOS = *((uint16_t *)TOS);\r
1692                         }\r
1693 #else\r
1694                         TOS = *((uint16_t *)TOS);\r
1695 #endif\r
1696                         endcase;\r
1697 \r
1698                 case ID_WORD_STORE: /* ( w waddr -- ) */\r
1699                         \r
1700 #if (defined(PF_BIG_ENDIAN_DIC) || defined(PF_LITTLE_ENDIAN_DIC))\r
1701                         if( IN_DICS( TOS ) )\r
1702                         {\r
1703                                 WRITE_SHORT_DIC((uint16_t *)TOS,(uint16_t)M_POP);\r
1704                         }\r
1705                         else\r
1706                         {\r
1707                                 *((uint16_t *)TOS) = (uint16_t) M_POP;\r
1708                         }\r
1709 #else\r
1710                         *((uint16_t *)TOS) = (uint16_t) M_POP;\r
1711 #endif\r
1712                         M_DROP;\r
1713                         endcase;\r
1714 \r
1715                 case ID_XOR: BINARY_OP( ^ ); endcase;\r
1716                                 \r
1717                                 \r
1718 /* Branch is followed by an offset relative to address of offset. */\r
1719                 case ID_ZERO_BRANCH:\r
1720 DBUGX(("Before 0Branch: IP = 0x%x\n", InsPtr ));\r
1721                         if( TOS == 0 )\r
1722                         {\r
1723                                 M_BRANCH;\r
1724                         }\r
1725                         else\r
1726                         {\r
1727                                 InsPtr++;      /* skip over offset */\r
1728                         }\r
1729                         M_DROP;\r
1730 DBUGX(("After 0Branch: IP = 0x%x\n", InsPtr ));\r
1731                         endcase;\r
1732                         \r
1733                 default:\r
1734                         ERR("pfCatch: Unrecognised token = 0x");\r
1735                         ffDotHex(Token);\r
1736                         ERR(" at 0x");\r
1737                         ffDotHex((cell_t) InsPtr);\r
1738                         EMIT_CR;\r
1739                         InsPtr = 0;\r
1740                         endcase;\r
1741                 }\r
1742                 \r
1743                 if(InsPtr) Token = READ_CELL_DIC(InsPtr++);   /* Traverse to next token in secondary. */\r
1744                 \r
1745 #ifdef PF_DEBUG\r
1746                 M_DOTS;\r
1747 #endif\r
1748 \r
1749 #if 0\r
1750                 if( _CrtCheckMemory() == 0 )\r
1751                 {\r
1752                         ERR("_CrtCheckMemory abort: InsPtr = 0x");\r
1753                         ffDotHex((int)InsPtr);\r
1754                         ERR("\n");\r
1755                 }\r
1756 #endif\r
1757 \r
1758         } while( (InitialReturnStack - TORPTR) > 0 );\r
1759 \r
1760         SAVE_REGISTERS;\r
1761         \r
1762         return ExceptionReturnCode;\r
1763 }\r