Diff for /gforth/Attic/engine.c between versions 1.29 and 1.41

version 1.29, 1995/10/07 17:38:12 version 1.41, 1997/03/04 17:49:48
Line 1 Line 1
 /*  /* Gforth virtual machine (aka inner interpreter)
   Copyright 1992 by the ANSI figForth Development Group  
     Copyright (C) 1995 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
     of the License, or (at your option) any later version.
   
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */  */
   
   #include "config.h"
 #include <ctype.h>  #include <ctype.h>
 #include <stdio.h>  #include <stdio.h>
 #include <string.h>  #include <string.h>
Line 18 Line 36
 #include <pwd.h>  #include <pwd.h>
 #include "forth.h"  #include "forth.h"
 #include "io.h"  #include "io.h"
   #include "threading.h"
   
 #ifndef SEEK_SET  #ifndef SEEK_SET
 /* should be defined in stdio.h, but some systems don't have it */  /* should be defined in stdio.h, but some systems don't have it */
Line 26 Line 45
   
 #define IOR(flag)       ((flag)? -512-errno : 0)  #define IOR(flag)       ((flag)? -512-errno : 0)
   
 typedef union {  
   struct {  
 #ifdef WORDS_BIGENDIAN  
     Cell high;  
     Cell low;  
 #else  
     Cell low;  
     Cell high;  
 #endif;  
   } cells;  
   DCell dcell;  
 } Double_Store;  
   
 typedef struct F83Name {  typedef struct F83Name {
   struct F83Name        *next;  /* the link field for old hands */    struct F83Name        *next;  /* the link field for old hands */
   char                  countetc;    char                  countetc;
Line 50  typedef struct F83Name { Line 56  typedef struct F83Name {
 #define F83NAME_SMUDGE(np)      (((np)->countetc & 0x40) != 0)  #define F83NAME_SMUDGE(np)      (((np)->countetc & 0x40) != 0)
 #define F83NAME_IMMEDIATE(np)   (((np)->countetc & 0x20) != 0)  #define F83NAME_IMMEDIATE(np)   (((np)->countetc & 0x20) != 0)
   
 /* !!someone should organize this ifdef chaos */  
 #if defined(LONG_LATENCY)  
 #if defined(AUTO_INCREMENT)  
 #define NEXT_P0         (cfa=*ip++)  
 #define IP              (ip-1)  
 #else /* AUTO_INCREMENT */  
 #define NEXT_P0         (cfa=*ip)  
 #define IP              ip  
 #endif /* AUTO_INCREMENT */  
 #define NEXT_INST       (cfa)  
 #define INC_IP(const_inc)       ({cfa=IP[const_inc]; ip+=(const_inc);})  
 #else /* LONG_LATENCY */  
 /* NEXT and NEXT1 are split into several parts to help scheduling,  
    unless CISC_NEXT is defined */  
 #define NEXT_P0  
 /* in order for execute to work correctly, NEXT_P0 (or other early  
    fetches) should not update the ip (or should we put  
    compensation-code into execute? */  
 #define NEXT_INST       (*ip)  
 /* the next instruction (or what is in its place, e.g., an immediate  
    argument */  
 #define INC_IP(const_inc)       (ip+=(const_inc))  
 /* increment the ip by const_inc and perform NEXT_P0 (or prefetching) again */  
 #define IP              ip  
 /* the pointer to the next instruction (i.e., NEXT_INST could be  
    defined as *IP) */  
 #endif /* LONG_LATENCY */  
   
 #if defined(CISC_NEXT) && !defined(LONG_LATENCY)  
 #define NEXT1_P1  
 #define NEXT_P1  
 #define DEF_CA  
 #ifdef DIRECT_THREADED  
 #define NEXT1_P2 ({goto *cfa;})  
 #else  
 #define NEXT1_P2 ({goto **cfa;})  
 #endif /* DIRECT_THREADED */  
 #define NEXT_P2 ({cfa = *ip++; NEXT1_P2;})  
 #else /* defined(CISC_NEXT) && !defined(LONG_LATENCY) */  
 #ifdef DIRECT_THREADED  
 #define NEXT1_P1  
 #define NEXT1_P2 ({goto *cfa;})  
 #define DEF_CA  
 #else /* DIRECT_THREADED */  
 #define NEXT1_P1 ({ca = *cfa;})  
 #define NEXT1_P2 ({goto *ca;})  
 #define DEF_CA  Label ca;  
 #endif /* DIRECT_THREADED */  
 #if defined(LONG_LATENCY)  
 #if defined(AUTO_INCREMENT)  
 #define NEXT_P1 NEXT1_P1  
 #else /* AUTO_INCREMENT */  
 #define NEXT_P1 ({ip++; NEXT1_P1;})  
 #endif /* AUTO_INCREMENT */  
 #else /* LONG_LATENCY */  
 #define NEXT_P1 ({cfa=*ip++; NEXT1_P1;})  
 #endif /* LONG_LATENCY */  
 #define NEXT_P2 NEXT1_P2  
 #endif /* defined(CISC_NEXT) && !defined(LONG_LATENCY) */  
   
 #define NEXT1 ({DEF_CA NEXT1_P1; NEXT1_P2;})  
 #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})  
   
 #ifdef USE_TOS  
 #define IF_TOS(x) x  
 #else  
 #define IF_TOS(x)  
 #define TOS (sp[0])  
 #endif  
   
 #ifdef USE_FTOS  
 #define IF_FTOS(x) x  
 #else  
 #define IF_FTOS(x)  
 #define FTOS (fp[0])  
 #endif  
   
 Cell *SP;  Cell *SP;
 Float *FP;  Float *FP;
   Address UP=NULL;
   
   #if 0
   /* not used currently */
 int emitcounter;  int emitcounter;
   #endif
 #define NULLC '\0'  #define NULLC '\0'
   
 char *cstr(Char *from, UCell size, int clear)  char *cstr(Char *from, UCell size, int clear)
 /* if clear is true, scratch can be reused, otherwise we want more of  /* return a C-string corresponding to the Forth string ( FROM SIZE ).
    the same */     the C-string lives until the next call of cstr with CLEAR being true */
 {  {
   static char *scratch=NULL;    static struct cstr_buffer {
   static unsigned scratchsize=0;      char *buffer;
   static char *nextscratch;      size_t size;
   char *oldnextscratch;    } *buffers=NULL;
     static int nbuffers=0;
     static int used=0;
     struct cstr_buffer *b;
   
     if (buffers==NULL)
       buffers=malloc(0);
   if (clear)    if (clear)
     nextscratch=scratch;      used=0;
   if (scratch==NULL) {    if (used>=nbuffers) {
     scratch=malloc(size+1);      buffers=realloc(buffers,sizeof(struct cstr_buffer)*(used+1));
     nextscratch=scratch;      buffers[used]=(struct cstr_buffer){malloc(0),0};
     scratchsize=size;      nbuffers=used+1;
   }    }
   else if (nextscratch+size>scratch+scratchsize) {    b=&buffers[used];
     char *oldscratch=scratch;    if (size+1 > b->size) {
     scratch = realloc(scratch, (nextscratch-scratch)+size+1);      b->buffer = realloc(b->buffer,size+1);
     nextscratch=scratch+(nextscratch-oldscratch);      b->size = size+1;
     scratchsize=size;    }
   }    memcpy(b->buffer,from,size);
   memcpy(nextscratch,from,size);    b->buffer[size]='\0';
   nextscratch[size]='\0';    used++;
   oldnextscratch = nextscratch;    return b->buffer;
   nextscratch += size+1;  
   return oldnextscratch;  
 }  }
   
 char *tilde_cstr(Char *from, UCell size, int clear)  char *tilde_cstr(Char *from, UCell size, int clear)
Line 172  char *tilde_cstr(Char *from, UCell size, Line 109  char *tilde_cstr(Char *from, UCell size,
     return cstr(from, size, clear);      return cstr(from, size, clear);
   if (size<2 || from[1]=='/') {    if (size<2 || from[1]=='/') {
     s1 = (char *)getenv ("HOME");      s1 = (char *)getenv ("HOME");
       if(s1 == NULL)
         s1 = "";
     s2 = from+1;      s2 = from+1;
     s2_len = size-1;      s2_len = size-1;
   } else {    } else {
     int i;      UCell i;
     for (i=1; i<size && from[i]!='/'; i++)      for (i=1; i<size && from[i]!='/'; i++)
       ;        ;
     {      {
Line 210  char *tilde_cstr(Char *from, UCell size, Line 149  char *tilde_cstr(Char *from, UCell size,
   
 static char* fileattr[6]={"r","rb","r+","r+b","w","wb"};  static char* fileattr[6]={"r","rb","r+","r+b","w","wb"};
   
 static Address up0=NULL;  #ifndef O_BINARY
   #define O_BINARY 0
   #endif
   #ifndef O_TEXT
   #define O_TEXT 0
   #endif
   
   static int ufileattr[6]= {
     O_RDONLY|O_TEXT, O_RDONLY|O_BINARY,
     O_RDWR  |O_TEXT, O_RDWR  |O_BINARY,
     O_WRONLY|O_TEXT, O_WRONLY|O_BINARY };
   
 /* if machine.h has not defined explicit registers, define them as implicit */  /* if machine.h has not defined explicit registers, define them as implicit */
 #ifndef IPREG  #ifndef IPREG
Line 241  static Address up0=NULL; Line 190  static Address up0=NULL;
 #define FTOSREG  #define FTOSREG
 #endif  #endif
   
   #ifndef CPU_DEP1
   # define CPU_DEP1 0
   #endif
   
   /* declare and compute cfa for certain threading variants */
   /* warning: this is nonsyntactical; it will not work in place of a statement */
   #ifdef CFA_NEXT
   #define DOCFA
   #else
   #define DOCFA   Xt cfa; GETCFA(cfa)
   #endif
   
 Label *engine(Xt *ip0, Cell *sp0, Cell *rp0, Float *fp0, Address lp0)  Label *engine(Xt *ip0, Cell *sp0, Cell *rp0, Float *fp0, Address lp0)
 /* executes code at ip, if ip!=NULL  /* executes code at ip, if ip!=NULL
    returns array of machine code labels (for use in a loader), if ip==NULL     returns array of machine code labels (for use in a loader), if ip==NULL
Line 251  Label *engine(Xt *ip0, Cell *sp0, Cell * Line 212  Label *engine(Xt *ip0, Cell *sp0, Cell *
   register Cell *rp RPREG = rp0;    register Cell *rp RPREG = rp0;
   register Float *fp FPREG = fp0;    register Float *fp FPREG = fp0;
   register Address lp LPREG = lp0;    register Address lp LPREG = lp0;
   #ifdef CFA_NEXT
   register Xt cfa CFAREG;    register Xt cfa CFAREG;
   register Address up UPREG = up0;  #endif
     register Address up UPREG = UP;
   IF_TOS(register Cell TOS TOSREG;)    IF_TOS(register Cell TOS TOSREG;)
   IF_FTOS(register Float FTOS FTOSREG;)    IF_FTOS(register Float FTOS FTOSREG;)
   #if defined(DOUBLY_INDIRECT)
     static Label *symbols;
     static void *routines[]= {
   #else /* !defined(DOUBLY_INDIRECT) */
   static Label symbols[]= {    static Label symbols[]= {
   #endif /* !defined(DOUBLY_INDIRECT) */
     &&docol,      &&docol,
     &&docon,      &&docon,
     &&dovar,      &&dovar,
Line 263  Label *engine(Xt *ip0, Cell *sp0, Cell * Line 231  Label *engine(Xt *ip0, Cell *sp0, Cell *
     &&dodefer,      &&dodefer,
     &&dofield,      &&dofield,
     &&dodoes,      &&dodoes,
     &&dodoes,  /* dummy for does handler address */      /* the following entry is normally unused;
          it's there because its index indicates a does-handler */
       CPU_DEP1,
 #include "prim_labels.i"  #include "prim_labels.i"
       0
   };    };
 #ifdef CPU_DEP  #ifdef CPU_DEP2
   CPU_DEP;    CPU_DEP2
 #endif  #endif
   
 #ifdef DEBUG  #ifdef DEBUG
Line 276  Label *engine(Xt *ip0, Cell *sp0, Cell * Line 247  Label *engine(Xt *ip0, Cell *sp0, Cell *
           (unsigned)fp,(unsigned)lp,(unsigned)up);            (unsigned)fp,(unsigned)lp,(unsigned)up);
 #endif  #endif
   
   if (ip == NULL)    if (ip == NULL) {
     return symbols;  #if defined(DOUBLY_INDIRECT)
   #define MAX_SYMBOLS 1000
       int i;
       Cell code_offset = offset_image? 11*sizeof(Cell) : 0;
   
       symbols = (Label *)(malloc(MAX_SYMBOLS*sizeof(Cell)+code_offset)+code_offset);
       for (i=0; i<DOESJUMP+1; i++)
         symbols[i] = (Label)routines[i];
       for (; routines[i]!=0; i++) {
         if (i>=MAX_SYMBOLS) {
           fprintf(stderr,"gforth-ditc: more than %d primitives\n",MAX_SYMBOLS);
           exit(1);
       }
       symbols[i] = &routines[i];
     }
   #endif /* defined(DOUBLY_INDIRECT) */
     return symbols;
   }
   
   IF_TOS(TOS = sp[0]);    IF_TOS(TOS = sp[0]);
   IF_FTOS(FTOS = fp[0]);    IF_FTOS(FTOS = fp[0]);
 /*  prep_terminal(); */  /*  prep_terminal(); */
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
   
   #ifdef CPU_DEP3
     CPU_DEP3
   #endif
       
  docol:   docol:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: col: %08x\n",(Cell)ip,(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: col: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
 #ifdef CISC_NEXT  #ifdef CISC_NEXT
   /* this is the simple version */      /* this is the simple version */
   *--rp = (Cell)ip;  
   ip = (Xt *)PFA1(cfa);  
   NEXT_P0;  
   NEXT;  
 #else  
   /* this one is important, so we help the compiler optimizing  
      The following version may be better (for scheduling), but probably has  
      problems with code fields employing calls and delay slots  
   */  
   {  
     DEF_CA  
     Xt *current_ip = (Xt *)PFA1(cfa);  
     cfa = *current_ip;  
     NEXT1_P1;  
     *--rp = (Cell)ip;      *--rp = (Cell)ip;
     ip = current_ip+1;      ip = (Xt *)PFA1(cfa);
     NEXT1_P2;      NEXT_P0;
   }      NEXT;
   #else
       /* this one is important, so we help the compiler optimizing
          The following version may be better (for scheduling), but probably has
          problems with code fields employing calls and delay slots
          */
       {
         DEF_CA
         Xt *current_ip = (Xt *)PFA1(cfa);
         cfa = *current_ip;
         NEXT1_P1;
         *--rp = (Cell)ip;
         ip = current_ip+1;
         NEXT1_P2;
       }
 #endif  #endif
     }
   
  docon:   docon:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: con: %08x\n",(Cell)ip,*(Cell*)PFA1(cfa));      fprintf(stderr,"%08lx: con: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa));
 #endif  #endif
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = *(Cell *)PFA1(cfa);      TOS = *(Cell *)PFA1(cfa);
 #else  #else
   *--sp = *(Cell *)PFA1(cfa);      *--sp = *(Cell *)PFA1(cfa);
 #endif  #endif
     }
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
       
  dovar:   dovar:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: var: %08x\n",(Cell)ip,(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: var: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = (Cell)PFA1(cfa);      TOS = (Cell)PFA1(cfa);
 #else  #else
   *--sp = (Cell)PFA1(cfa);      *--sp = (Cell)PFA1(cfa);
 #endif  #endif
     }
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
       
  douser:   douser:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: user: %08x\n",(Cell)ip,(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: user: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = (Cell)(up+*(Cell*)PFA1(cfa));      TOS = (Cell)(up+*(Cell*)PFA1(cfa));
 #else  #else
   *--sp = (Cell)(up+*(Cell*)PFA1(cfa));      *--sp = (Cell)(up+*(Cell*)PFA1(cfa));
 #endif  #endif
     }
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
       
  dodefer:   dodefer:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: defer: %08x\n",(Cell)ip,(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: defer: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa));
 #endif  #endif
   cfa = *(Xt *)PFA1(cfa);      EXEC(*(Xt *)PFA1(cfa));
   NEXT1;    }
   
  dofield:   dofield:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   fprintf(stderr,"%08x: field: %08x\n",(Cell)ip,(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: field: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
   TOS += *(Cell*)PFA1(cfa);       TOS += *(Cell*)PFA1(cfa); 
     }
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
   
Line 383  Label *engine(Xt *ip0, Cell *sp0, Cell * Line 392  Label *engine(Xt *ip0, Cell *sp0, Cell *
      pfa:       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  #ifdef DEBUG
   fprintf(stderr,"%08x/%08x: does: %08x\n",(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));      fprintf(stderr,"%08lx/%08lx: does: %08lx\n",(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));
   fflush(stderr);      fflush(stderr);
 #endif  #endif
   *--rp = (Cell)ip;      *--rp = (Cell)ip;
   /* PFA1 might collide with DOES_CODE1 here, so we use PFA */      /* PFA1 might collide with DOES_CODE1 here, so we use PFA */
   ip = DOES_CODE1(cfa);      ip = DOES_CODE1(cfa);
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = (Cell)PFA(cfa);      TOS = (Cell)PFA(cfa);
 #else  #else
   *--sp = (Cell)PFA(cfa);      *--sp = (Cell)PFA(cfa);
 #endif  #endif
       /*    fprintf(stderr,"TOS = %08lx, IP=%08lx\n", TOS, IP);*/
     }
   NEXT_P0;    NEXT_P0;
   NEXT;    NEXT;
   

Removed from v.1.29  
changed lines
  Added in v.1.41


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>