--- gforth/engine/engine.c 2001/12/24 14:09:08 1.34 +++ gforth/engine/engine.c 2007/12/31 18:40:25 1.105 @@ -1,12 +1,12 @@ /* Gforth virtual machine (aka inner interpreter) - Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc. + Copyright (C) 1995,1996,1997,1998,2000,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of Gforth. Gforth is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,10 +15,15 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + along with this program; if not, see http://www.gnu.org/licenses/. */ +#if defined(GFORTH_DEBUGGING) || defined(INDIRECT_THREADED) || defined(DOUBLY_INDIRECT) || defined(VM_PROFILING) +#define USE_NO_TOS +#else +#define USE_TOS +#endif + #include "config.h" #include "forth.h" #include @@ -39,6 +44,7 @@ #include #include #include +#include #include #ifdef HAVE_FNMATCH_H #include @@ -46,7 +52,7 @@ #include "fnmatch.h" #endif #else -#include "systypes.h" +/* #include */ #endif #if defined(HAVE_LIBDL) || defined(HAVE_DLOPEN) /* what else? */ @@ -59,37 +65,28 @@ #include #endif +#ifdef HAS_FFCALL +#include +#include +#endif + +#ifdef HAS_LIBFFI +#include +#endif + #ifndef SEEK_SET /* should be defined in stdio.h, but some systems don't have it */ #define SEEK_SET 0 #endif -#define IOR(flag) ((flag)? -512-errno : 0) +#ifndef HAVE_FSEEKO +#define fseeko fseek +#endif -struct F83Name { - struct F83Name *next; /* the link field for old hands */ - char countetc; - char name[0]; -}; - -#define F83NAME_COUNT(np) ((np)->countetc & 0x1f) - -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)) - -Cell *SP; -Float *FP; -Address UP=NULL; - -#if 0 -/* not used currently */ -int emitcounter; +#ifndef HAVE_FTELLO +#define ftello ftell #endif + #define NULLC '\0' #ifdef MEMCMP_AS_SUBROUTINE @@ -97,155 +94,63 @@ 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.lo0; i--) fprintf(stderr, " $%lx",sp[i]); fprintf(stderr, " $%lx\n",spTOS); } +#else +# define NAME(string) asmcomment(string); #endif -Xt *primtable(Label symbols[], Cell size) +#ifdef DEBUG +#define CFA_TO_NAME(__cfa) \ + Cell len, i; \ + char * name = __cfa; \ + for(i=0; i<32; i+=sizeof(Cell)) { \ + len = ((Cell*)name)[-1]; \ + if(len < 0) { \ + len &= 0x1F; \ + if((len+sizeof(Cell)) > i) break; \ + } len = 0; \ + name -= sizeof(Cell); \ + } +#endif + +#ifdef STANDALONE +jmp_buf throw_jmp_buf; + +void throw(int code) { -#ifdef DIRECT_THREADED - return symbols; -#else /* !defined(DIRECT_THREADED) */ - Xt *xts = (Xt *)malloc(size*sizeof(Xt)); - Cell i; - - for (i=0; i=MAX_SYMBOLS) { - fprintf(stderr,"gforth-ditc: more than %d primitives\n",MAX_SYMBOLS); + fprintf(stderr,"gforth-ditc: more than %ld primitives\n",(long)MAX_SYMBOLS); exit(1); } - symbols[i] = &routines[i]; + xts[i] = symbols[i] = &routines[i]; } #endif /* defined(DOUBLY_INDIRECT) */ +#ifdef STANDALONE + return image; +#else return symbols; +#endif } - IF_spTOS(spTOS = sp[0]); +#if !(defined(GFORTH_DEBUGGING) || defined(INDIRECT_THREADED) || defined(DOUBLY_INDIRECT) || defined(VM_PROFILING)) + sp += STACK_CACHE_DEFAULT-1; + /* some of those registers are dead, but its simpler to initialize them all */ spTOS = sp[0]; + spb = sp[-1]; + spc = sp[-2]; + spd = sp[-3]; + spe = sp[-4]; + spf = sp[-5]; + spg = sp[-6]; + sph = sp[-7]; +#endif + IF_fpTOS(fpTOS = fp[0]); /* prep_terminal(); */ +#ifdef NO_IP + goto *(*(Label *)ip0); + before_goto: + goto *real_ca; + after_goto:; +#else SET_IP(ip); SUPER_END; /* count the first block, too */ - NEXT; - + FIRST_NEXT; +#endif #ifdef CPU_DEP3 CPU_DEP3 #endif - - docol: - { - DOCFA; -#ifdef DEBUG - fprintf(stderr,"%08lx: col: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); -#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 */ - { - DEF_CA - rp[-1] = (Cell)ip; - SET_IP((Xt *)PFA1(cfa)); - SUPER_END; - NEXT_P1; - rp--; - NEXT_P2; - } -#endif - } - docon: - { - DOCFA; -#ifdef DEBUG - fprintf(stderr,"%08lx: con: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa)); -#endif -#ifdef USE_TOS - *sp-- = spTOS; - spTOS = *(Cell *)PFA1(cfa); -#else - *--sp = *(Cell *)PFA1(cfa); -#endif - } - NEXT_P0; - NEXT; - - dovar: - { - DOCFA; -#ifdef DEBUG - fprintf(stderr,"%08lx: var: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); -#endif -#ifdef USE_TOS - *sp-- = spTOS; - spTOS = (Cell)PFA1(cfa); -#else - *--sp = (Cell)PFA1(cfa); -#endif - } - NEXT_P0; - NEXT; - - douser: - { - DOCFA; -#ifdef DEBUG - fprintf(stderr,"%08lx: user: %08lx\n",(Cell)ip,(Cell)PFA1(cfa)); -#endif -#ifdef USE_TOS - *sp-- = spTOS; - spTOS = (Cell)(up+*(Cell*)PFA1(cfa)); -#else - *--sp = (Cell)(up+*(Cell*)PFA1(cfa)); -#endif - } - NEXT_P0; - NEXT; - - 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 - spTOS += *(Cell*)PFA1(cfa); - } - NEXT_P0; - NEXT; - - dodoes: - /* this assumes the following structure: - defining-word: - - ... - DOES> - (possible padding) - possibly handler: jmp dodoes - (possible branch delay slot(s)) - Forth code after DOES> - - defined word: - - cfa: address of or jump to handler OR - address of or jump to dodoes, address of DOES-code - pfa: - - */ - { - 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)); - fflush(stderr); -#endif - *--rp = (Cell)ip; - /* PFA1 might collide with DOES_CODE1 here, so we use PFA */ -#ifdef USE_TOS - *sp-- = spTOS; - spTOS = (Cell)PFA(cfa); -#else - *--sp = (Cell)PFA(cfa); -#endif - SET_IP(DOES_CODE1(cfa)); - SUPER_END; - /* fprintf(stderr,"TOS = %08lx, IP=%08lx\n", spTOS, IP);*/ - } - NEXT; - -#ifndef IN_ENGINE2 -#define LABEL(name) I_##name -#else -#define LABEL(name) J_##name: asm(".skip 16"); I_##name -#endif -#include "prim.i" -#undef LABEL +#include PRIM_I after_last: return (Label *)0; /*needed only to get the length of the last primitive */ -}' -) - -Label *engine enginerest - -#define IN_ENGINE2 -Label *engine2 enginerest + return (Label *)0; +}