--- gforth/engine/engine.c 2000/09/23 15:47:07 1.23 +++ gforth/engine/engine.c 2002/12/23 22:14:06 1.52 @@ -20,6 +20,7 @@ */ #include "config.h" +#include "forth.h" #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include "forth.h" #include "io.h" #include "threaded.h" #ifndef STANDALONE @@ -72,19 +72,16 @@ struct F83Name { char name[0]; }; -/* are macros for setting necessary? */ #define F83NAME_COUNT(np) ((np)->countetc & 0x1f) -#define F83NAME_SMUDGE(np) (((np)->countetc & 0x40) != 0) -#define F83NAME_IMMEDIATE(np) (((np)->countetc & 0x20) != 0) -Cell *SP; -Float *FP; -Address UP=NULL; - -#if 0 -/* not used currently */ -int emitcounter; -#endif +struct Longname { + struct Longname *next; /* the link field for old hands */ + Cell countetc; + char name[0]; +}; + +#define LONGNAME_COUNT(np) ((np)->countetc & (((~((UCell)0))<<3)>>3)) + #define NULLC '\0' #ifdef MEMCMP_AS_SUBROUTINE @@ -92,117 +89,48 @@ extern int gforth_memcmp(const char * s1 #define memcmp(s1,s2,n) gforth_memcmp(s1,s2,n) #endif -#ifdef HAS_FILE -char *cstr(Char *from, UCell size, int clear) -/* return a C-string corresponding to the Forth string ( FROM SIZE ). - the C-string lives until the next call of cstr with CLEAR being true */ -{ - static struct cstr_buffer { - char *buffer; - size_t size; - } *buffers=NULL; - static int nbuffers=0; - static int used=0; - struct cstr_buffer *b; - - if (buffers==NULL) - buffers=malloc(0); - if (clear) - used=0; - if (used>=nbuffers) { - buffers=realloc(buffers,sizeof(struct cstr_buffer)*(used+1)); - buffers[used]=(struct cstr_buffer){malloc(0),0}; - nbuffers=used+1; - } - b=&buffers[used]; - if (size+1 > b->size) { - b->buffer = realloc(b->buffer,size+1); - b->size = size+1; - } - memcpy(b->buffer,from,size); - b->buffer[size]='\0'; - used++; - return b->buffer; -} - -char *tilde_cstr(Char *from, UCell size, int clear) -/* like cstr(), but perform tilde expansion on the string */ -{ - char *s1,*s2; - int s1_len, s2_len; - struct passwd *getpwnam (), *user_entry; - - if (size<1 || from[0]!='~') - return cstr(from, size, clear); - if (size<2 || from[1]=='/') { - s1 = (char *)getenv ("HOME"); - if(s1 == NULL) - s1 = ""; - s2 = from+1; - s2_len = size-1; - } else { - UCell i; - for (i=1; ipw_dir; - s2 = from+i; - s2_len = size-i; - } - s1_len = strlen(s1); - if (s1_len>1 && s1[s1_len-1]=='/') - s1_len--; - { - char path[s1_len+s2_len]; - memcpy(path,s1,s1_len); - memcpy(path+s1_len,s2,s2_len); - return cstr(path,s1_len+s2_len,clear); - } -} -#endif - -DCell timeval2us(struct timeval *tvp) -{ -#ifndef BUGGY_LONG_LONG - return (tvp->tv_sec*(DCell)1000000)+tvp->tv_usec; -#else - DCell d2; - DCell d1=mmul(tvp->tv_sec,1000000); - d2.lo = d1.lo+tvp->tv_usec; - d2.hi = d1.hi + (d2.lo i) break; \ + } len = 0; \ + name -= sizeof(Cell); \ + } #endif +#if !defined(ENGINE) +/* normal engine */ +#define VARIANT(v) (v) +#define JUMP(target) goto I_noop +#define LABEL(name) J_##name: asm(""); I_##name: + +#elif ENGINE==2 +/* variant with padding between VM instructions for finding out + cross-inst jumps (for dynamic code) */ +#define engine engine2 +#define VARIANT(v) (v) +#define JUMP(target) goto I_noop +#define LABEL(name) J_##name: SKIP16; I_##name: +#define IN_ENGINE2 + +#elif ENGINE==3 +/* variant with different immediate arguments for finding out + immediate arguments (for native code) */ +#define engine engine3 +#define VARIANT(v) ((v)^0xffffffff) +#define JUMP(target) goto K_lit +#define LABEL(name) J_##name: asm(""); I_##name: +#else +#error illegal ENGINE value +#endif /* ENGINE */ + +#define LABEL2(name) K_##name: + + Label *engine(Xt *ip0, Cell *sp0, Cell *rp0, Float *fp0, Address lp0) /* executes code at ip, if ip!=NULL returns array of machine code labels (for use in a loader), if ip==NULL */ { #ifndef GFORTH_DEBUGGING - register Xt *ip IPREG; register Cell *rp RPREG; #endif +#ifndef NO_IP + register Xt *ip IPREG = ip0; +#endif register Cell *sp SPREG = sp0; register Float *fp FPREG = fp0; register Address lp LPREG = lp0; -#ifdef CFA_NEXT register Xt cfa CFAREG; -#endif #ifdef MORE_VARS MORE_VARS #endif register Address up UPREG = UP; - IF_TOS(register Cell TOS TOSREG;) - IF_FTOS(register Float FTOS FTOSREG;) + IF_spTOS(register Cell spTOS TOSREG;) + IF_fpTOS(register Float fpTOS FTOSREG;) #if defined(DOUBLY_INDIRECT) static Label *symbols; static void *routines[]= { +#define MAX_SYMBOLS (sizeof(routines)/sizeof(routines[0])) #else /* !defined(DOUBLY_INDIRECT) */ static Label symbols[]= { +#define MAX_SYMBOLS (sizeof(symbols)/sizeof(symbols[0])) #endif /* !defined(DOUBLY_INDIRECT) */ (Label)&&docol, (Label)&&docon, @@ -289,50 +260,64 @@ Label *engine(Xt *ip0, Cell *sp0, Cell * (Label)&&dofield, (Label)&&dodoes, /* the following entry is normally unused; - it's there because its index indicates a does-handler */ + it is there because its index indicates a does-handler */ CPU_DEP1, +#define INST_ADDR(name) (Label)&&I_##name +#include "prim_lab.i" +#undef INST_ADDR + (Label)&&after_last, + (Label)0, +#define INST_ADDR(name) (Label)&&K_##name #include "prim_lab.i" - (Label)0 +#undef INST_ADDR +#define INST_ADDR(name) (Label)&&J_##name +#include "prim_lab.i" +#undef INST_ADDR }; #ifdef CPU_DEP2 CPU_DEP2 #endif - ip = ip0; rp = rp0; #ifdef DEBUG fprintf(stderr,"ip=%x, sp=%x, rp=%x, fp=%x, lp=%x, up=%x\n", - (unsigned)ip,(unsigned)sp,(unsigned)rp, + (unsigned)ip0,(unsigned)sp,(unsigned)rp, (unsigned)fp,(unsigned)lp,(unsigned)up); #endif - if (ip == NULL) { + if (ip0 == NULL) { #if defined(DOUBLY_INDIRECT) -#define MAX_SYMBOLS (sizeof(routines)/sizeof(routines[0])) -#define CODE_OFFSET (22*sizeof(Cell)) +#define CODE_OFFSET (26*sizeof(Cell)) +#define XT_OFFSET (22*sizeof(Cell)) int i; Cell code_offset = offset_image? CODE_OFFSET : 0; + Cell xt_offset = offset_image? XT_OFFSET : 0; symbols = (Label *)(malloc(MAX_SYMBOLS*sizeof(Cell)+CODE_OFFSET)+code_offset); + xts = (Label *)(malloc(MAX_SYMBOLS*sizeof(Cell)+XT_OFFSET)+xt_offset); for (i=0; i=MAX_SYMBOLS) { fprintf(stderr,"gforth-ditc: more than %d primitives\n",MAX_SYMBOLS); exit(1); } - symbols[i] = &routines[i]; + xts[i] = symbols[i] = &routines[i]; } #endif /* defined(DOUBLY_INDIRECT) */ return symbols; } - IF_TOS(TOS = sp[0]); - IF_FTOS(FTOS = fp[0]); + IF_spTOS(spTOS = sp[0]); + IF_fpTOS(fpTOS = fp[0]); /* prep_terminal(); */ +#ifdef NO_IP + goto *(*(Label *)ip0); +#else SET_IP(ip); + SUPER_END; /* count the first block, too */ NEXT; - +#endif #ifdef CPU_DEP3 CPU_DEP3 @@ -340,14 +325,22 @@ Label *engine(Xt *ip0, Cell *sp0, Cell * docol: { - DOCFA; +#ifdef NO_IP + *--rp = next_code; + goto **(Label *)PFA1(cfa); +#else #ifdef DEBUG - fprintf(stderr,"%08lx: col: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); + { + CFA_TO_NAME(cfa); + fprintf(stderr,"%08lx: col: %08lx %.*s\n",(Cell)ip,(Cell)PFA1(cfa), + len,name); + } #endif #ifdef CISC_NEXT /* this is the simple version */ *--rp = (Cell)ip; SET_IP((Xt *)PFA1(cfa)); + SUPER_END; NEXT; #else /* this one is important, so we help the compiler optimizing */ @@ -355,80 +348,94 @@ Label *engine(Xt *ip0, Cell *sp0, Cell * DEF_CA rp[-1] = (Cell)ip; SET_IP((Xt *)PFA1(cfa)); + SUPER_END; NEXT_P1; rp--; NEXT_P2; } #endif +#endif } docon: { - DOCFA; #ifdef DEBUG fprintf(stderr,"%08lx: con: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa)); #endif #ifdef USE_TOS - *sp-- = TOS; - TOS = *(Cell *)PFA1(cfa); + *sp-- = spTOS; + spTOS = *(Cell *)PFA1(cfa); #else *--sp = *(Cell *)PFA1(cfa); #endif } +#ifdef NO_IP + goto *next_code; +#else NEXT_P0; NEXT; +#endif dovar: { - DOCFA; #ifdef DEBUG fprintf(stderr,"%08lx: var: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); #endif #ifdef USE_TOS - *sp-- = TOS; - TOS = (Cell)PFA1(cfa); + *sp-- = spTOS; + spTOS = (Cell)PFA1(cfa); #else *--sp = (Cell)PFA1(cfa); #endif } +#ifdef NO_IP + goto *next_code; +#else NEXT_P0; NEXT; +#endif douser: { - DOCFA; #ifdef DEBUG fprintf(stderr,"%08lx: user: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); #endif #ifdef USE_TOS - *sp-- = TOS; - TOS = (Cell)(up+*(Cell*)PFA1(cfa)); + *sp-- = spTOS; + spTOS = (Cell)(up+*(Cell*)PFA1(cfa)); #else *--sp = (Cell)(up+*(Cell*)PFA1(cfa)); #endif } +#ifdef NO_IP + goto *next_code; +#else NEXT_P0; NEXT; +#endif dodefer: { - DOCFA; #ifdef DEBUG fprintf(stderr,"%08lx: defer: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa)); #endif + SUPER_END; EXEC(*(Xt *)PFA1(cfa)); } dofield: { - DOCFA; #ifdef DEBUG fprintf(stderr,"%08lx: field: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); #endif - TOS += *(Cell*)PFA1(cfa); + spTOS += *(Cell*)PFA1(cfa); } +#ifdef NO_IP + goto *next_code; +#else NEXT_P0; NEXT; +#endif dodoes: /* this assumes the following structure: @@ -448,9 +455,14 @@ Label *engine(Xt *ip0, Cell *sp0, Cell * pfa: */ +#ifdef NO_IP + *--rp = next_code; + IF_spTOS(spTOS = sp[0]); + sp--; + spTOS = (Cell)PFA(cfa); + goto **(Label *)DOES_CODE1(cfa); +#else { - DOCFA; - /* fprintf(stderr, "Got CFA %08lx at doescode %08lx/%08lx: does: %08lx\n",cfa,(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));*/ #ifdef DEBUG fprintf(stderr,"%08lx/%08lx: does: %08lx\n",(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa)); @@ -459,15 +471,19 @@ Label *engine(Xt *ip0, Cell *sp0, Cell * *--rp = (Cell)ip; /* PFA1 might collide with DOES_CODE1 here, so we use PFA */ #ifdef USE_TOS - *sp-- = TOS; - TOS = (Cell)PFA(cfa); + *sp-- = spTOS; + spTOS = (Cell)PFA(cfa); #else *--sp = (Cell)PFA(cfa); #endif SET_IP(DOES_CODE1(cfa)); - /* fprintf(stderr,"TOS = %08lx, IP=%08lx\n", TOS, IP);*/ + SUPER_END; + /* fprintf(stderr,"TOS = %08lx, IP=%08lx\n", spTOS, IP);*/ } NEXT; +#endif #include "prim.i" + after_last: return (Label *)0; + /*needed only to get the length of the last primitive */ }