File:  [gforth] / gforth / vmgen-ex2 / engine.c
Revision 1.2: download - view: text, annotated - select for diffs
Sun Jun 2 17:02:56 2002 UTC (21 years, 10 months ago) by anton
Branches: MAIN
CVS tags: HEAD
vmgen* now works with lcc and "gcc -O3 -ansi --pedantic -U__GNUC__"

    1: /* vm interpreter wrapper
    2: 
    3:   Copyright (C) 2001 Free Software Foundation, Inc.
    4: 
    5:   This file is part of Gforth.
    6: 
    7:   Gforth is free software; you can redistribute it and/or
    8:   modify it under the terms of the GNU General Public License
    9:   as published by the Free Software Foundation; either version 2
   10:   of the License, or (at your option) any later version.
   11: 
   12:   This program is distributed in the hope that it will be useful,
   13:   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15:   GNU General Public License for more details.
   16: 
   17:   You should have received a copy of the GNU General Public License
   18:   along with this program; if not, write to the Free Software
   19:   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   20: */
   21: 
   22: #include "mini.h"
   23: 
   24: #define vm_Cell2Cell(_x,_y) ((_y)=(_x))
   25: 
   26: #define USE_spTOS 1
   27: 
   28: #ifdef USE_spTOS
   29: #define IF_spTOS(x) x
   30: #else
   31: #define IF_spTOS(x)
   32: #endif
   33: 
   34: #ifdef VM_DEBUG
   35: #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%p: %-20s, ", ip-1, _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
   36: #else
   37: #define NAME(_x)
   38: #endif
   39: 
   40: /* different threading schemes for different architectures; the sparse
   41:    numbering is there for historical reasons */
   42: 
   43: /* here you select the threading scheme; I have only set this up for
   44:    386 and generic, because I don't know what preprocessor macros to
   45:    test for (Gforth uses config.guess instead).
   46:    Anyway, it's probably best to build them all and select the fastest
   47:    instead of hardwiring a specific scheme for an architecture. */
   48: #ifndef THREADING_SCHEME
   49: #ifdef i386
   50: #define THREADING_SCHEME 8
   51: #else
   52: #define THREADING_SCHEME 5
   53: #endif
   54: #endif /* defined(THREADING_SCHEME) */
   55: 
   56: #ifdef __GNUC__
   57: #if THREADING_SCHEME==1
   58: /* direct threading scheme 1: autoinc, long latency (HPPA, Sharc) */
   59: #  define NEXT_P0	({cfa=*ip++;})
   60: #  define IP		(ip-1)
   61: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   62: #  define NEXT_INST	(cfa)
   63: #  define INC_IP(const_inc)	({cfa=IP[const_inc]; ip+=(const_inc);})
   64: #  define DEF_CA
   65: #  define NEXT_P1
   66: #  define NEXT_P2	({goto *cfa;})
   67: #endif
   68: 
   69: #if THREADING_SCHEME==3
   70: /* direct threading scheme 3: autoinc, low latency (68K) */
   71: #  define NEXT_P0
   72: #  define IP		(ip)
   73: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   74: #  define NEXT_INST	(*ip)
   75: #  define INC_IP(const_inc)	({ip+=(const_inc);})
   76: #  define DEF_CA
   77: #  define NEXT_P1	({cfa=*ip++;})
   78: #  define NEXT_P2	({goto *cfa;})
   79: #endif
   80: 
   81: #if THREADING_SCHEME==5
   82: /* direct threading scheme 5: early fetching (Alpha, MIPS) */
   83: #  define CFA_NEXT
   84: #  define NEXT_P0	({cfa=*ip;})
   85: #  define IP		((Cell *)ip)
   86: #  define SET_IP(p)	({ip=(Inst *)(p); NEXT_P0;})
   87: #  define NEXT_INST	((Cell)cfa)
   88: #  define INC_IP(const_inc)	({cfa=ip[const_inc]; ip+=(const_inc);})
   89: #  define DEF_CA
   90: #  define NEXT_P1	(ip++)
   91: #  define NEXT_P2	({goto *cfa;})
   92: #endif
   93: 
   94: #if THREADING_SCHEME==8
   95: /* direct threading scheme 8: i386 hack */
   96: #  define NEXT_P0
   97: #  define IP		(ip)
   98: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   99: #  define NEXT_INST	(*IP)
  100: #  define INC_IP(const_inc)	({ ip+=(const_inc);})
  101: #  define DEF_CA
  102: #  define NEXT_P1	(ip++)
  103: #  define NEXT_P2	({goto *((*(ip-1)).inst);})
  104: #endif
  105: 
  106: #if THREADING_SCHEME==9
  107: /* direct threading scheme 9: prefetching (for PowerPC) */
  108: /* note that the "cfa=next_cfa;" occurs only in NEXT_P1, because this
  109:    works out better with the capabilities of gcc to introduce and
  110:    schedule the mtctr instruction. */
  111: #  define NEXT_P0
  112: #  define IP		ip
  113: #  define SET_IP(p)	({ip=(p); next_cfa=*ip; NEXT_P0;})
  114: #  define NEXT_INST	(next_cfa)
  115: #  define INC_IP(const_inc)	({next_cfa=IP[const_inc]; ip+=(const_inc);})
  116: #  define DEF_CA	
  117: #  define NEXT_P1	({cfa=next_cfa; ip++; next_cfa=*ip;})
  118: #  define NEXT_P2	({goto *cfa;})
  119: #  define MORE_VARS	Inst next_cfa;
  120: #endif
  121: 
  122: #if THREADING_SCHEME==10
  123: /* direct threading scheme 10: plain (no attempt at scheduling) */
  124: #  define NEXT_P0
  125: #  define IP		(ip)
  126: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
  127: #  define NEXT_INST	(*ip)
  128: #  define INC_IP(const_inc)	({ip+=(const_inc);})
  129: #  define DEF_CA
  130: #  define NEXT_P1
  131: #  define NEXT_P2	({cfa=*ip++; goto *cfa;})
  132: #endif
  133: 
  134: 
  135: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
  136: #define IPTOS ((Cell)(NEXT_INST))
  137: #define CASE
  138: 
  139: #define INST_ADDR(name) (Label)&&I_##name
  140: #define LABEL(name) I_##name
  141: #else /* !defined(__GNUC__) */
  142: /* use switch dispatch */
  143: #define DEF_CA
  144: #define NEXT_P0
  145: #define NEXT_P1
  146: #define NEXT_P2 goto next_inst;
  147: #define SET_IP(p)	(ip=(p))
  148: #define IP              ip
  149: #define NEXT_INST	(*ip)
  150: #define INC_IP(const_inc)	(ip+=(const_inc))
  151: #define IPTOS NEXT_INST
  152: #define INST_ADDR(name) I_##name
  153: #define LABEL(name) case I_##name
  154: 
  155: #endif /* !defined(__GNUC__) */
  156: 
  157: #ifdef VM_PROFILING
  158: #define SUPER_END  vm_count_block(IP)
  159: #else
  160: #define SUPER_END
  161: #endif
  162: 
  163: #ifndef __GNUC__
  164: enum {
  165: #include "mini-labels.i"
  166: };
  167: #endif
  168: 
  169: /* the return type can be anything you want it to */
  170: long engine(Cell *ip0, Cell *sp, char *fp)
  171: {
  172:   /* VM registers (you may want to use gcc's "Explicit Reg Vars" here) */
  173:   Cell * ip;
  174:   Cell * cfa;
  175: #ifdef USE_spTOS
  176:   Cell   spTOS;
  177: #else
  178: #define spTOS (sp[0])
  179: #endif
  180:   static Label   labels[] = {
  181: #include "mini-labels.i"
  182:   };
  183: #ifdef MORE_VARS
  184:   MORE_VARS
  185: #endif
  186: 
  187:   if (vm_debug)
  188:       fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp);
  189:   if (ip0 == NULL) {
  190:     vm_prim = labels;
  191:     return 0;
  192:   }
  193: 
  194:   /* I don't have a clue where these things come from,
  195:      but I've put them in macros.h for the moment */
  196:   IF_spTOS(spTOS = sp[0]);
  197: 
  198:   SET_IP(ip0);
  199:   SUPER_END;  /* count the BB starting at ip0 */
  200: 
  201: #ifdef __GNUC__
  202:   NEXT;
  203: #include "mini-vm.i"
  204: #else  
  205:  next_inst:
  206:   switch((*ip++).inst) {
  207: #include "mini-vm.i"
  208:   default:
  209:     fprintf(stderr,"unknown instruction %d at %p\n", ip[-1], ip-1);
  210:     exit(1);
  211:   }
  212: #endif
  213: }

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