#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),
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; }