Example #1
0
#define _FN3(rt, a1, a2, a3, s, d, f) _FN(SEXP_OP_FCALL3, 3, 0, rt, a1, a2, a3, s, d, f)
#define _FN3OPT(rt, a1, a2, a3, s, d, f) _FN(SEXP_OP_FCALL3, 2, 1, rt, a1, a2, a3, s, d, f)
#define _FN4(rt, a1, a2, a3, s, d, f) _FN(SEXP_OP_FCALL4, 4, 0, rt, a1, a2, a3, s, d, f)
#define _FN5(rt, a1, a2, a3, s, d, f) _FN(SEXP_OP_FCALLN, 5, 0, rt, a1, a2, a3, s, d, f)

static struct sexp_opcode_struct opcodes[] = {
_PARAM("current-input-port", _I(SEXP_IPORT)),
_PARAM("current-output-port", _I(SEXP_OPORT)),
_PARAM("current-error-port", _I(SEXP_OPORT)),
_PARAM("current-exception-handler", _I(SEXP_PROCEDURE)),
_PARAM("interaction-environment", _I(SEXP_ENV)),
_PARAM("current-usage-environment", _I(SEXP_ENV)),
_PARAM("current-transformer-environment", _I(SEXP_ENV)),
_PARAM("current-renamer", _I(SEXP_PROCEDURE)),
_PARAM("command-line", SEXP_NULL),
_OP(SEXP_OPC_GETTER, SEXP_OP_CAR, 1, 0, _I(SEXP_OBJECT), _I(SEXP_PAIR), SEXP_FALSE, SEXP_FALSE, 0, "car", 0, NULL),
_OP(SEXP_OPC_SETTER, SEXP_OP_SET_CAR, 2, 0, SEXP_VOID, _I(SEXP_PAIR), _I(SEXP_OBJECT), SEXP_FALSE, 0, "set-car!", 0, NULL),
_OP(SEXP_OPC_GETTER, SEXP_OP_CDR, 1, 0, _I(SEXP_OBJECT), _I(SEXP_PAIR), SEXP_FALSE, SEXP_FALSE, 0, "cdr", 0, NULL),
_OP(SEXP_OPC_SETTER, SEXP_OP_SET_CDR, 2, 0, SEXP_VOID, _I(SEXP_PAIR), _I(SEXP_OBJECT), SEXP_FALSE, 0, "set-cdr!", 0, NULL),
_GETTER("pair-source", SEXP_PAIR, 2),
_SETTER("pair-source-set!", SEXP_PAIR, 2),
_GETTER("syntactic-closure-rename", SEXP_SYNCLO, 3),
_SETTER("syntactic-closure-set-rename!", SEXP_SYNCLO, 3),
_OP(SEXP_OPC_GETTER, SEXP_OP_VECTOR_REF, 2, 0, _I(SEXP_OBJECT), _I(SEXP_VECTOR), _I(SEXP_FIXNUM), SEXP_FALSE, 0, "vector-ref", 0, NULL),
_OP(SEXP_OPC_SETTER, SEXP_OP_VECTOR_SET, 3, 0, SEXP_VOID, _I(SEXP_VECTOR), _I(SEXP_FIXNUM), _I(SEXP_OBJECT), 0, "vector-set!", 0, NULL),
_OP(SEXP_OPC_GETTER, SEXP_OP_VECTOR_LENGTH, 1, 0, _I(SEXP_FIXNUM), _I(SEXP_VECTOR), SEXP_FALSE, SEXP_FALSE, 0, "vector-length", 0, NULL),
_OP(SEXP_OPC_GETTER, SEXP_OP_BYTES_REF, 2, 0, _I(SEXP_FIXNUM), _I(SEXP_BYTES), _I(SEXP_FIXNUM), SEXP_FALSE, 0, "bytevector-u8-ref", 0, NULL),
_OP(SEXP_OPC_SETTER, SEXP_OP_BYTES_SET, 3, 0, SEXP_VOID, _I(SEXP_BYTES), _I(SEXP_FIXNUM), _I(SEXP_FIXNUM), 0, "bytevector-u8-set!", 0, NULL),
_OP(SEXP_OPC_GETTER, SEXP_OP_BYTES_LENGTH, 1, 0, _I(SEXP_FIXNUM), _I(SEXP_BYTES), SEXP_FALSE, SEXP_FALSE, 0, "bytevector-length", 0, NULL),
#if SEXP_USE_UTF8_STRINGS
_OP(SEXP_OPC_GETTER, SEXP_OP_STRING_REF, 2, 0, _I(SEXP_CHAR), _I(SEXP_STRING), _I(SEXP_STRING_CURSOR), SEXP_FALSE, 0, "string-cursor-ref", 0, NULL),
Example #2
0
int
sim_proper(core_t *core, const field_t * const war_pos_tab, unsigned int *death_tab )
{
  /*
   * Core and Process queue memories.
   *
   * The warriors share a common cyclic buffer for use as a process
   * queue which the contains core addresses where active processes
   * are.  The buffer has size N*P+1, where N = number of warriors,
   * P = maximum number of processes / warrior.
   *
   * Each warrior has a fixed slice of the buffer for its own process
   * queue which are initially allocated to the warriors in reverse
   * order. i.e. if the are N warriors w1, w2, ..., wN, the slice for
   * wN is 0..P-1, w{N-1} has P..2P-1, until w1 has (N-1)P..NP-1.
   *
   * The core address of the instruction is fetched from the head of
   * the process queue and processes are pushed to the tail, so the
   * individual slices slide along at one location per executed
   * instruction.  The extra '+1' in the buffer size is to have free
   * space to slide the slices along.
   * 
   * For two warriors w1, w2:
   *
   * |\......../|\......../| |
   * | w2 queue | w1 queue | |
   * 0          P         2P 2P+1
   */

  /*
   * Cache Registers.
   *
   * The '94 draft specifies that the redcode processor model be
   * 'in-register'.  That is, the current instruction and the
   * instructions at the effective addresses (ea's) be cached in
   * registers during instruction execution, rather than have
   * core memory accessed directly when the operands are needed.  This
   * causes differences from the 'in-memory' model.  e.g. MOV 0,>0
   * doesn't change the instruction's b-field since the instruction at
   * the a-field's effective address (i.e. the instruction itself) was
   * cached before the post-increment happened.
   *
   * There are conceptually three registers: IN, A, and B.  IN is the
   * current instruction, and A, B are the ones at the a- and
   * b-fields' effective addresses respectively.
   *
   * We don't actually cache the complete instructions, but rather
   * only the *values* of their a- and b-field.  This is because
   * currently there is no way effective address computations can
   * modify the opcode, modifier, or addressing modes of an
   * instruction.
   */


  /*
   * misc.
   */
  insn_t* const coreptr = core->Core_Mem;
  insn_t** const queue_start = core->Queue_Mem;
  insn_t** const queue_end = core->Queue_Mem + core->NWarriors*core->Processes+1;
  w_t* w;			/* current warrior */
  const unsigned int coresize = core->Coresize;
  const unsigned int coresize1 = coresize-1; /* size of core, size of core - 1 */
  insn_t* const CoreEnd = coreptr + coresize; // point after last instruction
  insn_t* const CoreEnd1 = CoreEnd - 1; // point to last instruction
  int cycles = core->NWarriors * core->Cycles; /* set instruction executions until tie counter */
  int alive_cnt = core->NWarriors;
  int max_alive_proc = core->NWarriors * core->Processes;
  insn_t **pofs = queue_end-1;

#if DEBUG >= 1
  insn_t insn;			/* used for disassembly */
  char debug_line[256];		/* ditto */
#endif


	core->War_Tab[0].succ = &core->War_Tab[core->NWarriors-1];
	core->War_Tab[core->NWarriors-1].pred = &core->War_Tab[0];
	{
	u32_t ftmp = 0;		/* temps */
		
	do {
		int t = core->NWarriors-1-ftmp;
		if ( t > 0 ) core->War_Tab[t].succ = &(core->War_Tab[t-1]);
		if ( t < core->NWarriors-1 ) core->War_Tab[t].pred = &(core->War_Tab[t+1]);
		pofs -= core->Processes;
		*pofs = &(coreptr[war_pos_tab[ftmp]]);
		core->War_Tab[t].head = pofs;
		core->War_Tab[t].tail = pofs+1;
		core->War_Tab[t].nprocs = 1;
		core->War_Tab[t].id = ftmp;
		ftmp++;
	} while ( ftmp < core->NWarriors );
	}
	
	/*******************************************************************
	 * Main loop - optimize here
	 */
	w = &core->War_Tab[ core->NWarriors-1 ];
	do {
		/* 'in' field of current insn for decoding */
		u32_t in;

		/* A register values */
		u32_t ra_a, ra_b;

		/* B register values */
		u32_t rb_a, rb_b;

		insn_t *pta;
		insn_t *ptb;
		unsigned int mode;

		insn_t* ip = *(w->head);
		if ( ++(w->head) == queue_end ) w->head = queue_start;
		in = ip->in;		/* note: flags must be unset! */
#if !SIM_STRIP_FLAGS
		in = in & iMASK;		/* strip flags. */
#endif
		rb_a = ra_a = ip->a;
		rb_b = ip->b;

#if DEBUG >= 1
		insn = *ip;
		dis1( debug_line, insn, coresize);
#endif
		
		mode = in & mMASK;
		
		/* a-mode calculation */
		if (mode == IMMEDIATE) {
			/*printf("IMMEDIATE\n");*/
			ra_b = rb_b;
			pta = ip;
		} else if (mode == DIRECT) {
			/*printf("DIRECT\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;
			ra_b = pta->b;
		} else if (mode == BINDIRECT) {
			/*printf("BINDIRECT\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			pta = pta + pta->b; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
		} else if (mode == APOSTINC) {
			/*printf("APOSTINC\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			{field_t* f = &(pta->a);
			pta = pta + pta->a; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
			INCMOD(*f);}
		} else if (mode == BPOSTINC) {
			/*printf("BPOSTINC\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			{field_t* f = &(pta->b);
			pta = pta + pta->b; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
			INCMOD(*f);}
		} else if (mode == APREDEC) {
			/*printf("APREDEC\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			DECMOD(pta->a);
			pta = pta + pta->a; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
		} else if (mode == BPREDEC) {
			/*printf("BPREDEC\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			DECMOD(pta->b);
			pta = pta + pta->b; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
		} else { /* AINDIRECT */
			/*printf("AINDIRECT\n");*/
			pta = ip + ra_a; if (pta >= CoreEnd) pta -= coresize;
			pta = pta + pta->a; if (pta >= CoreEnd) pta -= coresize;
			ra_a = pta->a;		/* read in registers */
			ra_b = pta->b;
		}
	
		mode = in & (mMASK<<mBITS);

		/* special mov.i code to improve performance */
		if ((in & 16320) == (_OP(MOV, mI) << (mBITS*2))) {
			if (mode == APREDEC<<mBITS) {
				/*++modes[0];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				DECMOD(ptb->a);
				ptb = ptb + ptb->a; if (ptb >= CoreEnd) ptb -= coresize;
			} else if (mode == DIRECT<<mBITS) {
				/*++modes[1];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			} else if (mode == APOSTINC<<mBITS) {
				/*++modes[2];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				{field_t* f = &(ptb->a);
				ptb = ptb + *f; if (ptb >= CoreEnd) ptb -= coresize;
				INCMOD(*f);}
			} else if (mode == BPREDEC<<mBITS) {
				/*++modes[3];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				DECMOD(ptb->b);
				ptb = ptb + ptb->b; if (ptb >= CoreEnd) ptb -= coresize;
			} else if (mode == IMMEDIATE<<mBITS) {
				/*++modes[4];*/
				ptb = ip;
			} else if (mode == BPOSTINC<<mBITS) {
				/*++modes[5];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				{field_t* f = &(ptb->b);
				ptb = ptb + *f; if (ptb >= CoreEnd) ptb -= coresize;
				INCMOD(*f);}
			} else if (mode == BINDIRECT<<mBITS) {
				/*++modes[6];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				ptb = ptb + ptb->b; if (ptb >= CoreEnd) ptb -= coresize;
			} else { /* AINDIRECT */
				/*++modes[7];*/
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				ptb = ptb + ptb->a; if (ptb >= CoreEnd) ptb -= coresize;
			}
			ptb->a = ra_a;
			ptb->b = ra_b;
			ptb->in = pta->in;
			IPINCMOD(ip);
			queue(ip);
			goto noqueue;
		}
		
		/*15360: 
		 *              0  0  1  1  1  1  0  0  0  0  0  0  0  0  0  0
		 * bit         15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
		 * field   | flags | |- op-code  -| |-.mod-| |b-mode| |a-mode|
		 */
		if (!(in & 15360)) {
			if (mode == IMMEDIATE<<mBITS) {
			} else if (mode == DIRECT<<mBITS) {
			} else if (mode == BPOSTINC<<mBITS) {
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				INCMOD(ptb->b);
			} else if (mode == BPREDEC<<mBITS) {
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				DECMOD(ptb->b);
			} else if (mode == APREDEC<<mBITS) {
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				DECMOD(ptb->a);
			} else if (mode == APOSTINC<<mBITS) {
				ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
				INCMOD(ptb->a);
			} /* BINDIRECT, AINDIRECT */
			
			if (in & 512) {
			spl:
				IPINCMOD(ip);
				queue(ip);
				if ( w->nprocs < core->Processes ) {
					++w->nprocs;
					queue(pta);
				}
				/* in the endgame, check if a tie is inevitable */
				if (cycles < max_alive_proc) {
					w_t* w_iterator = w->succ;
				
					/* break if all warriors have more processes than cycles */
					while ((w_iterator->nprocs * alive_cnt > cycles) && (w_iterator != w)) w_iterator = w_iterator->succ;
						if (w_iterator->nprocs*alive_cnt  > cycles) {
						/*printf("stopping at %d\n", cycles);*/
						goto out;
					}
				}
			}
			else {
			die:
				if (--w->nprocs) goto noqueue;
				w->pred->succ = w->succ;
				w->succ->pred = w->pred;
				*death_tab++ = w->id;
				cycles = cycles - cycles/alive_cnt; /* nC+k -> (n-1)C+k */
				max_alive_proc = alive_cnt * core->Processes;
				if ( --alive_cnt <= 1 ) 
					goto out;
			}
			goto noqueue;
		}

		
		/* b-mode calculation */
		if (mode == APREDEC<<mBITS) {
			/*printf("APREDEC\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			DECMOD(ptb->a);
			ptb = ptb + ptb->a; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
		} else if (mode == DIRECT<<mBITS) {
			/*printf("DIRECT\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;
			rb_b = ptb->b;
		} else if (mode == APOSTINC<<mBITS) {
			/*printf("APOSTINC\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			{field_t* f = &(ptb->a);
			ptb = ptb + ptb->a; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
			INCMOD(*f);}
		} else if (mode == BPREDEC<<mBITS) {
			/*printf("BPREDEC\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			DECMOD(ptb->b);
			ptb = ptb + ptb->b; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
		} else if (mode == IMMEDIATE<<mBITS) {
			/*printf("IMMEDIATE\n");*/
			ptb = ip;
		} else if (mode == BPOSTINC<<mBITS) {
			/*printf("BPOSTINC\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			{field_t* f = &(ptb->b);
			ptb = ptb + ptb->b; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
			INCMOD(*f);}
		} else if (mode == BINDIRECT<<mBITS) {
			/*printf("BINDIRECT\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			ptb = ptb + ptb->b; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
		} else { /* AINDIRECT */
			/*printf("AINDIRECT\n");*/
			ptb = ip + rb_b; if (ptb >= CoreEnd) ptb -= coresize;
			ptb = ptb + ptb->a; if (ptb >= CoreEnd) ptb -= coresize;
			rb_a = ptb->a;		/* read in registers */
			rb_b = ptb->b;
		}
	
#if DEBUG == 2
    /* Debug output */
    printf("%6d %4ld  %s  |%4ld, d %4ld,%4ld a %4ld,%4ld b %4ld,%4ld\n",
	   cycles, ip-core, debug_line,
	   w->nprocs, pta-core, ptb-core, 
	   ra_a, ra_b, rb_a, rb_b );
#endif

    /*
     * Execute the instruction on opcode.modifier
     */

		
    switch ( in>>(mBITS*2) ) {

    case _OP(MOV, mA):
      ptb->a = ra_a;
      break;
    case _OP(MOV, mF):
      ptb->a = ra_a;
    case _OP(MOV, mB):
      ptb->b = ra_b;
      break;
    case _OP(MOV, mAB):
      ptb->b = ra_a;
      break;
    case _OP(MOV, mX):
      ptb->b = ra_a;
    case _OP(MOV, mBA):
      ptb->a = ra_b;
      break;
    
    case _OP(MOV, mI):
	    printf("unreachable code reached. You have a problem!\n");
	    break;

    case _OP(DJN,mBA):
    case _OP(DJN,mA):
      DECMOD(ptb->a);
      if ( rb_a == 1 ) break;
      queue(pta);
      goto noqueue;

    case _OP(DJN,mAB):
    case _OP(DJN,mB):
      DECMOD(ptb->b);
      if ( rb_b == 1 ) break;
      queue(pta);
      goto noqueue;

    case _OP(DJN,mX):
    case _OP(DJN,mI):
    case _OP(DJN,mF):
      DECMOD(ptb->a);
      DECMOD(ptb->b);
      if ( rb_a == 1 && rb_b == 1 ) break;
      queue(pta);
      goto noqueue;


    case _OP(ADD, mI):
    case _OP(ADD, mF):
      ADDMOD(ptb->b, ra_b, rb_b );
    case _OP(ADD, mA):
      ADDMOD(ptb->a, ra_a, rb_a );
      break;
    case _OP(ADD, mB):
      ADDMOD(ptb->b, ra_b, rb_b );
      break;
    case _OP(ADD, mX):
      ADDMOD(ptb->a, ra_b, rb_a );
    case _OP(ADD, mAB):
      ADDMOD(ptb->b, ra_a, rb_b );
      break;
    case _OP(ADD, mBA):
      ADDMOD(ptb->a, ra_b, rb_a );
      break;


    case _OP(JMZ, mBA):
    case _OP(JMZ, mA):
      if ( rb_a )
	break;
      queue(pta);
      goto noqueue;

    case _OP(JMZ, mAB):
    case _OP(JMZ, mB):
      if ( rb_b )
	break;
      queue(pta);
      goto noqueue;

    case _OP(JMZ, mX):
    case _OP(JMZ, mF):
    case _OP(JMZ, mI):
      if ( rb_a || rb_b )
	break;
      queue(pta);
      goto noqueue;


    case _OP(SUB, mI):
    case _OP(SUB, mF):
      SUBMOD(ptb->b, rb_b, ra_b );
    case _OP(SUB, mA):
      SUBMOD(ptb->a, rb_a, ra_a);
      break;
    case _OP(SUB, mB):
      SUBMOD(ptb->b, rb_b, ra_b );
      break;
    case _OP(SUB, mX):
      SUBMOD(ptb->a, rb_a, ra_b );
    case _OP(SUB, mAB):
      SUBMOD(ptb->b, rb_b, ra_a );
      break;
    case _OP(SUB, mBA):
      SUBMOD(ptb->a, rb_a, ra_b );
      break;


    case _OP(SEQ, mA):
      if ( ra_a == rb_a )
	IPINCMOD(ip);
      break;
    case _OP(SEQ, mB):
      if ( ra_b == rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SEQ, mAB):
      if ( ra_a == rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SEQ, mBA):
      if ( ra_b == rb_a )
	IPINCMOD(ip);
      break;

    case _OP(SEQ, mI):
      if ( pta->in != ptb->in )
	break;
    case _OP(SEQ, mF):
      if ( ra_a == rb_a && ra_b == rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SEQ, mX):
      if ( ra_a == rb_b && ra_b == rb_a )
	IPINCMOD(ip);
      break;


    case _OP(SNE, mA):
      if ( ra_a != rb_a )
	IPINCMOD(ip);
      break;
    case _OP(SNE, mB):
      if ( ra_b != rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SNE, mAB):
      if ( ra_a != rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SNE, mBA):
      if ( ra_b != rb_a )
	IPINCMOD(ip);
      break;

    case _OP(SNE, mI):
      if ( pta->in != ptb->in ) {
	IPINCMOD(ip);
	break;
      }
      /* fall through */
    case _OP(SNE, mF):
      if ( ra_a != rb_a || ra_b != rb_b )
	IPINCMOD(ip);
      break;
    case _OP(SNE, mX):
      if ( ra_a != rb_b || ra_b != rb_a )
	IPINCMOD(ip);
      break;


    case _OP(JMN, mBA):
    case _OP(JMN, mA):
      if (! rb_a )
	break;
      queue(pta);
      goto noqueue;

    case _OP(JMN, mAB):
    case _OP(JMN, mB):
      if (! rb_b )
	break;
      queue(pta);
      goto noqueue;

    case _OP(JMN, mX):
    case _OP(JMN, mF):
    case _OP(JMN, mI):
      if (rb_a || rb_b) {
        queue(pta);
        goto noqueue;
      }
      break;


    case _OP(JMP, mA):
    case _OP(JMP, mB):
    case _OP(JMP, mAB):
    case _OP(JMP, mBA):
    case _OP(JMP, mX):
    case _OP(JMP, mF):
    case _OP(JMP, mI):
      queue(pta);
      goto noqueue;



    case _OP(SLT, mA):
      if (ra_a < rb_a)
	IPINCMOD(ip);
      break;
    case _OP(SLT, mAB):
      if (ra_a < rb_b)
	IPINCMOD(ip);
      break;
    case _OP(SLT, mB):
      if (ra_b < rb_b)
	IPINCMOD(ip);
      break;
    case _OP(SLT, mBA):
      if (ra_b < rb_a)
	IPINCMOD(ip);
      break;
    case _OP(SLT, mI):
    case _OP(SLT, mF):
      if (ra_a < rb_a && ra_b < rb_b)
	IPINCMOD(ip);
      break;
    case _OP(SLT, mX):
      if (ra_a < rb_b && ra_b < rb_a)
	IPINCMOD(ip);
      break;


    case _OP(MODM, mI):
    case _OP(MODM, mF):
      if ( ra_a ) ptb->a = rb_a % ra_a;
      if ( ra_b ) ptb->b = rb_b % ra_b;
      if (!ra_a || !ra_b) goto die;
      break;
    case _OP(MODM, mX):
      if ( ra_b ) ptb->a = rb_a % ra_b;
      if ( ra_a ) ptb->b = rb_b % ra_a;
      if (!ra_b || !ra_a) goto die;
      break;
    case _OP(MODM, mA):
      if ( !ra_a ) goto die;
      ptb->a = rb_a % ra_a;
      break;
    case _OP(MODM, mB):
      if ( !ra_b ) goto die;
      ptb->b = rb_b % ra_b;
      break;
    case _OP(MODM, mAB):
      if ( !ra_a ) goto die;
      ptb->b = rb_b % ra_a;
      break;
    case _OP(MODM, mBA):
      if ( !ra_b ) goto die;
      ptb->a = rb_a % ra_b;
      break;


    case _OP(MUL, mI):
    case _OP(MUL, mF):
      ptb->b = (rb_b * ra_b) % coresize;
    case _OP(MUL, mA):
      ptb->a = (rb_a * ra_a) % coresize;
      break;
    case _OP(MUL, mB):
      ptb->b = (rb_b * ra_b) % coresize;
      break;
    case _OP(MUL, mX):
      ptb->a = (rb_a * ra_b) % coresize;
    case _OP(MUL, mAB):
      ptb->b = (rb_b * ra_a) % coresize;
      break;
    case _OP(MUL, mBA):
      ptb->a = (rb_a * ra_b) % coresize;
      break;


    case _OP(DIV, mI):
    case _OP(DIV, mF):
      if ( ra_a ) ptb->a = rb_a / ra_a;
      if ( ra_b ) ptb->b = rb_b / ra_b;
      if (!ra_a || !ra_b) goto die;
      break;
    case _OP(DIV, mX):
      if ( ra_b ) ptb->a = rb_a / ra_b;
      if ( ra_a ) ptb->b = rb_b / ra_a;
      if (!ra_b || !ra_a) goto die;
      break;
    case _OP(DIV, mA):
      if ( !ra_a ) goto die;
      ptb->a = rb_a / ra_a;
      break;
    case _OP(DIV, mB):
      if ( !ra_b ) goto die;
      ptb->b = rb_b / ra_b;
      break;
    case _OP(DIV, mAB):
      if ( !ra_a ) goto die;
      ptb->b = rb_b / ra_a;
      break;
    case _OP(DIV, mBA):
      if ( !ra_b ) goto die;
      ptb->a = rb_a / ra_b;
      break;


    case _OP(NOP,mI):
    case _OP(NOP,mX):
    case _OP(NOP,mF):
    case _OP(NOP,mA):
    case _OP(NOP,mAB):
    case _OP(NOP,mB):
    case _OP(NOP,mBA):
      break;

    case _OP(LDP,mA):
      ptb->a = UNSAFE_PSPACE_GET(w->id, ra_a % core->PSpace_size);
      break;
    case _OP(LDP,mAB):
      ptb->b = UNSAFE_PSPACE_GET(w->id, ra_a % core->PSpace_size);
      break;
    case _OP(LDP,mBA):
      ptb->a = UNSAFE_PSPACE_GET(w->id, ra_b % core->PSpace_size);
      break;
    case _OP(LDP,mF):
    case _OP(LDP,mX):
    case _OP(LDP,mI):
    case _OP(LDP,mB):
      ptb->b = UNSAFE_PSPACE_GET(w->id, ra_b % core->PSpace_size);
      break;

    case _OP(STP,mA):
      UNSAFE_PSPACE_SET(w->id, rb_a % core->PSpace_size, ra_a);
      break;
    case _OP(STP,mAB):
      UNSAFE_PSPACE_SET(w->id, rb_b % core->PSpace_size, ra_a);
      break;
    case _OP(STP,mBA):
      UNSAFE_PSPACE_SET(w->id, rb_a % core->PSpace_size, ra_b);
      break;
    case _OP(STP,mF):
    case _OP(STP,mX):
    case _OP(STP,mI):
    case _OP(STP,mB):
      UNSAFE_PSPACE_SET(w->id, rb_b % core->PSpace_size, ra_b);
      break;

#if DEBUG > 0
    default:
      alive_cnt = -1;
      goto out;
#endif
    }

    IPINCMOD(ip);
    queue(ip);
  noqueue:
    w = w->succ;
  } while(--cycles > 0);

 out:
#if DEBUG == 2
  printf("cycles: %d\n", cycles);
#endif
  
  return alive_cnt;
}