File:  [gforth] / gforth / vmgen-ex / engine.c
Revision 1.16: download - view: text, annotated - select for diffs
Mon Dec 31 19:02:25 2007 UTC (11 years, 10 months ago) by anton
Branches: MAIN
CVS tags: v0-7-0, HEAD
updated copyright year after changing license notice

    1: /* vm interpreter wrapper
    2: 
    3:   Copyright (C) 2001,2002,2003,2007 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 3
   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, see http://www.gnu.org/licenses/.
   19: */
   20: 
   21: #include "mini.h"
   22: 
   23: #define USE_spTOS 1
   24: 
   25: #ifdef USE_spTOS
   26: #define IF_spTOS(x) x
   27: #else
   28: #define IF_spTOS(x)
   29: #endif
   30: 
   31: #ifdef VM_DEBUG
   32: #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%p: %-20s, ", ip-1, _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
   33: #else
   34: #define NAME(_x)
   35: #endif
   36: 
   37: /* different threading schemes for different architectures; the sparse
   38:    numbering is there for historical reasons */
   39: 
   40: /* here you select the threading scheme; I have only set this up for
   41:    386 and generic, because I don't know what preprocessor macros to
   42:    test for (Gforth uses config.guess instead).  Anyway, it's probably
   43:    best to build them all and select the fastest instead of hardwiring
   44:    a specific scheme for an architecture.  E.g., scheme 8 is fastest
   45:    for Gforth "make bench" on a 486, whereas scheme 5 is fastest for
   46:    "mini fib.mini" on an Athlon */
   47: #ifndef THREADING_SCHEME
   48: #define THREADING_SCHEME 5
   49: #endif /* defined(THREADING_SCHEME) */
   50: 
   51: #ifdef __GNUC__
   52: #if THREADING_SCHEME==1
   53: /* direct threading scheme 1: autoinc, long latency (HPPA, Sharc) */
   54: #  define NEXT_P0	({cfa=*ip++;})
   55: #  define IP		(ip-1)
   56: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   57: #  define NEXT_INST	(cfa)
   58: #  define INC_IP(const_inc)	({cfa=IP[const_inc]; ip+=(const_inc);})
   59: #  define DEF_CA
   60: #  define NEXT_P1
   61: #  define NEXT_P2	({goto *cfa;})
   62: #endif
   63: 
   64: #if THREADING_SCHEME==3
   65: /* direct threading scheme 3: autoinc, low latency (68K) */
   66: #  define NEXT_P0
   67: #  define IP		(ip)
   68: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   69: #  define NEXT_INST	(*ip)
   70: #  define INC_IP(const_inc)	({ip+=(const_inc);})
   71: #  define DEF_CA
   72: #  define NEXT_P1	({cfa=*ip++;})
   73: #  define NEXT_P2	({goto *cfa;})
   74: #endif
   75: 
   76: #if THREADING_SCHEME==5
   77: /* direct threading scheme 5: early fetching (Alpha, MIPS) */
   78: #  define CFA_NEXT
   79: #  define NEXT_P0	({cfa=*ip;})
   80: #  define IP		(ip)
   81: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   82: #  define NEXT_INST	(cfa)
   83: #  define INC_IP(const_inc)	({cfa=ip[const_inc]; ip+=(const_inc);})
   84: #  define DEF_CA
   85: #  define NEXT_P1	(ip++)
   86: #  define NEXT_P2	({goto *cfa;})
   87: #endif
   88: 
   89: #if THREADING_SCHEME==8
   90: /* direct threading scheme 8: i386 hack */
   91: #  define NEXT_P0
   92: #  define IP		(ip)
   93: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
   94: #  define NEXT_INST	(*IP)
   95: #  define INC_IP(const_inc)	({ ip+=(const_inc);})
   96: #  define DEF_CA
   97: #  define NEXT_P1	(ip++)
   98: #  define NEXT_P2	({goto **(ip-1);})
   99: #endif
  100: 
  101: #if THREADING_SCHEME==9
  102: /* direct threading scheme 9: prefetching (for PowerPC) */
  103: /* note that the "cfa=next_cfa;" occurs only in NEXT_P1, because this
  104:    works out better with the capabilities of gcc to introduce and
  105:    schedule the mtctr instruction. */
  106: #  define NEXT_P0
  107: #  define IP		ip
  108: #  define SET_IP(p)	({ip=(p); next_cfa=*ip; NEXT_P0;})
  109: #  define NEXT_INST	(next_cfa)
  110: #  define INC_IP(const_inc)	({next_cfa=IP[const_inc]; ip+=(const_inc);})
  111: #  define DEF_CA	
  112: #  define NEXT_P1	({cfa=next_cfa; ip++; next_cfa=*ip;})
  113: #  define NEXT_P2	({goto *cfa;})
  114: #  define MORE_VARS	Inst next_cfa;
  115: #endif
  116: 
  117: #if THREADING_SCHEME==10
  118: /* direct threading scheme 10: plain (no attempt at scheduling) */
  119: #  define NEXT_P0
  120: #  define IP		(ip)
  121: #  define SET_IP(p)	({ip=(p); NEXT_P0;})
  122: #  define NEXT_INST	(*ip)
  123: #  define INC_IP(const_inc)	({ip+=(const_inc);})
  124: #  define DEF_CA
  125: #  define NEXT_P1
  126: #  define NEXT_P2	({cfa=*ip++; goto *cfa;})
  127: #endif
  128: 
  129: 
  130: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
  131: #define IPTOS NEXT_INST
  132: 
  133: #define INST_ADDR(name) (Label)&&I_##name
  134: #define LABEL(name) I_##name:
  135: #else /* !defined(__GNUC__) */
  136: /* use switch dispatch */
  137: #define DEF_CA
  138: #define NEXT_P0
  139: #define NEXT_P1
  140: #define NEXT_P2 goto next_inst;
  141: #define SET_IP(p)	(ip=(p))
  142: #define IP              ip
  143: #define NEXT_INST	(*ip)
  144: #define INC_IP(const_inc)	(ip+=(const_inc))
  145: #define IPTOS NEXT_INST
  146: #define INST_ADDR(name) I_##name
  147: #define LABEL(name) case I_##name:
  148: 
  149: #endif /* !defined(__GNUC__) */
  150: 
  151: #define LABEL2(x)
  152: 
  153: #ifdef VM_PROFILING
  154: #define SUPER_END  vm_count_block(IP)
  155: #else
  156: #define SUPER_END
  157: #endif
  158: 
  159: #ifndef __GNUC__
  160: enum {
  161: #include "mini-labels.i"
  162: };
  163: #endif
  164: 
  165: #if defined(__GNUC__) && ((__GNUC__==2 && defined(__GNUC_MINOR__) && __GNUC_MINOR__>=7)||(__GNUC__>2))
  166: #define MAYBE_UNUSED __attribute__((unused))
  167: #else
  168: #define MAYBE_UNUSED
  169: #endif
  170: 
  171: /* the return type can be anything you want it to */
  172: Cell engine(Inst *ip0, Cell *sp, char *fp)
  173: {
  174:   /* VM registers (you may want to use gcc's "Explicit Reg Vars" here) */
  175:   Inst * ip;
  176:   Inst * cfa;
  177: #ifdef USE_spTOS
  178:   Cell   spTOS;
  179: #else
  180: #define spTOS (sp[0])
  181: #endif
  182:   static Label labels[] = {
  183: #include "mini-labels.i"
  184:   };
  185: #ifdef MORE_VARS
  186:   MORE_VARS
  187: #endif
  188: 
  189:   if (vm_debug)
  190:       fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp);
  191:   if (ip0 == NULL) {
  192:     vm_prim = labels;
  193:     return 0;
  194:   }
  195: 
  196:   /* I don't have a clue where these things come from,
  197:      but I've put them in macros.h for the moment */
  198:   IF_spTOS(spTOS = sp[0]);
  199: 
  200:   SET_IP(ip0);
  201:   SUPER_END;  /* count the BB starting at ip0 */
  202: 
  203: #ifdef __GNUC__
  204:   NEXT;
  205: #include "mini-vm.i"
  206: #else  
  207:  next_inst:
  208:   switch(*ip++) {
  209: #include "mini-vm.i"
  210:   default:
  211:     fprintf(stderr,"unknown instruction %d at %p\n", ip[-1], ip-1);
  212:     exit(1);
  213:   }
  214: #endif
  215: }

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