1 /* sim.c: simulator functions
2  * $Id: sim.c,v 1.2 2003/09/04 15:44:24 varfar Exp $
3  */
4 
5 /* This file is part of `exhaust', a memory array redcode simulator.
6  * Author: M Joonas Pihlaja
7  * Public Domain.
8  */
9 
10 /*
11  * Thanks go to the pMARS authors and Ken Espiritu whose ideas have
12  * been used in this simulator.  Especially Ken's effective addressing
13  * calculation code in pMARS 0.8.6 has been adapted for use here.
14  */
15 
16 #define FOLDCHECK(x) if(coresize1 < x) panic("foldcheck");
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "exhaust.h"
23 #include "asm.h"
24 #include "sim.h"
25 #include "insn.h"
26 
27 /* Should we strip flags from instructions when loading?  By default,
28    yes.  If so, then the simulator won't bother masking them off.  */
29 #ifndef SIM_STRIP_FLAGS
30 #define SIM_STRIP_FLAGS 1
31 #endif
32 
33 
34 /* DEBUG level:
35  *     0: none
36  *   >=1: disassemble each instruction (no output)
37  *     2: print each instruction as it is executed
38  */
39 
40 /*
41  * File scoped stuff
42  */
43 
44 /* internal warrior structure */
45 typedef struct w_st {
46   field_t *tail;		/* next free location to queue a process */
47   field_t *head;		/* next process to run from queue */
48   struct w_st *succ;		/* next warrior alive */
49   u32_t nprocs;			/* number of live processes in this warrior */
50   struct w_st *pred;		/* previous warrior alive */
51   int id;			/* index (or identity) of warrior */
52 } w_t;
53 
54 #define DEF_MAX_WARS 2
55 #define DEF_CORESIZE 8000
56 #define DEF_PROCESSES 8000
57 #define DEF_CYCLES 80000
58 
59 static unsigned int Coresize  = 0;
60 static unsigned int Processes = 0;
61 static unsigned int NWarriors = 0;
62 static unsigned int Cycles    = 0;
63 
64 static w_t          *War_Tab = NULL;
65 static insn_t       *Core_Mem = NULL;
66 static field_t      *Queue_Mem = NULL;
67 
68 /* P-space */
69 static unsigned int PSpace_size = 0;    /* # p-space slots per warrior. */
70 static pspace_t	    **PSpaces;	        /* p-spaces of each warrior. */
71 
72 /* protos */
73 static int sim_proper( unsigned int, const field_t *, unsigned int * );
74 static void alloc_pspaces( unsigned int nwars, unsigned int pspacesize );
75 static void free_pspaces( unsigned int nwars );
76 
77 static const int OPCODE_COUNT = _OP(OPCODE_LAST,MODIFIER_LAST)+1;
78 static unsigned char *exec_trail = NULL;
79 static unsigned long long *opcode_count;
80 static unsigned exec_trail_checksum;
81 static unsigned exec_trail_length;
82 
get_opcode_count(const char in)83 unsigned long long get_opcode_count(const char in) { return opcode_count[in]; }
84 static unsigned EXEC_TRAIL_LEN = 0;
get_exec_trail_checksum()85 unsigned get_exec_trail_checksum() { return exec_trail_checksum; }
clear_exec_trail()86 static void clear_exec_trail() {	exec_trail_length = 0; }
get_exec_trail_length()87 unsigned get_exec_trail_length() { return exec_trail_length; }
get_exec_trail(unsigned i)88 unsigned char get_exec_trail(unsigned i) { return exec_trail[i]; }
89 
opcode_panic(char * context,unsigned char in)90 static void opcode_panic(char *context,unsigned char in) {
91 	printf("\t%s opcode %hhi (%hhi.%hhi) > %i\t",context,in,(in >> moBITS),(in & moMASK),OPCODE_COUNT);
92 	panic("x1");
93 }
94 
append_to_exec_trail(unsigned char in)95 static void append_to_exec_trail(unsigned char in) {
96 	if(in >= OPCODE_COUNT) opcode_panic("exec_trail\'ed",in);
97 	if(exec_trail_length >= EXEC_TRAIL_LEN) {
98 		printf("\topcode %hhi (%hhi.%hhi) > %i\t",in,(in >> moBITS),(in & moMASK),OPCODE_COUNT);
99 		printf("exec_trail_length(%u) >= EXEC_TRAIL_LEN(%u)\n",exec_trail_length,EXEC_TRAIL_LEN);
100 		panic("x2");
101 	}
102 	opcode_count[in]++;
103 	exec_trail_checksum += in;
104 	exec_trail[exec_trail_length++] = in;
105 }
106 
107 
108 /*---------------------------------------------------------------
109  * Simulator memory management
110  */
111 
112 void
sim_clear_core()113 sim_clear_core()
114 {
115   memset(Core_Mem, 0, Coresize*sizeof(insn_t));
116 }
117 
118 
119 /* NAME
120  *     sim_alloc_bufs, sim_alloc_bufs2, sim_free_bufs --
121  *				alloc and free buffers used in simulation
122  *
123  * SYNOPSIS
124  *     insn_t *sim_alloc_bufs( unsigned int nwars, unsigned int coresize,
125  *                             unsigned int processes, unsigned int cycles );
126  *     insn_t *sim_alloc_bufs2( unsigned int nwars, unsigned int coresize,
127  *				unsigned int processes, unsigned int cycles,
128  *				unsigned int pspacesize );
129  *     void sim_free_bufs();
130  *
131  * INPUTS
132  *     nwar        -- number of warriors
133  *     coresize    -- size of core
134  *     processes   -- max no of processes / warrior
135  *     cycles      -- the number of cycles to play before tie.
136  *     pspacesize  -- size of p-space per warrior.  For sim_alloc_bufs(),
137  *		      it defaults to min(1,coresize/16).
138  *
139  * RESULTS
140  *     These functions manage the core, queue, and w_t warrior info
141  *     struct array memories.
142  *
143  *     Core_Mem, Queue_Mem, War_Tab and PSpace_mem memories are allocated
144  *     or freed as requested.  Any earlier memories are freed before
145  *     new allocations are made.
146  *
147  * RETURN VALUE
148  *     sim_alloc_bufs(): the address of core memory, or NULL if
149  *			 out of memory.
150  *     sim_free_bufs(): none
151  *
152  * GLOBALS
153  *     All file scoped globals.
154  */
155 
156 void
sim_free_bufs()157 sim_free_bufs()
158 {
159   free_pspaces(NWarriors);
160   if ( Core_Mem ) free( Core_Mem ); Core_Mem = NULL; Coresize = 0;
161   if ( Queue_Mem ) free( Queue_Mem ); Queue_Mem = NULL; Processes = 0;
162   if ( War_Tab ) free( War_Tab ); War_Tab = NULL; NWarriors = 0;
163 }
164 
165 
166 insn_t *
sim_alloc_bufs2(unsigned int nwars,unsigned int coresize,unsigned int processes,unsigned int cycles,unsigned int pspace)167 sim_alloc_bufs2( unsigned int nwars, unsigned int coresize,
168 		 unsigned int processes, unsigned int cycles,
169 		 unsigned int pspace )
170 {
171   unsigned int queue_size;
172 
173   sim_free_bufs();
174 
175   Core_Mem = (insn_t*)malloc( sizeof(insn_t) * coresize );
176   queue_size = nwars*processes+1;
177   Queue_Mem = (field_t*)malloc( sizeof(field_t)*queue_size );
178   War_Tab = (w_t*)malloc( sizeof(w_t)*nwars );
179 
180   EXEC_TRAIL_LEN = (sizeof(unsigned char)*cycles*2)+2;
181   exec_trail = (unsigned char*)malloc(EXEC_TRAIL_LEN);
182   opcode_count = (unsigned long long*)calloc(OPCODE_COUNT,sizeof(unsigned long long));
183   exec_trail_checksum = 0;
184 
185   alloc_pspaces(nwars, pspace);
186 
187   if ( Core_Mem && Queue_Mem && War_Tab && PSpaces ) {
188     Cycles = cycles;
189     NWarriors = nwars;
190     Coresize = coresize;
191     Processes = processes;
192     sim_clear_pspaces();
193     return Core_Mem;
194   }
195   sim_free_bufs();
196   return NULL;
197 }
198 
199 insn_t *
sim_alloc_bufs(unsigned int nwars,unsigned int coresize,unsigned int processes,unsigned int cycles)200 sim_alloc_bufs( unsigned int nwars, unsigned int coresize,
201 		unsigned int processes, unsigned int cycles )
202 {
203   unsigned int pspace;
204   pspace = coresize/16 == 0 ? 1 : coresize/16;
205   return sim_alloc_bufs2( nwars, coresize, processes, cycles, pspace );
206 }
207 
208 
209 /* NAME
210  *     sim_load_warrior -- load warrior code into core.
211  *
212  * SYNOPSIS
213  *     sim_load_warrior(unsigned int pos, insn_t *code, unsigned int len);
214  *
215  * INPUTS
216  *     pos -- The core address to load the warrior into.
217  *     code -- array of instructions.
218  *     len --
219  *
220  * DESCRIPTION
221  *     This function is the preferred method to load warriors into core.
222  *     It strips the instructions of any flags they may possess, and
223  *     copies the instructions into core.
224  *
225  *     The code will happily overwrite any previous contents of core,
226  *     so beware not to load warriors so that their code overlaps.
227  *
228  * NOTE
229  *     The core must have been allocated previously with sim(), or
230  *     preferably sim_alloc_bufs() and not freed since.
231  *
232  * RETURN VALUE
233  *     0 -- warrior loaded OK.
234  *    -1 -- core memory not allocated.
235  *    -2 -- warrior length > core size.
236  */
237 int
sim_load_warrior(unsigned int pos,const insn_t * code,unsigned int len)238 sim_load_warrior(unsigned int pos, const insn_t *code, unsigned int len)
239 {
240   unsigned int i;
241   field_t k;
242   u32_t in;
243 
244   if ( Core_Mem == NULL )  return -1;
245   if ( len > Coresize ) return -2;
246 
247   for (i=0; i<len; i++) {
248     k = (pos+i) % Coresize;
249 
250 #if SIM_STRIP_FLAGS
251     in = code[i].in & iMASK;
252 #else
253     in = code[i].in;
254 #endif
255 
256     Core_Mem[k].in = in;
257     Core_Mem[k].a = code[i].a;
258     Core_Mem[k].b = code[i].b;
259   }
260   return 0;
261 }
262 
263 
264 
265 
266 /*---------------------------------------------------------------
267  * P-Space management.
268  */
269 
270 static void
free_pspaces(unsigned int nwars)271 free_pspaces(unsigned int nwars)
272 {
273   unsigned int i;
274   if ( nwars>0 ) {
275     if (PSpaces) {
276       for (i=0; i<nwars; i++) {
277 	pspace_free(PSpaces[i]);
278       }
279       free(PSpaces);
280     }
281   }
282   PSpace_size = 0;
283   PSpaces = NULL;
284 }
285 
286 
287 static void
alloc_pspaces(unsigned int nwars,unsigned int pspacesize)288 alloc_pspaces(unsigned int nwars, unsigned int pspacesize)
289 {
290   unsigned int i;
291   int success = 0;
292 
293   PSpaces = NULL;
294   PSpace_size = 0;
295   if (nwars==0) { return; }
296 
297   if (( PSpaces = (pspace_t**)malloc(sizeof(pspace_t*)*nwars))) {
298     success = 1;
299     for (i=0; i<nwars; i++) { PSpaces[i] = NULL; }
300     for (i=0; success && i<nwars; i++) {
301 	PSpaces[i] = pspace_alloc(pspacesize);
302 	success = success && PSpaces[i] != NULL;
303     }
304   }
305 
306   if ( !success ) {
307     free_pspaces(nwars);
308   } else {
309     PSpace_size = pspacesize;
310   }
311 }
312 
313 
314 /* NAME
315  *     sim_get_pspaces -- get array of p-spaces of warriors.
316  *     sim_get_pspace -- get a single p-space.
317  *
318  * SYNOPSIS
319  *     pspace_t **sim_get_pspaces(void);
320  *     pspace_t *sim_get_pspace(unsigned int war_id)
321  *
322  * DESCRIPTION
323  *     Return an array of pointers to p-space structures of the warriors.
324  *     The pspace at index i is used as the pspace of the ith warrior
325  *     when fighting.
326  */
327 pspace_t **
sim_get_pspaces()328 sim_get_pspaces()
329 {
330     return PSpaces;
331 }
332 
333 pspace_t *
sim_get_pspace(unsigned int war_id)334 sim_get_pspace(unsigned int war_id)
335 {
336     return PSpaces[war_id];
337 }
338 
339 /* NAME
340  *     sim_clear_pspaces -- clear and/or reinitialise p-spaces
341  *     sim_reset_pspaces
342  *
343  * SYNOPSIS
344  *     void sim_clear_pspaces(void);
345  *     void sim_reset_pspaces(void);
346  *
347  * DESCRIPTION
348  *	All p-spaces are cleared and the P-space locations 0 are set
349  *	to CORESIZE-1.  For sim_reset_pspaces(): All p-spaces are made
350  *	private.
351  * */
352 
353 void
sim_clear_pspaces()354 sim_clear_pspaces()
355 {
356   unsigned int i;
357   for (i=0; i<NWarriors; i++) {
358     pspace_clear(PSpaces[i]);
359     pspace_set(PSpaces[i], 0, Coresize-1);
360   }
361 }
362 
363 void
sim_reset_pspaces()364 sim_reset_pspaces()
365 {
366   unsigned int i;
367   for (i=0; i<NWarriors; i++) {
368     pspace_privatise(PSpaces[i]);
369   }
370   sim_clear_pspaces();
371 }
372 
373 
374 
375 /*---------------------------------------------------------------
376  * Simulator interface
377  */
378 
379 /* NAME
380  *     sim, sim_mw -- public functions to simulate a round of Core War
381  *
382  * SYNOPSIS
383  *     int sim_mw( unsigned int nwar, const field_t *war_pos_tab,
384  *                 unsigned int *death_tab );
385  *     int sim( int nwar, field_t w1_start, field_t w2_start,
386  * 		unsigned int cycles, void **ptr_result );
387  *
388  * INPUTS
389  *     nwar        -- number of warriors
390  *     w1_start, w2_start -- core addresses of first processes
391  *                    warrior 1 and warrior 2. Warrior 1 executes first.
392  *     cycles      -- the number of cycles to play before tie.
393  *     ptr_result  -- NULL, except when requesting the address of core.
394  *     war_pos_tab -- core addresses where warriors are loaded in
395  *		      the order they are to be executed.
396  *     death_tab   -- the table where dead warrior indices are stored
397  *
398  * DESCRIPTION
399  *     The real simulator is inside sim_proper() to which sim() and
400  *     sim_mw() are proxies.  sim_mw() reads the warrior position
401  *     of the ith warrior from war_tab_pos[i-1].
402  *
403  * RESULTS
404  *     The warriors fight their fight in core which gets messed up in
405  *     the process.  If a warrior died during the fight then its p-space
406  *     location 0 is cleared.  Otherwise the number of warriors alive
407  *     at the end of the battle is stored into its p-space location 0.
408  *
409  *     sim_mw() stores indices of warriors that die into the death_tab
410  *     array in the order of death.  Warrior indices start from 0.
411  *
412  *     For sim(): If nwar == -1 then buffers of default size for
413  *     max. two warriors are allocated and the address of the core
414  *     memory is returned via the ptr_result pointer.
415  *
416  * RETURN VALUE
417  *     sim_mw(): the number of warriors still alive at the end of the
418  *		 battle.
419  *       -1: simulator panic attack -- something's gone wrong
420  *
421  *     sim():
422  *       single warrior: 0: warrior suicided, 1: warrior didn't die.
423  *       one-on-one two warriors:
424  * 	      0: warrior 1 won, 1: warrior 2 won, 2: tie
425  *       -1: simulator panic attack -- something's gone wrong
426  *
427  * GLOBALS
428  *     All file scoped globals */
429 
430 int
sim_mw(unsigned int nwar,const field_t * war_pos_tab,unsigned int * death_tab)431 sim_mw( unsigned int nwar, const field_t *war_pos_tab,
432 	unsigned int *death_tab )
433 {
434   int alive_count;
435   if ( !Core_Mem || !Queue_Mem || !War_Tab || !PSpaces ) return -1;
436 
437   alive_count = sim_proper( nwar, war_pos_tab, death_tab );
438 
439   /* Update p-space locations 0. */
440   if (alive_count >= 0) {
441     unsigned int nalive = alive_count;
442     unsigned int i;
443 
444     for (i=0; i<nwar; i++) {
445       pspace_set( PSpaces[i], 0, nalive);
446     }
447     for (i=0; i<nwar-nalive; i++) {
448       pspace_set( PSpaces[death_tab[i]], 0, 0);
449     }
450   }
451   return alive_count;
452 }
453 
454 
455 int
sim(int nwar,field_t w1_start,field_t w2_start,unsigned int cycles,void ** ptr_result)456 sim( int nwar,
457      field_t w1_start,
458      field_t w2_start,
459      unsigned int cycles,
460      void **ptr_result )
461 {
462   field_t war_pos_tab[2];
463   unsigned int death_tab[2];
464   int alive_cnt;
465 
466   /* if the caller requests for the address of core, allocate
467    * the default buffers and give it
468    */
469   if ( nwar < 0 ) {
470     if ( nwar == -1 && ptr_result ) {
471       *ptr_result = sim_alloc_bufs( DEF_MAX_WARS, DEF_CORESIZE,
472 				    DEF_PROCESSES, DEF_CYCLES );
473       return 0;
474     }
475     return -1;
476   }
477   if ( nwar > 2 ) return -1;
478 
479   /* otherwise set up things for sim_mw() */
480   Cycles = cycles;
481   war_pos_tab[0] = w1_start;
482   war_pos_tab[1] = w2_start;
483 
484   alive_cnt = sim_mw( nwar, war_pos_tab, death_tab );
485   if ( alive_cnt < 0 ) return -1;
486 
487   if ( nwar == 1) return alive_cnt;
488 
489   if ( alive_cnt == 2 ) return 2;
490   return death_tab[0] == 0 ? 1 : 0;
491 }
492 
493 
494 
495 /*-------------------------------------------------------------------------
496  * private functions
497  */
498 
499 /* NAME
500  *     sim_proper -- the real simulator code
501  *
502  * SYNOPSIS
503  *     int sim_proper( unsigned int nwar,
504  *                     const field_t *war_pos_tab,
505  *                     unsigned int *death_tab );
506  *
507  * INPUTS
508  *     nwar        -- number of warriors
509  *     war_pos_tab -- core addresses where warriors are loaded in
510  *		      the order they are to be executed.
511  *     death_tab   -- the table where dead warrior indices are stored
512  *
513  * RESULTS
514  *     The warriors fight their fight in core which gets messed up in
515  *     the process.  The indices of warriors that die are stored into
516  *     the death_tab[] array in the order of death.  Warrior indices
517  *     start from 0.
518  *
519  * RETURN VALUE
520  *     The number of warriors still alive at the end of the
521  *     battle or -1 on an anomalous condition.
522  *
523  * GLOBALS
524  *     All file scoped globals
525  */
526 
527 /* Various macros:
528  *
529  *  queue(x): Inserts a core address 'x' to the head of the current
530  *            warrior's process queue.  Assumes the warrior's
531  * 	      tail pointer is inside the queue buffer.
532  *
533  * x, y must be in 0..coresize-1 for the following macros:
534  *
535  * INCMOD(x): x = x+1 mod coresize
536  * DECMOD(x): x = x-1 mod coresize
537  * ADDMOD(z,x,y): z = x+y mod coresize
538  * SUBMOD(z,x,y): z = x-y mod coresize
539  */
540 
541 #define queue(x)  do { *w->tail++ = (x); if ( w->tail == queue_end )\
542                                           w->tail = queue_start; } while (0)
543 
544 #define INCMOD(x) do { if ( ++(x) == coresize ) (x) = 0; } while (0)
545 #define DECMOD(x) do { if ((x)-- == 0) (x) = coresize1; } while (0)
546 #define ADDMOD(z,x,y) do { (z) = (x)+(y); if ((z)>=coresize) (z) -= coresize; } while (0)
547 #define SUBMOD(z,x,y) do { (z) = (x)-(y); if ((int)(z)<0) (z) += coresize; } while (0)
548 
549 /* private macros to access p-space. */
550 #define UNSAFE_PSPACE_SET(warid, paddr, val) do {\
551     if (paddr) {\
552 	pspaces_[(warid)]->mem[(paddr)] = (val);\
553     } else {\
554 	pspaces_[(warid)]->lastresult = (val);\
555     }\
556 } while(0)
557 
558 #define UNSAFE_PSPACE_GET(warid, paddr) \
559 	( (paddr) ? pspaces_[(warid)]->mem[(paddr)]\
560 		  : pspaces_[(warid)]->lastresult )
561 
562 
563 int
sim_proper(unsigned int nwar,const field_t * war_pos_tab,unsigned int * death_tab)564 sim_proper( unsigned int nwar, const field_t *war_pos_tab,
565 	    unsigned int *death_tab )
566 {
567   /*
568    * Core and Process queue memories.
569    *
570    * The warriors share a common cyclic buffer for use as a process
571    * queue which the contains core addresses where active processes
572    * are.  The buffer has size N*P+1, where N = number of warriors,
573    * P = maximum number of processes / warrior.
574    *
575    * Each warrior has a fixed slice of the buffer for its own process
576    * queue which are initially allocated to the warriors in reverse
577    * order. i.e. if the are N warriors w1, w2, ..., wN, the slice for
578    * wN is 0..P-1, w{N-1} has P..2P-1, until w1 has (N-1)P..NP-1.
579    *
580    * The core address of the instruction is fetched from the head of
581    * the process queue and processes are pushed to the tail, so the
582    * individual slices slide along at one location per executed
583    * instruction.  The extra '+1' in the buffer size is to have free
584    * space to slide the slices along.
585    *
586    * For two warriors w1, w2:
587    *
588    * |\......../|\......../| |
589    * | w2 queue | w1 queue | |
590    * 0          P         2P 2P+1
591    */
592 
593   insn_t *core;
594   field_t *queue_start, *queue_end; /* queue mem. start, end */
595 
596   /*
597    * Cache Registers.
598    *
599    * The '94 draft specifies that the redcode processor model be
600    * 'in-register'.  That is, the current instruction and the
601    * instructions at the effective addresses (ea's) be cached in
602    * registers during instruction execution, rather than have
603    * core memory accessed directly when the operands are needed.  This
604    * causes differences from the 'in-memory' model.  e.g. MOV 0,>0
605    * doesn't change the instruction's b-field since the instruction at
606    * the a-field's effective address (i.e. the instruction itself) was
607    * cached before the post-increment happened.
608    *
609    * There are conceptually three registers: IN, A, and B.  IN is the
610    * current instruction, and A, B are the ones at the a- and
611    * b-fields' effective addresses respectively.
612    *
613    * We don't actually cache the complete instructions, but rather
614    * only the *values* of their a- and b-field.  This is because
615    * currently there is no way effective address computations can
616    * modify the opcode, modifier, or addressing modes of an
617    * instruction.
618    */
619 
620   u32_t in;			/* 'in' field of current insn for decoding */
621   u32_t ra_a, ra_b,		/* A register values */
622         rb_a, rb_b;		/* B register values */
623   u32_t da, db;			/* effective address of instruction's
624 				 * a- and b-fields */
625   /*
626    * alias some register names to real variables
627    */
628 #define in_a ra_a
629 #define in_b rb_b
630 
631   field_t *pofs;
632   insn_t *pt;
633   unsigned int mode;
634 
635   /*
636    * misc.
637    */
638   w_t *w;			/* current warrior */
639   u32_t ip;			/* current instruction pointer */
640   u32_t ftmp, t;		/* temps */
641   unsigned int coresize, coresize1; /* size of core, size of core - 1 */
642   int cycles;			/* instructions to execute before tie counter*/
643   int alive_cnt;
644   pspace_t **pspaces_;
645   u32_t pspacesize;
646 
647 #if DEBUG >= 1
648   insn_t insn;			/* used for disassembly */
649   char debug_line[256];		/* ditto */
650 #endif
651 
652 
653   /*
654    * Setup queue and core pointers
655    */
656   alive_cnt = nwar;
657   cycles = nwar * Cycles; /* set instruction executions until tie counter */
658   coresize = Coresize;
659   coresize1 = Coresize-1;
660   core = Core_Mem;
661   queue_start = Queue_Mem;
662   queue_end = Queue_Mem + NWarriors*Processes+1;
663   pspaces_ = PSpaces;
664   pspacesize = PSpace_size;
665   clear_exec_trail();
666 
667   /* Setup War_Tab and links all around */
668   pofs = queue_end-1;		/* init. wars[] table */
669   War_Tab[0].succ = &War_Tab[nwar-1];
670   War_Tab[nwar-1].pred = &War_Tab[0];
671   t = nwar-1;
672   ftmp = 0;
673   do {
674     if ( t > 0 ) War_Tab[t].succ = &War_Tab[t-1];
675     if ( t < nwar-1 ) War_Tab[t].pred = &War_Tab[t+1];
676     pofs -= Processes;
677     *pofs = war_pos_tab[ftmp];
678     War_Tab[t].head = pofs;
679     War_Tab[t].tail = pofs+1;
680     War_Tab[t].nprocs = 1;
681     War_Tab[t].id = ftmp;
682     --t;
683     ftmp++;
684   } while ( ftmp < nwar );
685 
686 
687   /*
688    * Main loop is run for each executed instruction
689    */
690   w = &War_Tab[ nwar-1 ];
691   do {
692 
693     ip = *w->head++;		/* load current instruction */
694     FOLDCHECK(ip);
695     if ( w->head == queue_end ) w->head = queue_start;
696     in = core[ ip ].in;		/* note: flags must be unset! */
697 #if !SIM_STRIP_FLAGS
698     in = in & iMASK;		/* strip flags. */
699 #endif
700     in_a = core[ ip ].a;
701     in_b = core[ ip ].b;
702 
703 #if DEBUG >= 1
704     insn = core[ip];
705     dis1( debug_line, insn, coresize);
706 #endif
707 
708     /*
709      * a-field effective address calculation.
710      *
711      * This bit was assimilated from Ken Espiritu's
712      * pmars 0.8.6 patch.  Ditto for the b-field
713      * calculation.
714      */
715     mode = in & mMASK;
716     in >>= mBITS;		/* shift out a-mode bits */
717     rb_a = in_a;		/* necessary if B-mode is immediate */
718 
719     if ( mode != IMMEDIATE ) {
720       ADDMOD( da, in_a, ip );
721       FOLDCHECK(da);
722       pt = core+da;		/* pt is where field points to (without */
723 				/* indirection). */
724 
725       if ( mode != DIRECT ) {
726 	if ( INDIR_A(mode) ) {
727 	  mode = RAW_MODE(mode);
728 	  pofs = &(pt->a);
729 	} else
730 	  pofs = &(pt->b);
731 
732 	t = *pofs;		/* pofs is the indirection offset */
733 	if (mode == PREDEC) {
734 	  DECMOD(t);
735 	  *pofs = t;
736 	}
737 	ADDMOD(da, t, da);
738 	FOLDCHECK(da);
739 
740 	pt = core+da;		/* now pt is the final destination */
741 				/* of indiretion. */
742 	ra_a = pt->a;		/* read in registers */
743 	ra_b = pt->b;
744 
745 	if (mode == POSTINC) {
746 	  INCMOD(t);
747 	  *pofs = t;
748 	}
749       } else /* DIRECT */{
750 	ra_a = pt->a;
751 	ra_b = pt->b;
752       }
753     } else /* IMMEDIATE */ {
754       ra_b = in_b;
755       da = ip;
756     }
757 
758 
759     /*
760      * b-field effective address calculation
761      */
762     mode = in & mMASK;
763     in >>= mBITS;		/* shift out b-mode bits */
764 
765     if ( mode != IMMEDIATE ) {
766       ADDMOD( db, in_b, ip );
767 		FOLDCHECK(db);
768       pt = core+db;
769 
770       if ( mode != DIRECT ) {
771 	if ( INDIR_A(mode) ) {
772 	  mode = RAW_MODE(mode);
773 	  pofs = &(pt->a);
774 	} else
775 	  pofs = &(pt->b);
776 
777 	t = *pofs;
778 	if (mode == PREDEC) {
779 	  DECMOD(t);
780 	  *pofs = t;
781 	}
782 	ADDMOD(db, t, db);
783 	FOLDCHECK(db);
784 
785 	pt = core+db;
786 	rb_a = pt->a;
787 	rb_b = pt->b;
788 
789 	if (mode == POSTINC) {
790 	  INCMOD(t);
791 	  *pofs = t;
792 	}
793       } else /* DIRECT */{
794 	rb_a = pt->a;
795 	rb_b = pt->b;
796       }
797     } else /* IMMEDIATE */ {
798       db = ip;
799     }
800 
801 #if DEBUG == 2
802     /* Debug output */
803     printf("%6d %4ld  %s  |%4ld, d %4ld,%4ld a %4ld,%4ld b %4ld,%4ld\n",
804 	   cycles, ip, debug_line,
805 	   w->nprocs, da, db,
806 	   ra_a, ra_b, rb_a, rb_b );
807 #endif
808 
809 	 append_to_exec_trail(in);
810 
811     /*
812      * Execute the instruction on opcode.modifier
813      */
814     switch ( in ) {
815 
816     case _OP(DAT, mA):
817     case _OP(DAT, mB):
818     case _OP(DAT, mAB):
819     case _OP(DAT, mBA):
820     case _OP(DAT, mX):
821     case _OP(DAT, mF):
822     case _OP(DAT, mI):
823     die:
824       if ( --w->nprocs > 0 )
825 	goto noqueue;
826       w->pred->succ = w->succ;
827       w->succ->pred = w->pred;
828       *death_tab++ = w->id;
829       cycles = cycles - cycles/alive_cnt; /* nC+k -> (n-1)C+k */
830       if ( --alive_cnt <= 1 )
831 	goto out;
832       goto noqueue;
833 
834 
835     case _OP(SPL, mA):
836     case _OP(SPL, mB):
837     case _OP(SPL, mAB):
838     case _OP(SPL, mBA):
839     case _OP(SPL, mX):
840     case _OP(SPL, mF):
841     case _OP(SPL, mI):
842       INCMOD(ip);
843       queue(ip);
844       if ( w->nprocs < Processes ) {
845 	++w->nprocs;
846 	queue(da);
847       }
848       goto noqueue;
849 
850 
851     case _OP(MOV, mA):
852       core[db].a = ra_a;
853       break;
854     case _OP(MOV, mF):
855       core[db].a = ra_a;
856     case _OP(MOV, mB):
857       core[db].b = ra_b;
858       break;
859     case _OP(MOV, mAB):
860       core[db].b = ra_a;
861       break;
862     case _OP(MOV, mX):
863       core[db].b = ra_a;
864     case _OP(MOV, mBA):
865       core[db].a = ra_b;
866       break;
867     case _OP(MOV, mI):
868       core[db].a = ra_a;
869       core[db].b = ra_b;
870       core[db].in = core[da].in;
871       break;
872 
873 
874     case _OP(DJN,mBA):
875     case _OP(DJN,mA):
876       t = core[db].a;
877       DECMOD(t);
878       core[db].a = t;
879       if ( rb_a == 1 ) break;
880       queue(da);
881       goto noqueue;
882 
883     case _OP(DJN,mAB):
884     case _OP(DJN,mB):
885       t = core[db].b;
886       DECMOD(t);
887       core[db].b = t;
888       if ( rb_b == 1 ) break;
889       queue(da);
890       goto noqueue;
891 
892     case _OP(DJN,mX):
893     case _OP(DJN,mI):
894     case _OP(DJN,mF):
895       t = core[db].a;      DECMOD(t);      core[db].a = t;
896       t = core[db].b;      DECMOD(t);      core[db].b = t;
897       if ( rb_a == 1 && rb_b == 1 ) break;
898       queue(da);
899       goto noqueue;
900 
901 
902     case _OP(ADD, mI):
903     case _OP(ADD, mF):
904       ADDMOD( t, ra_b, rb_b ); core[db].b = t;
905     case _OP(ADD, mA):
906       ADDMOD( t, ra_a, rb_a ); core[db].a = t;
907       break;
908     case _OP(ADD, mB):
909       ADDMOD( t, ra_b, rb_b ); core[db].b = t;
910       break;
911     case _OP(ADD, mX):
912       ADDMOD( t, ra_b, rb_a ); core[db].a = t;
913     case _OP(ADD, mAB):
914       ADDMOD( t, ra_a, rb_b ); core[db].b = t;
915       break;
916     case _OP(ADD, mBA):
917       ADDMOD( t, ra_b, rb_a ); core[db].a = t;
918       break;
919 
920 
921     case _OP(JMZ, mBA):
922     case _OP(JMZ, mA):
923       if ( rb_a )
924 	break;
925       queue(da);
926       goto noqueue;
927 
928     case _OP(JMZ, mAB):
929     case _OP(JMZ, mB):
930       if ( rb_b )
931 	break;
932       queue(da);
933       goto noqueue;
934 
935     case _OP(JMZ, mX):
936     case _OP(JMZ, mF):
937     case _OP(JMZ, mI):
938       if ( rb_a || rb_b )
939 	break;
940       queue(da);
941       goto noqueue;
942 
943 
944     case _OP(SUB, mI):
945     case _OP(SUB, mF):
946       SUBMOD( t, rb_b, ra_b ); core[db].b = t;
947     case _OP(SUB, mA):
948       SUBMOD( t, rb_a, ra_a); core[db].a = t;
949       break;
950     case _OP(SUB, mB):
951       SUBMOD( t, rb_b, ra_b ); core[db].b = t;
952       break;
953     case _OP(SUB, mX):
954       SUBMOD( t, rb_a, ra_b ); core[db].a = t;
955     case _OP(SUB, mAB):
956       SUBMOD( t, rb_b, ra_a ); core[db].b = t;
957       break;
958     case _OP(SUB, mBA):
959       SUBMOD( t, rb_a, ra_b ); core[db].a = t;
960       break;
961 
962 
963     case _OP(SEQ, mA):
964       if ( ra_a == rb_a )
965 	INCMOD(ip);
966       break;
967     case _OP(SEQ, mB):
968       if ( ra_b == rb_b )
969 	INCMOD(ip);
970       break;
971     case _OP(SEQ, mAB):
972       if ( ra_a == rb_b )
973 	INCMOD(ip);
974       break;
975     case _OP(SEQ, mBA):
976       if ( ra_b == rb_a )
977 	INCMOD(ip);
978       break;
979 
980     case _OP(SEQ, mI):
981 #if !SIM_STRIP_FLAGS
982 #define mask  (1<<(flPOS)-1)
983       if ( core[da].in & bitmask != core[db].in & bitmask )
984 	break;
985 #else
986       if ( core[da].in != core[db].in )
987 	break;
988 #endif
989       /* fallthrough */
990     case _OP(SEQ, mF):
991       if ( ra_a == rb_a && ra_b == rb_b )
992 	INCMOD(ip);
993       break;
994     case _OP(SEQ, mX):
995       if ( ra_a == rb_b && ra_b == rb_a )
996 	INCMOD(ip);
997       break;
998 
999 
1000     case _OP(SNE, mA):
1001       if ( ra_a != rb_a )
1002 	INCMOD(ip);
1003       break;
1004     case _OP(SNE, mB):
1005       if ( ra_b != rb_b )
1006 	INCMOD(ip);
1007       break;
1008     case _OP(SNE, mAB):
1009       if ( ra_a != rb_b )
1010 	INCMOD(ip);
1011       break;
1012     case _OP(SNE, mBA):
1013       if ( ra_b != rb_a )
1014 	INCMOD(ip);
1015       break;
1016 
1017     case _OP(SNE, mI):
1018       if ( core[da].in != core[db].in ) {
1019 	INCMOD(ip);
1020 	break;
1021       }
1022       /* fall through */
1023     case _OP(SNE, mF):
1024       if ( ra_a != rb_a || ra_b != rb_b )
1025 	INCMOD(ip);
1026       break;
1027     case _OP(SNE, mX):
1028       if ( ra_a != rb_b || ra_b != rb_a )
1029 	INCMOD(ip);
1030       break;
1031 
1032 
1033     case _OP(JMN, mBA):
1034     case _OP(JMN, mA):
1035       if (! rb_a )
1036 	break;
1037       queue(da);
1038       goto noqueue;
1039 
1040     case _OP(JMN, mAB):
1041     case _OP(JMN, mB):
1042       if (! rb_b )
1043 	break;
1044       queue(da);
1045       goto noqueue;
1046 
1047     case _OP(JMN, mX):
1048     case _OP(JMN, mF):
1049     case _OP(JMN, mI):
1050       if (!rb_a && !rb_b)
1051 	break;
1052       queue(da);
1053       goto noqueue;
1054 
1055 
1056     case _OP(JMP, mA):
1057     case _OP(JMP, mB):
1058     case _OP(JMP, mAB):
1059     case _OP(JMP, mBA):
1060     case _OP(JMP, mX):
1061     case _OP(JMP, mF):
1062     case _OP(JMP, mI):
1063       queue(da);
1064       goto noqueue;
1065 
1066 
1067 
1068     case _OP(SLT, mA):
1069       if (ra_a < rb_a)
1070 	INCMOD(ip);
1071       break;
1072     case _OP(SLT, mAB):
1073       if (ra_a < rb_b)
1074 	INCMOD(ip);
1075       break;
1076     case _OP(SLT, mB):
1077       if (ra_b < rb_b)
1078 	INCMOD(ip);
1079       break;
1080     case _OP(SLT, mBA):
1081       if (ra_b < rb_a)
1082 	INCMOD(ip);
1083       break;
1084     case _OP(SLT, mI):
1085     case _OP(SLT, mF):
1086       if (ra_a < rb_a && ra_b < rb_b)
1087 	INCMOD(ip);
1088       break;
1089     case _OP(SLT, mX):
1090       if (ra_a < rb_b && ra_b < rb_a)
1091 	INCMOD(ip);
1092       break;
1093 
1094 
1095     case _OP(MODM, mI):
1096     case _OP(MODM, mF):
1097       ftmp = 0;			/* we must try to do both modulos even if
1098 				   one fails */
1099       if ( ra_a ) core[db].a = rb_a % ra_a; else ftmp = 1;
1100       if ( ra_b ) core[db].b = rb_b % ra_b; else ftmp = 1;
1101       if ( ftmp ) goto die;
1102       break;
1103     case _OP(MODM, mX):
1104       ftmp = 0;			/* we must try to do both modulos even if
1105 				   one fails */
1106       if ( ra_b ) core[db].a = rb_a%ra_b; else ftmp = 1;
1107       if ( ra_a ) core[db].b = rb_b%ra_a; else ftmp = 1;
1108       if ( ftmp ) goto die;
1109       break;
1110     case _OP(MODM, mA):
1111       if ( !ra_a ) goto die;
1112       core[db].a = rb_a % ra_a;
1113       break;
1114     case _OP(MODM, mB):
1115       if ( !ra_b ) goto die;
1116       core[db].b = rb_b % ra_b;
1117       break;
1118     case _OP(MODM, mAB):
1119       if ( !ra_a ) goto die;
1120       core[db].b = rb_b % ra_a;
1121       break;
1122     case _OP(MODM, mBA):
1123       if ( !ra_b ) goto die;
1124       core[db].a = rb_a % ra_b;
1125       break;
1126 
1127 
1128     case _OP(MUL, mI):
1129     case _OP(MUL, mF):
1130       core[db].b = (rb_b * ra_b) % coresize;
1131     case _OP(MUL, mA):
1132       core[db].a = (rb_a * ra_a) % coresize;
1133       break;
1134     case _OP(MUL, mB):
1135       core[db].b = (rb_b * ra_b) % coresize;
1136       break;
1137     case _OP(MUL, mX):
1138       core[db].a = (rb_a * ra_b) % coresize;
1139     case _OP(MUL, mAB):
1140       core[db].b = (rb_b * ra_a) % coresize;
1141       break;
1142     case _OP(MUL, mBA):
1143       core[db].a = (rb_a * ra_b) % coresize;
1144       break;
1145 
1146 
1147     case _OP(DIV, mI):
1148     case _OP(DIV, mF):
1149       ftmp = 0;			/* we must try to do both divisions even if
1150 				   one fails */
1151       if ( ra_a ) core[db].a = rb_a / ra_a; else ftmp = 1;
1152       if ( ra_b ) core[db].b = rb_b / ra_b; else ftmp = 1;
1153       if ( ftmp ) goto die;
1154       break;
1155     case _OP(DIV, mX):
1156       ftmp = 0;			/* we must try to do both divisions even if
1157 				   one fails */
1158       if ( ra_b ) core[db].a = rb_a / ra_b; else ftmp = 1;
1159       if ( ra_a ) core[db].b = rb_b / ra_a; else ftmp = 1;
1160       if ( ftmp ) goto die;
1161       break;
1162     case _OP(DIV, mA):
1163       if ( !ra_a ) goto die;
1164       core[db].a = rb_a / ra_a;
1165       break;
1166     case _OP(DIV, mB):
1167       if ( !ra_b ) goto die;
1168       core[db].b = rb_b / ra_b;
1169       break;
1170     case _OP(DIV, mAB):
1171       if ( !ra_a ) goto die;
1172       core[db].b = rb_b / ra_a;
1173       break;
1174     case _OP(DIV, mBA):
1175       if ( !ra_b ) goto die;
1176       core[db].a = rb_a / ra_b;
1177       break;
1178 
1179 
1180     case _OP(NOP,mI):
1181     case _OP(NOP,mX):
1182     case _OP(NOP,mF):
1183     case _OP(NOP,mA):
1184     case _OP(NOP,mAB):
1185     case _OP(NOP,mB):
1186     case _OP(NOP,mBA):
1187       break;
1188 
1189     case _OP(LDP,mA):
1190       ftmp = ra_a % pspacesize;
1191       core[db].a = UNSAFE_PSPACE_GET(w->id, ftmp);
1192       break;
1193     case _OP(LDP,mAB):
1194       ftmp = ra_a % pspacesize;
1195       core[db].b = UNSAFE_PSPACE_GET(w->id, ftmp);
1196       break;
1197     case _OP(LDP,mBA):
1198       ftmp = ra_b % pspacesize;
1199       core[db].a = UNSAFE_PSPACE_GET(w->id, ftmp);
1200       break;
1201     case _OP(LDP,mF):
1202     case _OP(LDP,mX):
1203     case _OP(LDP,mI):
1204     case _OP(LDP,mB):
1205       ftmp = ra_b % pspacesize;
1206       core[db].b = UNSAFE_PSPACE_GET(w->id, ftmp);
1207       break;
1208 
1209     case _OP(STP,mA):
1210       ftmp = rb_a % pspacesize;
1211       UNSAFE_PSPACE_SET(w->id, ftmp, ra_a);
1212       break;
1213     case _OP(STP,mAB):
1214       ftmp = rb_b % pspacesize;
1215       UNSAFE_PSPACE_SET(w->id, ftmp, ra_a);
1216       break;
1217     case _OP(STP,mBA):
1218       ftmp = rb_a % pspacesize;
1219       UNSAFE_PSPACE_SET(w->id, ftmp, ra_b);
1220       break;
1221     case _OP(STP,mF):
1222     case _OP(STP,mX):
1223     case _OP(STP,mI):
1224     case _OP(STP,mB):
1225       ftmp = rb_b % pspacesize;
1226       UNSAFE_PSPACE_SET(w->id, ftmp, ra_b);
1227       break;
1228 
1229 #if DEBUG > 0
1230     default:
1231       alive_cnt = -1;
1232       goto out;
1233 #endif
1234 	default:
1235 		opcode_panic("defaulted",in);
1236     }
1237 
1238     INCMOD(ip);
1239     queue(ip);
1240   noqueue:
1241     w = w->succ;
1242   } while(--cycles>0);
1243 
1244  out:
1245 #if DEBUG == 1
1246   printf("cycles: %d\n", cycles);
1247 #endif
1248   return alive_cnt;
1249 }
1250