--- gforth/vmgen-ex2/engine.c 2002/06/02 15:46:17 1.1 +++ gforth/vmgen-ex2/engine.c 2007/12/31 19:02:25 1.10 @@ -1,12 +1,12 @@ /* vm interpreter wrapper - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001,2002,2003,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,14 +15,11 @@ 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/. */ #include "mini.h" -#define vm_Cell2Cell(_x,_y) ((_y)=(_x)) - #define USE_spTOS 1 #ifdef USE_spTOS @@ -42,17 +39,16 @@ /* here you select the threading scheme; I have only set this up for 386 and generic, because I don't know what preprocessor macros to - test for (Gforth uses config.guess instead). - Anyway, it's probably best to build them all and select the fastest - instead of hardwiring a specific scheme for an architecture. */ + test for (Gforth uses config.guess instead). Anyway, it's probably + best to build them all and select the fastest instead of hardwiring + a specific scheme for an architecture. E.g., scheme 8 is fastest + for Gforth "make bench" on a 486, whereas scheme 5 is fastest for + "mini fib.mini" on an Athlon */ #ifndef THREADING_SCHEME -#ifdef i386 -#define THREADING_SCHEME 8 -#else #define THREADING_SCHEME 5 -#endif #endif /* defined(THREADING_SCHEME) */ +#ifdef __GNUC__ #if THREADING_SCHEME==1 /* direct threading scheme 1: autoinc, long latency (HPPA, Sharc) */ # define NEXT_P0 ({cfa=*ip++;}) @@ -62,7 +58,7 @@ # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) # define DEF_CA # define NEXT_P1 -# define NEXT_P2 ({goto *cfa;}) +# define NEXT_P2 ({goto *(cfa.inst);}) #endif #if THREADING_SCHEME==3 @@ -74,20 +70,20 @@ # define INC_IP(const_inc) ({ip+=(const_inc);}) # define DEF_CA # define NEXT_P1 ({cfa=*ip++;}) -# define NEXT_P2 ({goto *cfa;}) +# define NEXT_P2 ({goto *(cfa.inst);}) #endif #if THREADING_SCHEME==5 /* direct threading scheme 5: early fetching (Alpha, MIPS) */ # define CFA_NEXT # define NEXT_P0 ({cfa=*ip;}) -# define IP ((Cell *)ip) +# define IP (ip) # define SET_IP(p) ({ip=(Inst *)(p); NEXT_P0;}) -# define NEXT_INST ((Cell)cfa) +# define NEXT_INST (cfa) # define INC_IP(const_inc) ({cfa=ip[const_inc]; ip+=(const_inc);}) # define DEF_CA # define NEXT_P1 (ip++) -# define NEXT_P2 ({goto *cfa;}) +# define NEXT_P2 ({goto *(cfa.inst);}) #endif #if THREADING_SCHEME==8 @@ -114,8 +110,8 @@ # define INC_IP(const_inc) ({next_cfa=IP[const_inc]; ip+=(const_inc);}) # define DEF_CA # define NEXT_P1 ({cfa=next_cfa; ip++; next_cfa=*ip;}) -# define NEXT_P2 ({goto *cfa;}) -# define MORE_VARS Inst next_cfa; +# define NEXT_P2 ({goto *(cfa.inst);}) +# define MORE_VARS Cell next_cfa; #endif #if THREADING_SCHEME==10 @@ -127,13 +123,32 @@ # define INC_IP(const_inc) ({ip+=(const_inc);}) # define DEF_CA # define NEXT_P1 -# define NEXT_P2 ({cfa=*ip++; goto *cfa;}) +# define NEXT_P2 ({cfa=*ip++; goto *(cfa.inst);}) #endif #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;}) -#define IPTOS ((Cell)(NEXT_INST)) -#define CASE +#define IPTOS ((NEXT_INST)) + +#define INST_ADDR(name) (Label)&&I_##name +#define LABEL(name) I_##name: +#else /* !defined(__GNUC__) */ +/* use switch dispatch */ +#define DEF_CA +#define NEXT_P0 +#define NEXT_P1 +#define NEXT_P2 goto next_inst; +#define SET_IP(p) (ip=(p)) +#define IP ip +#define NEXT_INST (*ip) +#define INC_IP(const_inc) (ip+=(const_inc)) +#define IPTOS NEXT_INST +#define INST_ADDR(name) I_##name +#define LABEL(name) case I_##name: + +#endif /* !defined(__GNUC__) */ + +#define LABEL2(x) #ifdef VM_PROFILING #define SUPER_END vm_count_block(IP) @@ -141,15 +156,24 @@ #define SUPER_END #endif -#define INST_ADDR(name) (Label)&&I_##name -#define LABEL(name) I_##name +#ifndef __GNUC__ +enum { +#include "mini-labels.i" +}; +#endif + +#if defined(__GNUC__) && ((__GNUC__==2 && defined(__GNUC_MINOR__) && __GNUC_MINOR__>=7)||(__GNUC__>2)) +#define MAYBE_UNUSED __attribute__((unused)) +#else +#define MAYBE_UNUSED +#endif /* the return type can be anything you want it to */ long engine(Cell *ip0, Cell *sp, char *fp) { /* VM registers (you may want to use gcc's "Explicit Reg Vars" here) */ Cell * ip; - Cell * cfa; + Cell cfa; #ifdef USE_spTOS Cell spTOS; #else @@ -175,7 +199,17 @@ long engine(Cell *ip0, Cell *sp, char *f SET_IP(ip0); SUPER_END; /* count the BB starting at ip0 */ - NEXT; +#ifdef __GNUC__ + NEXT; +#include "mini-vm.i" +#else + next_inst: + switch((*ip++).inst) { #include "mini-vm.i" + default: + fprintf(stderr,"unknown instruction %d at %p\n", ip[-1], ip-1); + exit(1); + } +#endif }