Annotation of gforth/vmgen-ex/engine.c, revision 1.16

1.1       anton       1: /* vm interpreter wrapper
                      2: 
1.16    ! anton       3:   Copyright (C) 2001,2002,2003,2007 Free Software Foundation, Inc.
1.1       anton       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
1.15      anton       9:   as published by the Free Software Foundation, either version 3
1.1       anton      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
1.15      anton      18:   along with this program; if not, see http://www.gnu.org/licenses/.
1.1       anton      19: */
                     20: 
                     21: #include "mini.h"
                     22: 
1.2       anton      23: #define USE_spTOS 1
                     24: 
1.1       anton      25: #ifdef USE_spTOS
                     26: #define IF_spTOS(x) x
                     27: #else
                     28: #define IF_spTOS(x)
                     29: #endif
                     30: 
                     31: #ifdef VM_DEBUG
1.3       anton      32: #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%p: %-20s, ", ip-1, _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
1.1       anton      33: #else
                     34: #define NAME(_x)
                     35: #endif
                     36: 
1.2       anton      37: /* different threading schemes for different architectures; the sparse
                     38:    numbering is there for historical reasons */
1.1       anton      39: 
1.2       anton      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
1.11      anton      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 */
1.2       anton      47: #ifndef THREADING_SCHEME
1.1       anton      48: #define THREADING_SCHEME 5
1.2       anton      49: #endif /* defined(THREADING_SCHEME) */
                     50: 
1.6       anton      51: #ifdef __GNUC__
1.2       anton      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
1.1       anton      75: 
                     76: #if THREADING_SCHEME==5
1.2       anton      77: /* direct threading scheme 5: early fetching (Alpha, MIPS) */
1.1       anton      78: #  define CFA_NEXT
                     79: #  define NEXT_P0      ({cfa=*ip;})
1.11      anton      80: #  define IP           (ip)
                     81: #  define SET_IP(p)    ({ip=(p); NEXT_P0;})
                     82: #  define NEXT_INST    (cfa)
1.1       anton      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: 
1.2       anton     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: 
1.1       anton     130: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
                    131: #define IPTOS NEXT_INST
                    132: 
1.6       anton     133: #define INST_ADDR(name) (Label)&&I_##name
1.10      anton     134: #define LABEL(name) I_##name:
1.6       anton     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
1.10      anton     147: #define LABEL(name) case I_##name:
1.6       anton     148: 
                    149: #endif /* !defined(__GNUC__) */
1.10      anton     150: 
                    151: #define LABEL2(x)
1.6       anton     152: 
1.1       anton     153: #ifdef VM_PROFILING
                    154: #define SUPER_END  vm_count_block(IP)
                    155: #else
                    156: #define SUPER_END
                    157: #endif
1.5       anton     158: 
1.6       anton     159: #ifndef __GNUC__
                    160: enum {
                    161: #include "mini-labels.i"
                    162: };
                    163: #endif
1.1       anton     164: 
1.13      anton     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: 
1.1       anton     171: /* the return type can be anything you want it to */
                    172: Cell engine(Inst *ip0, Cell *sp, char *fp)
                    173: {
1.2       anton     174:   /* VM registers (you may want to use gcc's "Explicit Reg Vars" here) */
1.1       anton     175:   Inst * ip;
                    176:   Inst * cfa;
                    177: #ifdef USE_spTOS
                    178:   Cell   spTOS;
                    179: #else
                    180: #define spTOS (sp[0])
                    181: #endif
1.9       anton     182:   static Label labels[] = {
1.1       anton     183: #include "mini-labels.i"
                    184:   };
1.2       anton     185: #ifdef MORE_VARS
                    186:   MORE_VARS
                    187: #endif
1.1       anton     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);
1.3       anton     201:   SUPER_END;  /* count the BB starting at ip0 */
1.6       anton     202: 
                    203: #ifdef __GNUC__
1.1       anton     204:   NEXT;
                    205: #include "mini-vm.i"
1.6       anton     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
1.1       anton     215: }

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