Annotation of gforth/engine.c, revision 1.23
1.1 anton 1: /*
2: Copyright 1992 by the ANSI figForth Development Group
3: */
4:
5: #include <ctype.h>
6: #include <stdio.h>
7: #include <string.h>
8: #include <math.h>
9: #include <sys/types.h>
10: #include <sys/stat.h>
11: #include <fcntl.h>
12: #include <assert.h>
13: #include <stdlib.h>
1.2 pazsan 14: #include <time.h>
1.6 pazsan 15: #include <sys/time.h>
1.22 anton 16: #include <unistd.h>
1.1 anton 17: #include "forth.h"
18: #include "io.h"
19:
1.20 anton 20: #ifndef SEEK_SET
21: /* should be defined in stdio.h, but some systems don't have it */
22: #define SEEK_SET 0
23: #endif
24:
1.1 anton 25: typedef union {
26: struct {
1.20 anton 27: #ifdef WORDS_BIGENDIAN
1.1 anton 28: Cell high;
29: Cell low;
30: #else
31: Cell low;
32: Cell high;
33: #endif;
34: } cells;
35: DCell dcell;
36: } Double_Store;
37:
38: typedef struct F83Name {
39: struct F83Name *next; /* the link field for old hands */
40: char countetc;
41: Char name[0];
42: } F83Name;
43:
44: /* are macros for setting necessary? */
45: #define F83NAME_COUNT(np) ((np)->countetc & 0x1f)
46: #define F83NAME_SMUDGE(np) (((np)->countetc & 0x40) != 0)
47: #define F83NAME_IMMEDIATE(np) (((np)->countetc & 0x20) != 0)
48:
1.23 ! anton 49: /* !!someone should organize this ifdef chaos */
! 50: #if defined(LONG_LATENCY)
! 51: #if defined(AUTO_INCREMENT)
! 52: #define NEXT_P0 (cfa=*ip++)
! 53: #define IP (ip-1)
! 54: #else /* AUTO_INCREMENT */
! 55: #define NEXT_P0 (cfa=*ip)
! 56: #define IP ip
! 57: #endif /* AUTO_INCREMENT */
! 58: #define NEXT_INST (cfa)
! 59: #define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
! 60: #else /* LONG_LATENCY */
1.14 anton 61: /* NEXT and NEXT1 are split into several parts to help scheduling,
62: unless CISC_NEXT is defined */
1.23 ! anton 63: #define NEXT_P0
! 64: /* in order for execute to work correctly, NEXT_P0 (or other early
! 65: fetches) should not update the ip (or should we put
! 66: compensation-code into execute? */
! 67: #define NEXT_INST (*ip)
! 68: /* the next instruction (or what is in its place, e.g., an immediate
! 69: argument */
! 70: #define INC_IP(const_inc) (ip+=(const_inc))
! 71: /* increment the ip by const_inc and perform NEXT_P0 (or prefetching) again */
! 72: #define IP ip
! 73: /* the pointer to the next instruction (i.e., NEXT_INST could be
! 74: defined as *IP) */
! 75: #endif /* LONG_LATENCY */
! 76:
! 77: #if defined(CISC_NEXT) && !defined(LONG_LATENCY)
1.14 anton 78: #define NEXT1_P1
79: #define NEXT_P1
80: #define DEF_CA
1.1 anton 81: #ifdef DIRECT_THREADED
1.14 anton 82: #define NEXT1_P2 ({goto *cfa;})
1.1 anton 83: #else
1.14 anton 84: #define NEXT1_P2 ({goto **cfa;})
85: #endif /* DIRECT_THREADED */
86: #define NEXT_P2 ({cfa = *ip++; NEXT1_P2;})
1.23 ! anton 87: #else /* defined(CISC_NEXT) && !defined(LONG_LATENCY) */
1.14 anton 88: #ifdef DIRECT_THREADED
89: #define NEXT1_P1
90: #define NEXT1_P2 ({goto *cfa;})
91: #define DEF_CA
92: #else /* DIRECT_THREADED */
93: #define NEXT1_P1 ({ca = *cfa;})
94: #define NEXT1_P2 ({goto *ca;})
95: #define DEF_CA Label ca;
96: #endif /* DIRECT_THREADED */
1.23 ! anton 97: #if defined(LONG_LATENCY)
! 98: #if defined(AUTO_INCREMENT)
! 99: #define NEXT_P1 NEXT1_P1
! 100: #else /* AUTO_INCREMENT */
! 101: #define NEXT_P1 ({ip++; NEXT1_P1;})
! 102: #endif /* AUTO_INCREMENT */
! 103: #else /* LONG_LATENCY */
1.14 anton 104: #define NEXT_P1 ({cfa=*ip++; NEXT1_P1;})
1.23 ! anton 105: #endif /* LONG_LATENCY */
1.14 anton 106: #define NEXT_P2 NEXT1_P2
1.23 ! anton 107: #endif /* defined(CISC_NEXT) && !defined(LONG_LATENCY) */
1.1 anton 108:
1.14 anton 109: #define NEXT1 ({DEF_CA NEXT1_P1; NEXT1_P2;})
110: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
1.1 anton 111:
112: #ifdef USE_TOS
113: #define IF_TOS(x) x
114: #else
115: #define IF_TOS(x)
116: #define TOS (sp[0])
117: #endif
118:
119: #ifdef USE_FTOS
120: #define IF_FTOS(x) x
121: #else
122: #define IF_FTOS(x)
123: #define FTOS (fp[0])
124: #endif
125:
126: int emitcounter;
127: #define NULLC '\0'
128:
1.14 anton 129: char *cstr(Char *from, UCell size, int clear)
130: /* if clear is true, scratch can be reused, otherwise we want more of
131: the same */
132: {
133: static char *scratch=NULL;
134: static unsigned scratchsize=0;
135: static char *nextscratch;
136: char *oldnextscratch;
137:
138: if (clear)
139: nextscratch=scratch;
140: if (scratch==NULL) {
141: scratch=malloc(size+1);
142: nextscratch=scratch;
143: scratchsize=size;
144: }
145: else if (nextscratch+size>scratch+scratchsize) {
146: char *oldscratch=scratch;
147: scratch = realloc(scratch, (nextscratch-scratch)+size+1);
148: nextscratch=scratch+(nextscratch-oldscratch);
149: scratchsize=size;
150: }
151: memcpy(nextscratch,from,size);
152: nextscratch[size]='\0';
153: oldnextscratch = nextscratch;
154: nextscratch += size+1;
155: return oldnextscratch;
156: }
1.13 pazsan 157:
1.1 anton 158: #define NEWLINE '\n'
159:
1.21 pazsan 160: #ifndef HAVE_RINT
161: #define rint(x) floor((x)+0.5)
162: #endif
1.13 pazsan 163:
1.1 anton 164: static char* fileattr[6]={"r","rb","r+","r+b","w+","w+b"};
1.6 pazsan 165:
1.11 pazsan 166: static Address up0=NULL;
167:
1.15 anton 168: /* if machine.h has not defined explicit registers, define them as implicit */
169: #ifndef IPREG
170: #define IPREG
171: #endif
172: #ifndef SPREG
173: #define SPREG
174: #endif
175: #ifndef RPREG
176: #define RPREG
177: #endif
178: #ifndef FPREG
179: #define FPREG
180: #endif
181: #ifndef LPREG
182: #define LPREG
183: #endif
184: #ifndef CFAREG
185: #define CFAREG
186: #endif
187: #ifndef UPREG
188: #define UPREG
189: #endif
190: #ifndef TOSREG
191: #define TOSREG
192: #endif
193: #ifndef FTOSREG
194: #define FTOSREG
195: #endif
1.13 pazsan 196:
1.15 anton 197: Label *engine(Xt *ip0, Cell *sp0, Cell *rp0, Float *fp0, Address lp0)
1.1 anton 198: /* executes code at ip, if ip!=NULL
199: returns array of machine code labels (for use in a loader), if ip==NULL
200: */
1.15 anton 201: {
202: register Xt *ip IPREG = ip0;
203: register Cell *sp SPREG = sp0;
204: register Cell *rp RPREG = rp0;
205: register Float *fp FPREG = fp0;
206: register Address lp LPREG = lp0;
207: register Xt cfa CFAREG;
208: register Address up UPREG = up0;
209: IF_TOS(register Cell TOS TOSREG;)
210: IF_FTOS(register Float FTOS FTOSREG;)
1.1 anton 211: static Label symbols[]= {
212: &&docol,
213: &&docon,
214: &&dovar,
1.4 pazsan 215: &&douser,
1.12 anton 216: &&dodefer,
1.1 anton 217: &&dodoes,
1.6 pazsan 218: &&dodoes, /* dummy for does handler address */
1.1 anton 219: #include "prim_labels.i"
220: };
221: #ifdef CPU_DEP
222: CPU_DEP;
223: #endif
224:
1.16 pazsan 225: #ifdef DEBUG
226: fprintf(stderr,"ip=%x, sp=%x, rp=%x, fp=%x, lp=%x, up=%x\n",
1.19 anton 227: (unsigned)ip,(unsigned)sp,(unsigned)rp,
228: (unsigned)fp,(unsigned)lp,(unsigned)up);
1.16 pazsan 229: #endif
230:
1.1 anton 231: if (ip == NULL)
232: return symbols;
1.10 anton 233:
1.1 anton 234: IF_TOS(TOS = sp[0]);
235: IF_FTOS(FTOS = fp[0]);
236: prep_terminal();
1.23 ! anton 237: NEXT_P0;
1.1 anton 238: NEXT;
239:
240: docol:
241: #ifdef DEBUG
1.16 pazsan 242: fprintf(stderr,"%08x: col: %08x\n",(Cell)ip,(Cell)PFA1(cfa));
1.1 anton 243: #endif
1.15 anton 244: #ifdef CISC_NEXT
1.1 anton 245: /* this is the simple version */
246: *--rp = (Cell)ip;
247: ip = (Xt *)PFA1(cfa);
1.23 ! anton 248: NEXT_P0;
1.1 anton 249: NEXT;
1.15 anton 250: #else
1.1 anton 251: /* this one is important, so we help the compiler optimizing
252: The following version may be better (for scheduling), but probably has
253: problems with code fields employing calls and delay slots
254: */
255: {
1.4 pazsan 256: DEF_CA
1.1 anton 257: Xt *current_ip = (Xt *)PFA1(cfa);
258: cfa = *current_ip;
259: NEXT1_P1;
260: *--rp = (Cell)ip;
261: ip = current_ip+1;
1.3 pazsan 262: NEXT1_P2;
1.1 anton 263: }
1.15 anton 264: #endif
1.23 ! anton 265:
1.1 anton 266: docon:
267: #ifdef DEBUG
1.16 pazsan 268: fprintf(stderr,"%08x: con: %08x\n",(Cell)ip,*(Cell*)PFA1(cfa));
1.1 anton 269: #endif
270: #ifdef USE_TOS
271: *sp-- = TOS;
272: TOS = *(Cell *)PFA1(cfa);
273: #else
274: *--sp = *(Cell *)PFA1(cfa);
275: #endif
1.23 ! anton 276: NEXT_P0;
1.1 anton 277: NEXT;
278:
279: dovar:
280: #ifdef DEBUG
1.16 pazsan 281: fprintf(stderr,"%08x: var: %08x\n",(Cell)ip,(Cell)PFA1(cfa));
1.1 anton 282: #endif
283: #ifdef USE_TOS
284: *sp-- = TOS;
285: TOS = (Cell)PFA1(cfa);
286: #else
287: *--sp = (Cell)PFA1(cfa);
288: #endif
1.23 ! anton 289: NEXT_P0;
1.1 anton 290: NEXT;
291:
1.4 pazsan 292: douser:
293: #ifdef DEBUG
1.16 pazsan 294: fprintf(stderr,"%08x: user: %08x\n",(Cell)ip,(Cell)PFA1(cfa));
1.4 pazsan 295: #endif
296: #ifdef USE_TOS
297: *sp-- = TOS;
1.5 anton 298: TOS = (Cell)(up+*(Cell*)PFA1(cfa));
1.4 pazsan 299: #else
1.5 anton 300: *--sp = (Cell)(up+*(Cell*)PFA1(cfa));
1.4 pazsan 301: #endif
1.23 ! anton 302: NEXT_P0;
1.4 pazsan 303: NEXT;
304:
1.12 anton 305: dodefer:
306: #ifdef DEBUG
1.16 pazsan 307: fprintf(stderr,"%08x: defer: %08x\n",(Cell)ip,(Cell)PFA1(cfa));
1.12 anton 308: #endif
309: cfa = *(Xt *)PFA1(cfa);
310: NEXT1;
311:
1.1 anton 312: dodoes:
313: /* this assumes the following structure:
314: defining-word:
315:
316: ...
317: DOES>
318: (possible padding)
319: possibly handler: jmp dodoes
320: (possible branch delay slot(s))
321: Forth code after DOES>
322:
323: defined word:
324:
325: cfa: address of or jump to handler OR
326: address of or jump to dodoes, address of DOES-code
327: pfa:
328:
329: */
330: #ifdef DEBUG
1.17 anton 331: fprintf(stderr,"%08x/%08x: does: %08x\n",(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));
1.16 pazsan 332: fflush(stderr);
1.1 anton 333: #endif
334: *--rp = (Cell)ip;
335: /* PFA1 might collide with DOES_CODE1 here, so we use PFA */
1.13 pazsan 336: ip = DOES_CODE1(cfa);
1.1 anton 337: #ifdef USE_TOS
338: *sp-- = TOS;
339: TOS = (Cell)PFA(cfa);
340: #else
341: *--sp = (Cell)PFA(cfa);
342: #endif
1.23 ! anton 343: NEXT_P0;
1.1 anton 344: NEXT;
1.16 pazsan 345:
1.1 anton 346: #include "primitives.i"
347: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>