/*
** This is a 32 bit CINTCODE interpreter written in C
** with modifications for the Cintpos system.
**
** (c) Copyright:  Martin Richards  October 2010
**
** Modified 3 Sep 2018
**
** If FASTyes if defined, most of the debugging aids are
** disabled making it functionally equivalent to the
** handwritten assembly code versions provided for some
** architectures.
**
** The fast version defines the function cintasm
** while the slow version defines interpret.

** 17/5/02
** Added an option to check when indirect memory references are out
** of range. Note - only indirect not direct updates.
*/

//09/04/10

//Put time the time stamp (days, msecs) in the rootnode approx every msec.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

/* cintpos.h contains machine/system dependent #defines  */
#include "cintpos.h"

#ifndef FASTyes

#define TRACINGyes
#define TALLYyes
#define WATCHyes
#define MEMCHKyes
#define COUNTyes

#endif

#ifdef MEMCHKyes
#define MC1(a) if((UBCPLWORD)a>memupb){W[3]=a; res=12; pc--;  goto ret; }
#define MC2(a) if((UBCPLWORD)a>memupb){W[3]=a; res=12; pc-=2; goto ret; }
#define MC3(a) if((UBCPLWORD)a>memupb){W[3]=a; res=12; pc-=3; goto ret; }
#define MC5(a) if((UBCPLWORD)a>memupb){W[3]=a; res=12; pc-=5; goto ret; }
#else
#define MC1(a)
#define MC2(a)
#define MC3(a)
#define MC5(a)
#endif

#define msecsperday (24*60*60*1000)

// Declared in devices.c
extern BCPLWORD irqfifov[];         /* A fifo of interrupting devid's */
extern BCPLWORD irqfifop, irqfifoq; /* circular queue from p to q-1   */

// Declared in cintpos.c
extern BCPLWORD icount;
extern BCPLWORD kcount;

extern BCPLWORD result2;

extern BCPLWORD *lastWp;    /* Latest setting of Wp */
extern BCPLWORD *lastWg;    /* Latest setting of Wg */
extern BCPLWORD  lastst;    // Latest setting of st

extern pthread_mutex_t irq_mutex;
extern pthread_cond_t irq_cv;

extern int tracing;
extern BCPLWORD memupb;
UBCPLWORD memupbb;

extern BCPLWORD *tallyv;
extern BCPLWORD tallylim;

#ifdef TALLYyes
UBCPLWORD tallylimb;
#endif

extern BCPLWORD dosys(BCPLWORD p, BCPLWORD g);
extern BCPLWORD doflt(BCPLWORD op, BCPLWORD a, BCPLWORD b, BCPLWORD c);
extern BCPLWORD muldiv(BCPLWORD a, BCPLWORD b, BCPLWORD c);

extern void wrcode(char *form, BCPLWORD f, BCPLWORD a); 
extern void wrfcode(BCPLWORD f);
extern void trace(BCPLWORD pc, BCPLWORD p, BCPLWORD a, BCPLWORD b);
extern BCPLWORD timestamp(BCPLWORD *datstamp);

//extern BCPLWORD joyscan(BCPLWORD fd, BCPLWORD *g, BCPLWORD *W);


#define Gn_currco      7
#define Gn_result2    10

/* CINTCODE function codes  */

#define F_0       0

#define F_fltop   1
#define F_brk     2
#define F_k0      0
#define F_lf     12
#define F_lm     14
#define F_lm1    15
#define F_l0     16
#define F_fhop   27
#define F_jeq    28

#define F_k      32
#define F_kh     33
#define F_kw     34
#define F_k0g    32
#define F_k0g1   (F_k0g+32)
#define F_k0gh   (F_k0g+64)
#define F_s0g    44
#define F_s0g1   (F_s0g+32)
#define F_s0gh   (F_s0g+64)
#define F_l0g    45
#define F_l0g1   (F_l0g+32)
#define F_l0gh   (F_l0g+64)
#define F_l1g    46
#define F_l1g1   (F_l1g+32)
#define F_l1gh   (F_l1g+64)
#define F_l2g    47
#define F_l2g1   (F_l2g+32)
#define F_l2gh   (F_l2g+64)
#define F_lg     48
#define F_lg1    (F_lg+32)
#define F_lgh    (F_lg+64)
#define F_sg     49
#define F_sg1    (F_sg+32)
#define F_sgh    (F_sg+64)
#define F_llg    50
#define F_llg1   (F_llg+32)
#define F_llgh   (F_llg+64)
#define F_ag     51
#define F_ag1    (F_ag+32)
#define F_agh    (F_ag+64)
#define F_mul    52
#define F_div    53
#define F_rem    54
#define F_xor    55
#define F_sl     56
#define F_ll     58
#define F_jne    60

#define F_llp    64
#define F_llph   65
#define F_llpw   66
#define F_add    84
#define F_sub    85
#define F_lsh    86
#define F_rsh    87
#define F_and    88
#define F_or     89
#define F_lll    90
#define F_jls    92

#define F_l      96
#define F_lh     97
#define F_lw     98
#define F_rv    116
#define F_rtn   123
#define F_jgr   124

#define F_lp    128
#define F_lph   129
#define F_lpw   130
#define F_lp0   128
#define F_sys   145
#define F_swb   146
#define F_swl   147
#define F_st    148
#define F_st0   148
#define F_stp0  149
#define F_goto  155
#define F_jle   156

#define F_sp    160
#define F_sph   161
#define F_spw   162
#define F_sp0   160
#define F_s0    176
#define F_xch   181
#define F_gbyt  182
#define F_pbyt  183
#define F_atc   184
#define F_atb   185
#define F_j     186
#define F_jge   188

#define F_ap    192
#define F_aph   193
#define F_apw   194
#define F_ap0   192

#define F_xpbyt 205
#define F_lmh   206
#define F_btc   207
#define F_nop   208
#define F_a0    208
#define F_rvp0  211
#define F_st0p0 216
#define F_st1p0 218

#define F_mw    223

#define F_a     224
#define F_ah    225
#define F_aw    226
#define F_l0p0  224
#define F_s     237
#define F_sh    238

#define F_mdiv  239
#define F_chgco 240
#define F_neg   241
#define F_not   242
#define F_l1p0  240
#define F_l2p0  244
#define F_l3p0  247 
#define F_l4p0  249

#define F_selld 254
#define F_selst 255
#define F_255   255


/* The function interpret is designed to be separately compiled,
// and possibly implemented in assembly language.
//
// Unless either TRACINGyes or TALLYyes are defined, its only free
// variable is the function dosys(p, g).
//
// mem  is the pointer to the cintcode memory.
// regs is the position in the Cintcode memory where the initial
//      value of the Cintcode registers.
//
// interpret executes Cintcode instructions and returns with an
// integer result as follows:

//    -2      sys(Sys_dumpmem) cause a memory dump to DUMP.mem
//    -1 *    sys(Sys_setcount, val) called
//     0 *    sys(Sys_quit, 0) called
//     1      Non existent instruction
//     2      Brk instruction
//     3      Zero count
//     4      PC too large or negative
//     5      Division by zero
//    10      Cintasm single step trap
//    11      Contents of watch address has changed
//    12      Memory address too large or negative
//    13      SIGINT received
//    14      Unknown floating point operation
//    15
//    16      P pointer too large or negative
//     n      sys(Sys_quit, n) called
//
// On return the Cintcode registers are dumped back in the vector regs
*/

#ifdef FASTyes
extern BCPLWORD *watchaddr, watchval;
#else
BCPLWORD *watchaddr=0, watchval=0;
#endif

#ifdef FASTyes
extern BCPLWORD exitflag;          // Set by SIGINT or SIGSEGV
#else
BCPLWORD exitflag=0;               // Set by SIGINT or SIGSEGV
#endif

#ifdef FASTyes
int cintasm(BCPLWORD regs, BCPLWORD *mem)
#else
int interpret(BCPLWORD regs, BCPLWORD *mem)
#endif

{ register BCPLWORD *W = mem;

#define B (BP W)
#define SB (SBP W)
#define H (HP W)
#define SH (SHP W)

#ifdef BIGENDER
#define GH(x) ((WD B[x+0]<<8) | B[x+1])
#define GW(x) ((((((WD B[x]<<8)|B[x+1])<<8)|B[x+2])<<8)|B[x+3])
#else
#define GH(x) ((WD B[x+1]<<8) | B[x])
#define GW(x) ((((((WD B[x+3]<<8)|B[x+2])<<8)|B[x+1])<<8)|B[x])
#endif

   register BCPLWORD           a  = W[regs+0];
   register BCPLWORD           b  = W[regs+1];
   BCPLWORD                    c  = W[regs+2];
   BCPLWORD                    p  = W[regs+3]>>B2Wsh;
   BCPLWORD                    g  = W[regs+4]>>B2Wsh;
   BCPLWORD                    st = W[regs+5];
   register BCPLWORD           pc = W[regs+6];
   BCPLWORD                    count = W[regs+7];
   BCPLWORD                    mw = W[regs+8];

   register BCPLWORD *Wp  = W+p,    /* Optimise access to the stack */
                     *Wg  = W+g,    /* Optimise access to the global vector */
                     *Wg1 = W+g+256;

   BCPLWORD res, k, i;
   BCPLWORD clkirq=0;

   UBCPLWORD memupbb = memupb<<B2Wsh;

#ifdef TALLYyes
   UBCPLWORD tallylimb = tallylim<<B2Wsh;
#endif

   lastWp = Wp;
   lastWg = Wg;
   lastst = st;

   icount = 0;  // Check for device
   kcount = 0;  // and clock interrupts

   // printf("cinterp: entering interpret\n");
   //   tracing = 1;

fetchchk:
   // Check PC is in range
   if((UBCPLWORD)pc > memupbb) goto badpc;

fetch:

#ifdef WATCHyes
   /* Special watch debugging aid */
   if(watchaddr && *watchaddr!=watchval)
   { /*
       printf("%7lld: changed from %7lld(%8llx) to %7lld(%8llx)\n",
              LL watchaddr-W, LL watchval, LL (UBCPLWORD)watchval,
              *LL watchaddr, LL (UBCPLWORD)*watchaddr);
     */
     watchval = *watchaddr;
     W[1] = watchaddr-W;
     W[2] = watchval;
     res = 11;        /* Contents of watch address has changed */
     goto ret;
   }
   /* End of watch code */
#endif

   //   printf("%5d %5d\n", icount, kcount);
   if(--icount<=0) {
     icount = 1000; // reset icount, inspect intflag and check for interrupts
                    // ie once every 1000 Cintcode instructions.

     if(--kcount<=0) {
       BCPLWORD datv[3];   // -> [days, msecs, -1]
       BCPLWORD daysnow;   // Days since 1 Jan 1970
       BCPLWORD msecsnow;  // milli-seconds since midnight
       BCPLWORD clkq;
       kcount = 100;
       //printf("%5d %5d\n", icount, kcount);
       // Update the time roughly every 100,000 Cintcode instructions
       timestamp(datv);
       daysnow = datv[0];
       msecsnow = datv[1];

       //printf("cinterp: checking the time, daysnow=%d msecsnow=%d\n",
       //        daysnow, msecsnow);
       W[rootnode + Rtn_days]  = daysnow;
       W[rootnode + Rtn_msecs] = msecsnow;
       W[rootnode + Rtn_ticks] = -1;
       clkq = W[rootnode + Rtn_clwkq];
       //printf("Cinterp: rootnode=%d Rtn_clwkq=%d\n",
       //      rootnode, Rtn_clwkq, W[rootnode+Rtn_clwkq]);
       if (clkq) {
	 BCPLWORD pktdays  = W[clkq + Pkt_res1];
         BCPLWORD pktmsecs = W[clkq + Pkt_res2];
         if((msecsnow>=pktmsecs && daysnow==pktdays) ||
             daysnow>pktdays) clkirq = 1;
         //printf("Cinterp: clkq=%d daysnow=%d msecsnow=%d pktdays=%d pktmsecs=%d\n",
	 //	   clkq, daysnow, msecsnow, pktdays, pktmsecs);
         //printf("Cinterp: clkirq=%d\n", clkirq);
       }
     }

     //printf("Cinterp: locking irq_mutex to inspect the fifo\n");
     pthread_mutex_lock(&irq_mutex);

     if (W[rootnode+Rtn_intflag]) {
       // SIGINT has been received, so save the registers in bootregs
       // and return code 13
       W[rootnode+Rtn_intflag] = 0;
       printf("cinterp: SIGINT received\n");
       pthread_mutex_unlock(&irq_mutex);
       W[bootregs+0]  = a;
       W[bootregs+1]  = b;
       W[bootregs+2]  = c;
       W[bootregs+3]  = p<<B2Wsh;
       W[bootregs+4]  = g<<B2Wsh;
       W[bootregs+5]  = st;
       W[bootregs+6]  = pc;
       W[bootregs+7]  = count;
       res = 13;
       goto ret;
     }

     if (st==0) {
       // Interrupts are enabled and there is a request in the irq fifo

       // Extract the device id
       BCPLWORD devid = 0;

       if(clkirq) {
         devid = -1;
         clkirq = 0;
       } else {
         if(irqfifop!=irqfifoq) {
           devid = irqfifov[irqfifop++];
           irqfifop &= 1023;  // The fifo is a circular buffer of size 1024
         }
       }

       // devid is zero or holds the id of the interrupting device.

       pthread_mutex_unlock(&irq_mutex);
       //printf("cinterp: unlocks irq_mutex\n");

       // Check whether there really was an interrupt.
       if(devid==0) goto fetch;

       //printf("cinterp: Interrupt received from device %d\n", devid);

       // Save the Cintcode registers in saveregs
       W[saveregs+0]  = a;
       W[saveregs+1]  = b;
       W[saveregs+2]  = c;
       W[saveregs+3]  = p<<B2Wsh;
       W[saveregs+4]  = g<<B2Wsh;
       W[saveregs+5]  = st;
       W[saveregs+6]  = pc;
       W[saveregs+7]  = count;

       // Dispatch the interrupt service routine
       a      = devid;    // Put the device id in register a
       b      = 0;
       c      = 0;
       p      = W[isrregs+3]>>B2Wsh;
       g      = W[isrregs+4]>>B2Wsh;
       st     = 3;   // We are now entering the interrupt service routine.
       lastst = st;
       pc     = W[isrregs+6];
       //count = W[isrregs+7];  // Don't change count

       Wp  = W+p;
       Wg  = W+g;
       Wg1 = W+g+256;
       lastWp = Wp;
       lastWg = Wg;

       Wp[3] = a;    // Put a in P!3  (function calling convention)
                     // The first arg of irqrtn is the interrupting
                     // device number.

       //printf("cinterp: starting to execute the interrupt routine\n");
       if(pc>=0) goto fetch; // Start executing the interrupt service routine
       goto badpc;
     }

     pthread_mutex_unlock(&irq_mutex);
   }


   /* count>=0  means execute count instructions (slow interpreter)
      count=-1  means go on for ever (fast interpreter)
      count=-2  means single step the fast interpreter
   */
#ifdef COUNTyes
   if (count>=0)
   { if (count==0) { res = 3; goto ret; }
     count--;
   }
#endif

#ifdef TRACINGyes
   if (tracing) trace(pc, p, a, b);
#endif

#ifdef TALLYyes
   if ((UBCPLWORD)pc < tallylimb) tallyv[pc]++;
#endif

   if( (UBCPLWORD)p > memupbb) { res = 16; goto ret; }

switch(B[pc++])
{  default:
   case F_0:     /* Cases F_0 and F_255 have been added explicitly to   */
     //case F_255:   /* improve the compiled code (with luck)               */
                 res = 1; pc--; goto ret; /* Unimplemented instruction  */

     // Added 21/7/10
   case F_fltop:
     { BCPLWORD op = B[pc++];

#ifdef NOFLOAT
       a = 0;
       goto fetch;
#else
       //printf("fltop op=%lld\n", LL op);
       switch (op) {
       default:
         W[1] = op;
         res = 14; goto ret;

       case fl_avail:
         a = -1; goto fetch;

       case fl_mk:
       { BCPLWORD exponent = B[pc++]; // Signed byte
	 // The senior bit represents -128
         if (exponent>=128) exponent = exponent-256;
	 //printf("fl_mk calling doflt(%lld, %lld, %lld)\n",
         //        LL op, LL a, LL exponent);
         a = doflt(op, a, exponent, 0);
         goto fetch;
       }

       case fl_float:
       case fl_fix:
       case fl_pos:
       case fl_neg:
       case fl_abs:
         a = doflt(op, a, 0, 0);
         goto fetch;

       case fl_mul:
       case fl_div:
       case fl_mod: // Added 14/5/18
       case fl_add:
       case fl_sub:
       case fl_eq:
       case fl_ne:
       case fl_ls:
       case fl_gr:
       case fl_le:
       case fl_ge:
         a = doflt(op, b, a, 0);
         goto fetch;
       }
#endif
     }

     // Added 21/7/10
   case F_selld:  // load a field  SELLD len sh
     { BCPLWORD len = B[pc++];
       BCPLWORD sh  = B[pc++];
       BCPLWORD mask = -1;
       if (len) mask = (1<<len) - 1;
       a = (W[a]>>sh) & mask;
       goto fetch;
     }

     // Added 21/7/10
   case F_selst: // SLCT len:sh:0 OF <arg1> op:= <arg2>
                 //      len sh         a   op      b
     { BCPLWORD *ptr = &W[a];
       BCPLWORD op  = B[pc++];
       BCPLWORD len = B[pc++];
       BCPLWORD sh  = B[pc++];
       BCPLWORD mask;
       BCPLWORD val;
       BCPLWORD oldval;
       union IorF { BCPLWORD i; float f; } x, y;

       if(len==0) {
         mask = UWD(-1) >> sh;
       } else {
         mask = (1<<len) - 1;
       }
       val = WD(((UWD*ptr)>>sh)) & mask;
       oldval = val; // Old value shifted down

       // val and oldval are both the old field value shifted down
       switch(op) {
       default:          a = 0; goto fetch;
       case sf_none:     val = b;                 break;
       case sf_vecap:    val = W[val + b];        break;
       case sf_fmul:     x.i = val; y.i = b;
                         x.f = x.f * y.f;
                         val = x.i;               break;
       case sf_fdiv:     x.i = val; y.i = b;
                         x.f = x.f / y.f;
                         val = x.i;               break;
       case sf_fadd:     x.i = val; y.i = b;
                         x.f = x.f + y.f;
                         val = x.i;               break;
       case sf_fsub:     x.i = val; y.i = b;
                         x.f = x.f - y.f;
                         val = x.i;               break;
       case sf_mul:      val *= b;                break;
       case sf_div:      val /= b;                break;
       case sf_mod:      val %= b;                break;
       case sf_add:      val += b;                break;
       case sf_sub:      val -= b;                break;
       case sf_lshift:   if (b>=BperW) val=0; /* bug */
                         val <<= b;               break;
       case sf_rshift:   if (b>=BperW) val=0; /* bug */
	                 val = WD((UWD val)>>b);  break;
       case sf_logand:   val &= b;                break;
       case sf_logor:    val |= b;                break;
       case sf_eqv:      val = ~(val ^ b);        break;
       case sf_xor:      val ^= b;                break;
       }
       //printf("selst: op=%lld len=%lld sh=%lld oldval=%08llx "
                "val=%08llx mask=%08llx\n",
       //       LL op, LL len, LL sh,
       //       LL (UBCPLWORD)oldval, LL (UBCPLWORD)val, LL (UBCPLWORD)mask);
       // Replace field by new value
       *ptr ^= ((val ^ oldval)&mask) << sh;
       goto fetch;
     }

   case F_mul:   a = b * a;        goto fetch;
   case F_div:   if(a==0) {res=5;  goto ret; } /* Division by zero */
                 a = b / a;        goto fetch;
   case F_rem:   if(a==0) {res=5;  goto ret; } /* Division by zero */
                 a = b % a;        goto fetch;
   case F_add:   a = b + a;        goto fetch;
   case F_sub:   a = b - a;        goto fetch;
   case F_neg:   a = - a;          goto fetch;

   case F_fhop:  a = 0; pc++;      goto fetch;

   case F_lsh:   if (a>=BperW) b=0; /* bug */
                 a = b << a;       goto fetch;
   case F_rsh:   if (a>=BperW) b=0; /* bug */
                 a = WD((UWD b)>>a); goto fetch;
   case F_not:   a = ~ a;          goto fetch;
   case F_and:   a = b & a;        goto fetch;
   case F_or:    a = b | a;        goto fetch;
   case F_xor:   a = b ^ a;        goto fetch;

   case F_goto:  pc = a;           goto fetchchk;

   case F_brk:   res = 2; pc--; goto ret;  /* BREAKPOINT  */
                 
   case F_rv+6:  MC1(a+6) a = W[a+6]; goto fetch;
   case F_rv+5:  MC1(a+5) a = W[a+5]; goto fetch;
   case F_rv+4:  MC1(a+4) a = W[a+4]; goto fetch;
   case F_rv+3:  MC1(a+3) a = W[a+3]; goto fetch;
   case F_rv+2:  MC1(a+2) a = W[a+2]; goto fetch;
   case F_rv+1:  MC1(a+1) a = W[a+1]; goto fetch;
   case F_rv:    MC1(a+0) a = W[a+0]; goto fetch;

   case F_st+3:  MC1(a+3) W[a+3] = b; goto fetch;
   case F_st+2:  MC1(a+2) W[a+2] = b; goto fetch;
   case F_st+1:  MC1(a+1) W[a+1] = b; goto fetch;
   case F_st:    MC1(a+0) W[a+0] = b; goto fetch;

   case F_chgco: MC1(Wp[4]) 
                 W[Wg[Gn_currco]] = Wp[0]; /* !currco := !p    */
                 pc = Wp[1];               /* pc      := p!1   */
                 Wg[Gn_currco] = Wp[4];    /* currco  := cptr  */
                 p = W[Wp[4]]>>B2Wsh;      /* p       := !cptr */
                 Wp = W+p;
                 lastWp = Wp;
                 goto fetchchk;

 case F_mdiv:    //printf("mdiv: calling muldiv\n");
                 a = muldiv(Wp[3], Wp[4], Wp[5]);
                 Wg[Gn_result2] = result2;

		 //{ BCPLINT64 ab = (BCPLINT64)(Wp[3]) * (BCPLINT64)(Wp[4]);
                 //  BCPLWORD c = Wp[5];
                 //  if(c==0) c=1;
                 //  Wg[Gn_result2] = (BCPLWORD)(ab % c);
                 //  a = (BCPLWORD)(ab / c);
                 //  /* fall through to return  */
		 //}
   case F_rtn:   pc = Wp[1];
                 p  = W[p]>>B2Wsh;
                 Wp = W+p; 
                 lastWp = Wp;
                 goto fetchchk;

   case F_gbyt: i=a+(b<<B2Wsh); MC1(i>>B2Wsh) a=B[i]; goto fetch;
   case F_pbyt: i=a+(b<<B2Wsh); MC1(i>>B2Wsh) B[i]=c; goto fetch;
   case F_xpbyt:i=b+(a<<B2Wsh); MC1(i>>B2Wsh) B[i]=c; goto fetch;
   case F_atc:  c = a;                      goto fetch;
   case F_btc:  c = b;                      goto fetch;
   case F_atb:  b = a;                      goto fetch;
   case F_xch:  a = a^b; b = a^b; a = a^b;  goto fetch;

   case F_swb: { BCPLWORD n, k, val, i=1;
                 k = (pc+1)>>1;
                 n = H[k];
                 while(i<=n)
                 { i += i;
                   val = H[k+i];
                   if (a==val) { k += i; break; }
                   if (a<val) i++;
                 }
                 k++;
                 pc = (k<<1) + SH[k];
                 goto fetchchk;
               }

   case F_swl: { BCPLWORD n,q;
                 q = (pc+1)>>1;
                 n = H[q++];
                 if(0<=a && a<n) q += a + 1;
                 pc = (q<<1) + SH[q];
                 goto fetchchk;
               }

   case F_sys: switch(a) {
                 default: // system call -- general case
 
		         W[regs+0]  = a;    /* Save all the registers */
		         W[regs+1]  = b;    /* for debugging purposes */
                         W[regs+2]  = c;
                         W[regs+3]  = p<<B2Wsh;
                         W[regs+4]  = g<<B2Wsh;
                         W[regs+5]  = st;
                         W[regs+6]  = pc;
                         W[regs+7]  = count;
                         W[regs+8]  = mw;
  
                         a = dosys(p, g); 
                         goto fetch;

                 case Sys_setcount:
                         /* oldcount := sys(Sys_setcount, newcount)  */
                         a = count; 
		         count = Wp[4];
                         res = -1; /* Leave and immediately re-enter */
                         goto ret; /* the interpreter */

                 case Sys_quit:
                         res = Wp[4];
                         goto ret;

                 case Sys_rti:
                         /*  sys(Sys_rti, regs) */
                       { BCPLWORD s = Wp[4];

                         a  = W[s+0];
                         b  = W[s+1];
                         c  = W[s+2];
                         p  = W[s+3]>>B2Wsh;
                         g  = W[s+4]>>B2Wsh;
                         st = W[s+5];
                         pc = W[s+6];
                         //count = W[s+7];

                         Wp  = W+p;
                         Wg  = W+g;
                         Wg1 = W+g+256;
                         lastWp = Wp;
                         lastWg = Wg;
                         lastst = st;
                         goto fetchchk;
                       }

                 case Sys_saveregs:
                         /* sys(Sys_saveregs, regs) */
                       { BCPLWORD s = Wp[4];

                         W[s+0] = a;
                         W[s+1] = b;
                         W[s+2] = c;
                         W[s+3] = Wp[0];  /* typically p of eg qpkt not sys  */
                         W[s+4] = g<<B2Wsh;
                         W[s+5] = st;
                         W[s+6] = pc;     /* pc -> RTN in sys function  */
                         W[s+7] = count;

                         goto fetch; 
                       }

                 case Sys_setst:
                         /* sys(Sys_setst, st)  */
                         st = Wp[4];
			 lastst = st;
                         goto fetch;

                 case Sys_tracing:
                         /* sys(Sys_tracing, b)  */
                       { tracing = Wp[4];
                         goto fetch;
                       }

                 case Sys_watch:
                         /* sys(Sys_watch, addr)  */
                       { watchaddr = &W[Wp[4]];
	                 watchval = *watchaddr;
                         goto fetch;
                       }
               }

   case F_lp0+16:  b = a; a = Wp[16]; goto fetch;
   case F_lp0+15:  b = a; a = Wp[15]; goto fetch;
   case F_lp0+14:  b = a; a = Wp[14]; goto fetch;
   case F_lp0+13:  b = a; a = Wp[13]; goto fetch;
   case F_lp0+12:  b = a; a = Wp[12]; goto fetch;
   case F_lp0+11:  b = a; a = Wp[11]; goto fetch;
   case F_lp0+10:  b = a; a = Wp[10]; goto fetch;
   case F_lp0+9:   b = a; a = Wp[9];  goto fetch;
   case F_lp0+8:   b = a; a = Wp[8];  goto fetch;
   case F_lp0+7:   b = a; a = Wp[7];  goto fetch;
   case F_lp0+6:   b = a; a = Wp[6];  goto fetch;
   case F_lp0+5:   b = a; a = Wp[5];  goto fetch;
   case F_lp0+4:   b = a; a = Wp[4];  goto fetch;
   case F_lp0+3:   b = a; a = Wp[3];  goto fetch;

   case F_lp:   b = a; a = Wp[B[pc++]];          goto fetch;
   case F_lph:  b = a; a = Wp[GH(pc)];  pc += 2; goto fetch;

#ifdef TARGET64
   case F_lpw:  b = a;
                a = Wp[mw+GW(pc)]; mw = 0;
                pc += 4; goto fetch;

#else
   case F_lpw:  b = a; a = Wp[GW(pc)];  pc += 4; goto fetch;
#endif

   case F_llp:  b = a; a = p+B[pc++];             goto fetch;
   case F_llph: b = a; a = p+GH(pc);     pc += 2; goto fetch;

#ifdef TARGET64
   case F_llpw: b = a;
                a = p+GW(mw+pc); mw = 0;
                pc += 4; goto fetch;
#else
   case F_llpw: b = a; a = p+GW(pc);     pc += 4; goto fetch;
#endif

   case F_sp0+16: Wp[16] = a; goto fetch;
   case F_sp0+15: Wp[15] = a; goto fetch;
   case F_sp0+14: Wp[14] = a; goto fetch;
   case F_sp0+13: Wp[13] = a; goto fetch;
   case F_sp0+12: Wp[12] = a; goto fetch;
   case F_sp0+11: Wp[11] = a; goto fetch;
   case F_sp0+10: Wp[10] = a; goto fetch;
   case F_sp0+9:  Wp[9]  = a; goto fetch;
   case F_sp0+8:  Wp[8]  = a; goto fetch;
   case F_sp0+7:  Wp[7]  = a; goto fetch;
   case F_sp0+6:  Wp[6]  = a; goto fetch;
   case F_sp0+5:  Wp[5]  = a; goto fetch;
   case F_sp0+4:  Wp[4]  = a; goto fetch;
   case F_sp0+3:  Wp[3]  = a; goto fetch;

   case F_sp:    Wp[B[pc++]] = a;                  goto fetch;
   case F_sph:   Wp[GH(pc)]  = a;         pc += 2; goto fetch;

#ifdef TARGET64
   case F_spw:   Wp[mw+GW(pc)]  = a; mw = 0;
                 pc += 4; goto fetch;
#else
   case F_spw:   Wp[GW(pc)]  = a;         pc += 4; goto fetch;
#endif

   case F_lgh:   b = a; a = Wg[GH(pc)];   pc += 2; goto fetch;
   case F_lg1:   b = a; a = Wg1[B[pc++]];          goto fetch;
   case F_lg:    b = a; a = Wg[B[pc++]];           goto fetch;

   case F_sgh:   Wg[GH(pc)]   = a;        pc += 2; goto fetch;
   case F_sg1:   Wg1[B[pc++]] = a;                 goto fetch;
   case F_sg:    Wg[B[pc++]]  = a;                 goto fetch;

   case F_llgh: b = a; a = g+GH(pc);      pc += 2; goto fetch;
   case F_llg1: b = a; a = g+256+B[pc++];          goto fetch;
   case F_llg:  b = a; a = g+B[pc++];              goto fetch;

   case F_ll+1: i = (pc>>1) + B[pc];
                i = (i<<1) + SH[i];
                b = a; a = W[i>>B2Wsh];          pc++; goto fetch;

   case F_ll:   b = a; a = W[(pc+SB[pc])>>B2Wsh];pc++; goto fetch;

   case F_sl+1: i = (pc>>1) + B[pc];
                i = (i<<1) + SH[i];
                W[i>>B2Wsh] = a;                 pc++; goto fetch;

   case F_sl:   W[(pc+SB[pc])>>B2Wsh] = a;       pc++; goto fetch;
   
   case F_lll+1:i = (pc>>1) + B[pc];
                i = (i<<1) + SH[i];
                b = a; a = i>>B2Wsh;             pc++; goto fetch;

   case F_lll:  b = a; a = (pc+SB[pc])>>B2Wsh;   pc++; goto fetch;
   
   case F_l0+10: b = a; a = 10; goto fetch;
   case F_l0+9:  b = a; a =  9; goto fetch;
   case F_l0+8:  b = a; a =  8; goto fetch;
   case F_l0+7:  b = a; a =  7; goto fetch;
   case F_l0+6:  b = a; a =  6; goto fetch;
   case F_l0+5:  b = a; a =  5; goto fetch;
   case F_l0+4:  b = a; a =  4; goto fetch;
   case F_l0+3:  b = a; a =  3; goto fetch;
   case F_l0+2:  b = a; a =  2; goto fetch;
   case F_l0+1:  b = a; a =  1; goto fetch;
   case F_l0:    b = a; a =  0; goto fetch;
   case F_l0-1:  b = a; a = -1; goto fetch; 

   case F_l:     b = a; a = B[pc++];               goto fetch;
   case F_lh:    b = a; a = GH(pc);       pc += 2; goto fetch;

#ifdef TARGET64
   case F_lw:    b = a; a = mw+GW(pc); mw = 0;
                 pc += 4; goto fetch;
#else
   case F_lw:    b = a; a = GW(pc);       pc += 4; goto fetch;
#endif

   case F_lm:    b = a; a = - WD(B[pc++]);         goto fetch;
   case F_lmh:   b = a; a = - WD(GH(pc)); pc += 2; goto fetch;
                
   case F_lf+1:  b = a;
                 a = (pc>>1) + B[pc];
                 a = (a<<1) + SH[a];         pc++; goto fetch;

   case F_lf:    b = a; a = pc + SB[pc];     pc++; goto fetch;
 
   case F_k0gh+11: Wp[11] = p<<B2Wsh; p += 11; goto applygh;
   case F_k0gh+10: Wp[10] = p<<B2Wsh; p += 10; goto applygh;
   case F_k0gh+9:  Wp[ 9] = p<<B2Wsh; p +=  9; goto applygh;
   case F_k0gh+8:  Wp[ 8] = p<<B2Wsh; p +=  8; goto applygh;
   case F_k0gh+7:  Wp[ 7] = p<<B2Wsh; p +=  7; goto applygh;
   case F_k0gh+6:  Wp[ 6] = p<<B2Wsh; p +=  6; goto applygh;
   case F_k0gh+5:  Wp[ 5] = p<<B2Wsh; p +=  5; goto applygh;
   case F_k0gh+4:  Wp[ 4] = p<<B2Wsh; p +=  4; goto applygh;
   case F_k0gh+3:  Wp[ 3] = p<<B2Wsh; p +=  3;
   applygh:        Wp    = W+p;
                   Wp[1] = pc + 2;
                   pc    = Wg[GH(pc)];
                   Wp[2] = pc;
                   Wp[3] =  a;
                   lastWp = Wp;
                   goto fetchchk;

   case F_k0g1+11: Wp[11] = p<<B2Wsh; p += 11; goto applyg1;
   case F_k0g1+10: Wp[10] = p<<B2Wsh; p += 10; goto applyg1;
   case F_k0g1+9:  Wp[ 9] = p<<B2Wsh; p +=  9; goto applyg1;
   case F_k0g1+8:  Wp[ 8] = p<<B2Wsh; p +=  8; goto applyg1;
   case F_k0g1+7:  Wp[ 7] = p<<B2Wsh; p +=  7; goto applyg1;
   case F_k0g1+6:  Wp[ 6] = p<<B2Wsh; p +=  6; goto applyg1;
   case F_k0g1+5:  Wp[ 5] = p<<B2Wsh; p +=  5; goto applyg1;
   case F_k0g1+4:  Wp[ 4] = p<<B2Wsh; p +=  4; goto applyg1;
   case F_k0g1+3:  Wp[ 3] = p<<B2Wsh; p +=  3;
   applyg1:        Wp    = W+p;
                   Wp[1] = pc + 1;
                   pc    = Wg1[B[pc]];
                   Wp[2] = pc;
                   Wp[3] = a;
                   lastWp = Wp;
                   goto fetchchk;
 
   case F_k0g+11: Wp[11] = p<<B2Wsh; p += 11; goto applyg;
   case F_k0g+10: Wp[10] = p<<B2Wsh; p += 10; goto applyg;
   case F_k0g+9:  Wp[ 9] = p<<B2Wsh; p +=  9; goto applyg;
   case F_k0g+8:  Wp[ 8] = p<<B2Wsh; p +=  8; goto applyg;
   case F_k0g+7:  Wp[ 7] = p<<B2Wsh; p +=  7; goto applyg;
   case F_k0g+6:  Wp[ 6] = p<<B2Wsh; p +=  6; goto applyg;
   case F_k0g+5:  Wp[ 5] = p<<B2Wsh; p +=  5; goto applyg;
   case F_k0g+4:  Wp[ 4] = p<<B2Wsh; p +=  4; goto applyg;
   case F_k0g+3:  Wp[ 3] = p<<B2Wsh; p +=  3;
   applyg:        Wp    = W+p;
                  Wp[1] = pc + 1;
                  pc    = Wg[B[pc]];
                  Wp[2] = pc;
                  Wp[3] = a;
                  lastWp = Wp;
                  goto fetchchk;
 
   case F_k0+11:  Wp[11] = p<<B2Wsh; p += 11; goto applyk;
   case F_k0+10:  Wp[10] = p<<B2Wsh; p += 10; goto applyk;
   case F_k0+9:   Wp[ 9] = p<<B2Wsh; p +=  9; goto applyk;
   case F_k0+8:   Wp[ 8] = p<<B2Wsh; p +=  8; goto applyk;
   case F_k0+7:   Wp[ 7] = p<<B2Wsh; p +=  7; goto applyk;
   case F_k0+6:   Wp[ 6] = p<<B2Wsh; p +=  6; goto applyk;
   case F_k0+5:   Wp[ 5] = p<<B2Wsh; p +=  5; goto applyk;
   case F_k0+4:   Wp[ 4] = p<<B2Wsh; p +=  4; goto applyk;
   case F_k0+3:   Wp[ 3] = p<<B2Wsh; p +=  3;
   applyk:        Wp    = W+p;
                  Wp[1] = WD pc;
                  pc    = a;
                  Wp[2] = pc;
                  Wp[3] = a = b;
                  lastWp = Wp;
                  goto fetchchk;

   case F_k:      k = B[pc]; Wp[k] = p<<B2Wsh; p +=  k;
                  Wp    = W+p;
                  Wp[1] = pc + 1;
                  pc    = a;
                  Wp[2] = pc;
                  Wp[3] = a = b;
                  lastWp = Wp;
                  goto fetchchk;

   case F_kh:     k = GH(pc); Wp[k] = p<<B2Wsh; p +=  k;
                  Wp    = W+p;
                  Wp[1] = pc + 2;
                  pc    = a;
                  Wp[2] = pc;
                  Wp[3] = a = b;
                  lastWp = Wp;
                  goto fetchchk;

#ifdef TARGET64
   case F_kw:     k = mw+GW(pc); mw = 0;
                  Wp[k] = p<<B2Wsh; p +=  k;
#else
   case F_kw:     k = GW(pc); Wp[k] = p<<B2Wsh; p +=  k;
#endif
                  Wp    = W+p;
                  Wp[1] = pc + 4;
                  pc    = a;
                  Wp[2] = pc;
                  Wp[3] = a = b;
                  lastWp = Wp;
                  goto fetchchk;

   case F_jeq:   if(b==a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jeq+1: if(b==a) goto indjump;
                 pc++; goto fetch;
   case F_jeq+2: if(a==0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jeq+3: if(a==0) goto indjump;
                 pc++; goto fetch;

   case F_jne:   if(b!=a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jne+1: if(b!=a) goto indjump;
                 pc++; goto fetch;
   case F_jne+2: if(a!=0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jne+3: if(a!=0) goto indjump;
                 pc++; goto fetch;

   case F_jls:   if(b<a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jls+1: if(b<a) goto indjump;
                 pc++; goto fetch;
   case F_jls+2: if(a<0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jls+3: if(a<0) goto indjump;
                 pc++; goto fetch;

   case F_jgr:   if(b>a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jgr+1: if(b>a) goto indjump;
                 pc++; goto fetch;
   case F_jgr+2: if(a>0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jgr+3: if(a>0) goto indjump;
                 pc++; goto fetch;

   case F_jle:   if(b<=a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jle+1: if(b<=a) goto indjump;
                 pc++; goto fetch;
   case F_jle+2: if(a<=0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jle+3: if(a<=0) goto indjump;
                 pc++; goto fetch;

   case F_jge:   if(b>=a) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jge+1: if(b>=a) goto indjump;
                 pc++; goto fetch;
   case F_jge+2: if(a>=0) { pc += SB[pc];   goto fetch; }
                 pc++; goto fetch;
   case F_jge+3: if(a>=0) goto indjump;
                 pc++; goto fetch;

   case F_j:     pc += SB[pc];        goto fetch;

 indjump:
   case F_j+1:   pc = (pc>>1) + B[pc];
                 pc = (pc<<1) + SH[pc];
                 goto fetch;

   case F_ap0+12: a = a + Wp[12]; goto fetch;
   case F_ap0+11: a = a + Wp[11]; goto fetch;
   case F_ap0+10: a = a + Wp[10]; goto fetch;
   case F_ap0+9:  a = a + Wp[ 9]; goto fetch;
   case F_ap0+8:  a = a + Wp[ 8]; goto fetch;
   case F_ap0+7:  a = a + Wp[ 7]; goto fetch;
   case F_ap0+6:  a = a + Wp[ 6]; goto fetch;
   case F_ap0+5:  a = a + Wp[ 5]; goto fetch;
   case F_ap0+4:  a = a + Wp[ 4]; goto fetch;
   case F_ap0+3:  a = a + Wp[ 3]; goto fetch;

   case F_ap:    a += Wp[B[pc++]];         goto fetch;
   case F_aph:   a += Wp[GH(pc)]; pc += 2; goto fetch;

#ifdef TARGET64
   case F_apw:   a += Wp[mw+GW(pc)]; mw = 0;
                 pc += 4; goto fetch;
#else
   case F_apw:   a += Wp[GW(pc)]; pc += 4; goto fetch;
#endif

   case F_agh:   a += Wg[GH(pc)]; pc += 2; goto fetch;
   case F_ag1:   a += Wg1[B[pc++]];        goto fetch;
   case F_ag:    a += Wg[B[pc++]];         goto fetch;

   case F_a0+5: a += 5; goto fetch;
   case F_a0+4: a += 4; goto fetch;
   case F_a0+3: a += 3; goto fetch;
   case F_a0+2: a += 2; goto fetch;
   case F_a0+1: a += 1; goto fetch;
   case F_nop:          goto fetch;

   // mv is only used in 64-bit Cintcode
   // Only include if TARGET64 is define to avoid a warning

#ifdef TARGET64
   case F_mw:   mw = ((BCPLWORD)GW(pc))<<32;
                pc += 4; goto fetch;
#endif

   case F_a:    a += B[pc++];           goto fetch;
   case F_ah:   a += GH(pc);   pc += 2; goto fetch;

#ifdef TARGET64
   case F_aw:   a += mw+GW(pc); mw = 0;
                pc += 4; goto fetch;
#else
   case F_aw:   a += GW(pc);   pc += 4; goto fetch;
#endif

   case F_s:    a -= B[pc++];           goto fetch;
   case F_sh:   a -= GH(pc);   pc += 2; goto fetch;

   case F_s0+4: a -= 4; goto fetch;
   case F_s0+3: a -= 3; goto fetch;
   case F_s0+2: a -= 2; goto fetch;
   case F_s0+1: a -= 1; goto fetch;

   case F_l0p0+12: b = a; MC1(Wp[12]+0) a = W[Wp[12]+0]; goto fetch;
   case F_l0p0+11: b = a; MC1(Wp[11]+0) a = W[Wp[11]+0]; goto fetch;
   case F_l0p0+10: b = a; MC1(Wp[10]+0) a = W[Wp[10]+0]; goto fetch;
   case F_l0p0+9:  b = a; MC1(Wp[ 9]+0) a = W[Wp[ 9]+0]; goto fetch;
   case F_l0p0+8:  b = a; MC1(Wp[ 8]+0) a = W[Wp[ 8]+0]; goto fetch;
   case F_l0p0+7:  b = a; MC1(Wp[ 7]+0) a = W[Wp[ 7]+0]; goto fetch;
   case F_l0p0+6:  b = a; MC1(Wp[ 6]+0) a = W[Wp[ 6]+0]; goto fetch;
   case F_l0p0+5:  b = a; MC1(Wp[ 5]+0) a = W[Wp[ 5]+0]; goto fetch;
   case F_l0p0+4:  b = a; MC1(Wp[ 4]+0) a = W[Wp[ 4]+0]; goto fetch;
   case F_l0p0+3:  b = a; MC1(Wp[ 3]+0) a = W[Wp[ 3]+0]; goto fetch;

   case F_l1p0+6:  b = a; MC1(Wp[ 6]+1) a = W[Wp[ 6]+1]; goto fetch;
   case F_l1p0+5:  b = a; MC1(Wp[ 5]+1) a = W[Wp[ 5]+1]; goto fetch;
   case F_l1p0+4:  b = a; MC1(Wp[ 4]+1) a = W[Wp[ 4]+1]; goto fetch;
   case F_l1p0+3:  b = a; MC1(Wp[ 3]+1) a = W[Wp[ 3]+1]; goto fetch;

   case F_l2p0+5:  b = a; MC1(Wp[ 5]+2) a = W[Wp[ 5]+2]; goto fetch;
   case F_l2p0+4:  b = a; MC1(Wp[ 4]+2) a = W[Wp[ 4]+2]; goto fetch;
   case F_l2p0+3:  b = a; MC1(Wp[ 3]+2) a = W[Wp[ 3]+2]; goto fetch;

   case F_l3p0+4:  b = a; MC1(Wp[ 4]+3) a = W[Wp[ 4]+3]; goto fetch;
   case F_l3p0+3:  b = a; MC1(Wp[ 3]+3) a = W[Wp[ 3]+3]; goto fetch;

   case F_l4p0+4:  b = a; MC1(Wp[ 4]+4) a = W[Wp[ 4]+4]; goto fetch;
   case F_l4p0+3:  b = a; MC1(Wp[ 3]+4) a = W[Wp[ 3]+4]; goto fetch;

   case F_l0gh:  b = a; i = Wg[GH(pc)]+0; MC1(i) a=W[i]; pc += 2; goto fetch;
   case F_l1gh:  b = a; i = Wg[GH(pc)]+1; MC1(i) a=W[i]; pc += 2; goto fetch;
   case F_l2gh:  b = a; i = Wg[GH(pc)]+2; MC1(i) a=W[i]; pc += 2; goto fetch;
   case F_l0g1:  b = a; i = Wg1[B[pc++]]+0;        MC2(i) a=W[i]; goto fetch;
   case F_l1g1:  b = a; i = Wg1[B[pc++]]+1;        MC2(i) a=W[i]; goto fetch;
   case F_l2g1:  b = a; i = Wg1[B[pc++]]+2;        MC2(i) a=W[i]; goto fetch;
   case F_l0g:   b = a; i = Wg[B[pc++]]+0;         MC2(i) a=W[i]; goto fetch;
   case F_l1g:   b = a; i = Wg[B[pc++]]+1;         MC2(i) a=W[i]; goto fetch;
   case F_l2g:   b = a; i = Wg[B[pc++]]+2;         MC2(i) a=W[i]; goto fetch;

   case F_s0gh:  i=Wg[GH(pc)]+0;   MC1(i) W[i] = a;      pc += 2; goto fetch;
   case F_s0g1:  i=Wg1[B[pc++]]+0; MC2(i) W[i] = a;               goto fetch;
   case F_s0g:   i=Wg[B[pc++]]+0;  MC2(i) W[i] = a;               goto fetch;

   case F_stp0+5: i=a+Wp[5]; MC1(i) W[i] = b; goto fetch;
   case F_stp0+4: i=a+Wp[4]; MC1(i) W[i] = b; goto fetch;
   case F_stp0+3: i=a+Wp[3]; MC1(i) W[i] = b; goto fetch;

   case F_st0p0+4: i=Wp[4]+0; MC1(i) W[i] = a; goto fetch;
   case F_st0p0+3: i=Wp[3]+0; MC1(i) W[i] = a; goto fetch;

   case F_st1p0+4: i=Wp[4]+1; MC1(i) W[i] = a; goto fetch;
   case F_st1p0+3: i=Wp[3]+1; MC1(i) W[i] = a; goto fetch;
   
   case F_rvp0+7: i = a+Wp[7]; MC1(i) a = W[i]; goto fetch;
   case F_rvp0+6: i = a+Wp[6]; MC1(i) a = W[i]; goto fetch;
   case F_rvp0+5: i = a+Wp[5]; MC1(i) a = W[i]; goto fetch;
   case F_rvp0+4: i = a+Wp[4]; MC1(i) a = W[i]; goto fetch;
   case F_rvp0+3: i = a+Wp[3]; MC1(i) a = W[i]; goto fetch;
   }

badpc:
   res = 4;  /* pc too large or negative  */
 
ret:
   tracing = 0;
   //printf("cinterp: returning from interpret, res=%lld\n", LL res);
   W[regs+0]  = a;    /* Save the machine registers  */
   W[regs+1]  = b;
   W[regs+2]  = c;
   W[regs+3]  = p<<B2Wsh;
   W[regs+4]  = g<<B2Wsh;
   W[regs+5]  = st;
   W[regs+6]  = pc;
   W[regs+7]  = count;
   W[regs+8]  = mw;

   /* Save p in currco resumption point, for debugging purposes     */
   /* currco must always be set to the coroutine stack containing p */
   //W[Wg[Gn_currco]] = p;
   
   return res;  // Return from this invocation of interpret
}

