1 /* pMARS -- a portable Memory Array Redcode Simulator
2  * Copyright (C) 1993-1996 Albert Ma, Na'ndor Sieben, Stefan Strack and Mintardjo Wangsawidjaja
3  * Copyright (C) 2000 Ilmari Karonen
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 /*
21  * sim.c: simulator
22  * $Id: sim.c,v 1.3 2000/12/25 00:49:08 iltzu Exp $
23  *
24  * 10-23-98 Pentium optimized version 30% faster than the original
25  *          Ken Espiritu
26  */
27 
28 #include "global.h"
29 #include "sim.h"
30 #include <time.h>
31 
32 #ifdef unix
33 #include <signal.h>
34 #endif
35 #ifdef DOS16
36 #include <dos.h>
37 #endif
38 #ifdef DJGPP
39 #include <pc.h>
40 extern void sighandler(int dummy);
41 #endif
42 
43 
44 #ifdef TRACEGRAPHX
45 #include "trace.c"
46 #else
47 #if defined(MACGRAPHX)
48 #include "macdisp.c"
49 #else
50 #if defined(OS2PMGRAPHX)
51 #include "pmdisp.h"
52 #else
53 #if defined(GRAPHX)
54 
55 #ifdef CURSESGRAPHX
56 #include "curdisp.c"
57 #else
58 
59 #ifdef DOSTXTGRAPHX
60 #ifdef DJGPP
61 #include "gtdisp.c"
62 #else
63 #ifdef WATCOM
64 #include "wtdisp.c"
65 #else
66 #include "tdisp.c"
67 #endif
68 #endif                                /* DJGPP */
69 #endif                                /* DOSTXTGRAPHX */
70 
71 #ifdef DOSGRXGRAPHX
72 #ifdef DJGPP
73 #include "grxdisp.c"
74 #else
75 #ifdef WATCOM
76 #include "wgdisp.c"
77 #else
78 #include "bgidisp.c"
79 #endif
80 #endif                                /* DJGPP */
81 #endif                                /* DOSGRXGRAPHX */
82 
83 #ifdef DOSALLGRAPHX
84 #include "alldisp.c"
85 #endif
86 
87 #endif                                /* !CURSESGRAPHX */
88 #ifdef LINUXGRAPHX
89 #include "lnxdisp.c"
90 #else
91 #ifdef XWINGRAPHX
92 #include "xwindisp.c"
93 #else
94 #ifdef SDLGRAPHX
95 #include "sdldisp.c"
96 #else
97 #ifdef STDGRAPHX
98 #include "stddisp.c"
99 #else
100 #include "uidisp.c"
101 #endif
102 #endif
103 #endif
104 #endif
105 
106 #else                                /* !GRAPHX */
107 #define display_init()
108 #define display_clear()
109 #define display_read(addr)
110 #define display_write(addr)
111 #define display_dec(addr)
112 #define display_inc(addr)
113 #define display_exec(addr)
114 #define display_spl(warrior,tasks)
115 #define display_dat(address,warrior,tasks)
116 #define display_die(warnum)
117 #define display_close()
118 #define display_cycle()
119 #define display_push(val)
120 #endif                                /* TRACEGRAPHX */
121 #endif
122 #endif
123 #endif
124 
125 #ifdef DOS16
126 #define push(val) *W->taskTail++=(val)
127 #else
128 #define push(val) \
129 do { \
130  *W->taskTail=(val); \
131   if (++W->taskTail==endQueue) W->taskTail=taskQueue;\
132   display_push(val);\
133   } while (0)
134 #endif
135 
136 #ifdef PSPACE
137 #define get_pspace(idx) (((idx) % pSpaceSize) ?\
138 	    *(pSpace[W->pSpaceIndex] + ((idx) % pSpaceSize)) : W->lastResult)
139 #define set_pspace(idx,value) do {\
140 	    if ((idx) % pSpaceSize) \
141 		*(pSpace[W->pSpaceIndex] + ((idx) % pSpaceSize)) = value;\
142 	    else W->lastResult = value;\
143 	    } while(0)
144 #endif
145 
146 #define OP(opcode,modifier) (opcode<<3)+modifier
147 #define ADDMOD(A,B,C) do { if ((C=(int) A+B)>=coreSize) C-=coreSize; } \
148 while (0)
149 #define SUBMOD(A,B,C) do { if ((C=(int) A-B)<0) C+=coreSize; } \
150 while (0)
151 
152 #ifdef NEW_STYLE
153 extern int posit(void);
154 extern void npos(void);
155 extern S32_T rng(S32_T seed);
156 #else
157 extern int posit();
158 extern void npos();
159 extern S32_T rng();
160 #endif
161 
162 /* strings */
163 extern char *outOfMemory;
164 extern char *warriorTerminated;
165 extern char *fatalErrorInSimulator;
166 extern char *warriorTerminatedEndOfRound;
167 extern char *endOfRound;
168 
169 warrior_struct *W;                /* indicate which warrior is running */
170 U32_T   totaltask;                /* size of the taskQueue */
171 ADDR_T FAR *endQueue;
172 ADDR_T FAR *taskQueue;
173 ADDR_T  progCnt;                /* program counter */
174 
175   mem_struct FAR *destPtr;        /* pointer used to copy program to core */
176   mem_struct FAR *tempPtr;        /* temporary pointer used in op decode phase */
177 
178   mem_struct IR;                /* current instruction and A cell */
179 #ifdef NEW_MODES
180 //  mem_struct IRA;                /* A/B_field hold A-field of A/B-pointer
181 //                                 * necessary for '}' mode */
182 ADDR_T AA_Value, AB_Value;
183 #endif
184 
185 mem_struct FAR *memory;
186 
187 long    cycle;
188 int     round;
189 
190 char    alloc_p = 0;                /* indicate whether memory has been allocated */
191 int     warriorsLeft;                /* number of warriors still left in core */
192 
193 warrior_struct *endWar;                /* end of the warriors array */
194 
195 /*--------------------*/
196 #ifdef NEW_STYLE
197 S32_T
checksum_warriors(void)198 checksum_warriors(void)
199 #else
200 S32_T
201 checksum_warriors()
202 #endif
203 
204 {
205   int     shuffle = 0;                /* XOR with position-dependent int */
206   S32_T   checksum = 0;                /* accumulator */
207   mem_struct *source;
208   mem_struct *last;
209 
210   /*
211    * create a checksum for RNG seed based on warrior code; debuginfo is not
212    * used.
213    */
214   W = warrior;
215   do {
216     source = W->instBank;
217     last = source + W->instLen;
218     while (source != last) {
219       checksum += source->opcode ^ (shuffle++);
220       checksum += source->A_mode ^ (shuffle++);
221       checksum += source->B_mode ^ (shuffle++);
222       checksum += source->A_value ^ (shuffle++);
223       checksum += source->B_value ^ (shuffle++);
224       ++source;
225     }
226     ++W;
227   } while (W < endWar);
228   return checksum;
229 }
230 
231 void
simulator1()232 simulator1()
233 {
234 #ifdef PERMUTATE
235   int permidx = 0, permtmp, *permbuf = NULL;
236 #endif
237   /* range for random number generator */
238   warrior_struct *oldW;                /* the previous living warrior to execute */
239   ADDR_T  positions = coreSize + 1 - (separation << 1);
240   ADDR_T  coreSize1 = coreSize - 1;
241   warrior_struct *starter = warrior;        /* pointer to warrior that starts
242 					 * round */
243   U32_T   cycles2 = warriors * cycles;
244 #ifndef SERVER
245   char    outs[60];                /* for cdb() entering message */
246 #endif
247   mem_struct *sourcePtr;        /* pointer used to copy program to core */
248   mem_struct *endPtr;                /* pointer used to copy program to core */
249 register  int     temp;                        /* general purpose temporary variable */
250   int     addrA, addrB;                /* A and B pointers */
251 #ifndef SERVER
252   int     temp2;			/* needed in graphical versions to display postincrements at the correct address */
253 #endif
254   ADDR_T FAR *tempPtr2;
255 #ifdef NEW_MODES
256   ADDR_T FAR *offsPtr;                /* temporary pointer used in op decode phase */
257 #endif
258 
259   endWar = warrior + warriors;
260 
261 #ifdef PERMUTATE
262   if (SWITCH_P) {
263     permbuf = (int *) malloc((size_t)(warriors * positions * sizeof(int)));
264     if (!permbuf) {
265       errout(outOfMemory);
266       Exit(MEMERR);
267     }
268   }
269 #endif
270 
271 #ifdef DOS16
272   if (!alloc_p) {
273     memory = farmalloc((long) coreSize * sizeof(mem_struct));
274     if (!memory) {
275       errout(outOfMemory);
276       Exit(MEMERR);
277     }
278     taskQueue = farmalloc(65528L);        /* allocate an entire 64K segment */
279     if (!taskQueue) {
280       farfree(memory);
281       errout(outOfMemory);
282       Exit(MEMERR);
283     }
284     /* zero the offset so the weird segment hack works */
285     memory = (mem_struct far *) MK_FP(FP_SEG(memory), 0);
286     taskQueue = (ADDR_T far *) MK_FP(FP_SEG(taskQueue), 0);
287     alloc_p = 1;
288     endQueue = taskQueue + totaltask;        /* memory; */
289   }
290 #else
291   if (!alloc_p) {
292     memory = (mem_struct *) malloc((size_t) coreSize * sizeof(mem_struct));
293     if (!memory) {
294       errout(outOfMemory);
295       Exit(MEMERR);
296     }
297     totaltask = (U32_T) taskNum *warriors + 1;
298     taskQueue = (ADDR_T *) malloc((size_t) totaltask * sizeof(ADDR_T));
299     if (!taskQueue) {
300       free(memory);
301       errout(outOfMemory);
302       Exit(MEMERR);
303     }
304     alloc_p = 1;
305     endQueue = taskQueue + totaltask;
306   }
307 #endif
308   if (SWITCH_e)
309     debugState = STEP;                /* automatically enter debugger */
310   if (!debugState)
311     copyDebugInfo = TRUE;        /* this makes things a little faster */
312   seed = SWITCH_F ?
313     (SWITCH_F - separation) :        /* seed from argument */
314   /* seed from either checksum or time */
315     rng(SWITCH_f ? checksum_warriors() : time(0));
316 #ifdef PERMUTATE
317   if (SWITCH_F && SWITCH_P)
318     seed *= warriors; /* get table index from position */
319 #endif
320 
321   display_init();
322   round = 1;
323   do {                                /* each round */
324 #if defined(DOS16) && !defined(SERVER) && !defined(DOSTXTGRAPHX) && !defined(DOSGRXGRAPHX) && !defined(DJGPP)
325     fputc('\r', stdout);        /* enable interruption by Ctrl-C */
326 #else
327 #if defined(DJGPP) && !defined(SERVER) && !defined(DOSTXTGRAPHX) && !defined(DOSGRXGRAPHX) && !defined(CURSESGRAPHX)
328     if (kbhit())
329       sighandler(0);
330 #endif
331 #endif
332     warriorsLeft = warriors;
333     cycle = cycles2;
334     if (warriors > 1) {
335       if (warriors == 2) {
336 #ifdef PERMUTATE
337         if (SWITCH_P) {
338           if (permidx == 0) { /* initialize buffer */
339             for (;permidx < warriors*positions; permidx++)
340               permbuf[permidx] = permidx;
341           }
342           permtmp = seed % permidx;
343           warrior[1].position = separation + permbuf[permtmp]/warriors;
344           starter = warrior + permbuf[permtmp] % warriors;
345           permbuf[permtmp] = permbuf[--permidx];
346         } else
347 #endif
348 	  warrior[1].position = separation + seed % positions;
349 	seed = rng(seed);
350       } else {
351 	if (posit())
352 	  npos();                /* use back-up positioning algo npos if posit
353 				 * fails */
354       }
355     }
356     /* create nextWarrior links each round */
357     /* leave oldW pointing to last warrior */
358     for (oldW = warrior; oldW < endWar - 1; ++oldW)
359       oldW->nextWarrior = oldW + 1;
360     oldW->nextWarrior = warrior;
361     W = starter;
362     if (starter != warrior)
363       oldW = starter - 1;
364     addrA = warrior[0].instLen;
365     /* clear the core following warrior 0 */
366     do {
367       memory[addrA] = INITIALINST;
368     } while (++addrA < coreSize);
369     tempPtr2 = endQueue - taskNum - 1;
370     temp = 0;
371     do {
372       /* initialize head, tail, and taskQueue */
373       W->taskHead = tempPtr2;
374       W->taskTail = tempPtr2 + 1;
375       *tempPtr2 = (W->position + W->offset) % coreSize;
376       *tempPtr2 = *tempPtr2 < 0 ? *tempPtr2 + coreSize : *tempPtr2;
377       W->tasks = 1;
378       tempPtr2 -= taskNum;
379       destPtr = memory + W->position;
380       sourcePtr = W->instBank;
381       endPtr = sourcePtr + W->instLen;
382       /* copy the warriors to core */
383       while (sourcePtr != endPtr) {
384 	*destPtr++ = *sourcePtr++;
385       }
386       display_spl(temp, 1);
387       W = W->nextWarrior;
388     } while (++temp < warriors);
389 
390     display_clear();
391     /* the inner loop of execution */
392     do {                        /* each cycle */
393       display_cycle();
394      // progCnt = *(W->taskHead++);
395      // IR = memory[progCnt];        /* copy instruction into register */
396 	IR = memory[(progCnt= *(W->taskHead++))];
397 #ifndef DOS16
398       if (W->taskHead == endQueue)
399 	W->taskHead = taskQueue;
400 #endif
401 #ifndef SERVER
402       if (debugState && ((debugState == STEP) || memory[progCnt].debuginfo))
403 	debugState = cdb("");
404 #endif
405 #ifdef NEW_MODES
406       AB_Value = IR.A_value;        /* necessary if B-mode is immediate */
407 #endif
408 
409       /*
410        * evaluate A operand.  This is the hardest part of the entire
411        * simulator code.  Obfuscated C code at it's finest
412        */
413 if (IR.A_mode != (FIELD_T) IMMEDIATE)
414 {
415 	ADDMOD(IR.A_value, progCnt, addrA);
416 	tempPtr = &memory[addrA];
417 
418 	if (IR.A_mode != (FIELD_T) DIRECT)
419 	{
420 		#ifdef NEW_MODES
421 		if (INDIR_A(IR.A_mode))
422 		{
423 			IR.A_mode = RAW_MODE(IR.A_mode);
424 			offsPtr = &(tempPtr->A_value);
425 		} else
426 			offsPtr = &(tempPtr->B_value);
427 
428 		temp = *offsPtr;
429 		#endif
430 		if (IR.A_mode == (FIELD_T) PREDECR)
431 		{
432 			if (--temp < 0)
433 				temp = coreSize1;
434 			#ifdef NEW_MODES
435 			*offsPtr = temp;
436 			#else
437 			tempPtr->B_value = temp;
438 			#endif
439 			display_dec(addrA);
440 		}
441 		/* jk - added os2 part */
442 		display_read(addrA);
443 		#ifndef SERVER
444 		temp2 = addrA;        /* make the trace accurate */
445 		#endif
446 		ADDMOD(temp, addrA, addrA);
447 
448 		destPtr = &memory[addrA];       //new
449 		#ifdef NEW_MODES
450 		AA_Value = destPtr->A_value;
451 		#endif
452 		IR.A_value = destPtr->B_value;
453 
454 		if (IR.A_mode == (FIELD_T) POSTINC)
455 		{
456 			if (++temp == coreSize)
457 				temp = 0;
458 			#ifdef NEW_MODES
459 			*offsPtr = temp;
460 			#else
461 			tempPtr->B_value = temp;
462 			#endif
463 			#ifndef SERVER
464 			display_inc(temp2);
465 			#endif
466 		}
467 	} else
468 	{
469 	#ifdef NEW_MODES
470 
471 	IR.A_value = tempPtr->B_value;
472 	AA_Value = tempPtr->A_value;
473 
474 	#else
475 	IR.A_value = temp = tempPtr->B_value;
476 	#endif
477 	}
478 } else
479 {
480 	#ifdef NEW_MODES
481 	AA_Value = IR.A_value;
482 	#endif
483 	addrA = progCnt;
484 
485 	IR.A_value = IR.B_value;
486 }
487 
488       /*
489        * evaluate B operand.  This is the hardest part of the entire
490        * simulator code.  Obfuscated C code at it's finest
491        */
492  //     addrB = progCnt;
493 if (IR.B_mode != (FIELD_T) IMMEDIATE)
494 {
495 	ADDMOD(IR.B_value, progCnt, addrB);
496 	 tempPtr = &memory[addrB];
497 
498 	if (IR.B_mode != (FIELD_T) DIRECT)
499 	{
500 		#ifdef NEW_MODES
501 		if (INDIR_A(IR.B_mode))
502 		{
503 			IR.B_mode = RAW_MODE(IR.B_mode);
504 			offsPtr = &(tempPtr->A_value);
505 		} else
506 			offsPtr = &(tempPtr->B_value);
507 		temp = *offsPtr;
508 		#endif
509 		if (IR.B_mode == (FIELD_T) PREDECR)
510 		{
511 			if (--temp < 0)
512 				temp = coreSize1;
513 			#ifdef NEW_MODES
514 			*offsPtr = temp;
515 			#else
516 			tempPtr->B_value = temp;
517 			#endif
518 			display_dec(addrB);
519 		}
520 		/* jk - added os2 part */
521 		display_read(addrB);
522 		#ifndef SERVER
523 		temp2 = addrB;
524 		#endif
525 
526 		ADDMOD(temp, addrB, addrB);
527 
528 		destPtr = &memory[addrB];
529 		#ifdef NEW_MODES
530 		AB_Value = destPtr->A_value;
531 		#endif
532 
533 		IR.B_value = destPtr->B_value;
534 
535 		if (IR.B_mode == (FIELD_T) POSTINC)
536 		{
537 			if (++temp == coreSize)
538 				temp = 0;
539 			#ifdef NEW_MODES
540 			*offsPtr = temp;
541 			#else
542 			tempPtr->B_value = temp;
543 			#endif
544 			#ifndef SERVER
545 			display_inc(temp2);
546 			#endif
547 		}
548 	} else
549 	{
550 	#ifdef NEW_MODES
551 	AB_Value = tempPtr->A_value;
552 
553 	IR.B_value = tempPtr->B_value;
554 	#else
555 	IR.B_value = temp = tempPtr->B_value;
556 	#endif
557 	}
558 } else
559       addrB = progCnt;
560       /*
561        * addrA holds the A-pointer IR.A_value holds the B operand of the
562        * A-pointer cell. temp holds the B-pointer IR.B_value holds the B
563        * operand of the B-pointer cell.
564        */
565 #ifdef NEW_MODES
566       /*
567        * IRA_A_value holds the A operand of the A-pointer cell IRA.B_value
568        * holds the A operand of the B-pointer cell.
569        */
570 
571 #define ADDRA_AVALUE AA_Value
572 #define ADDRB_AVALUE AB_Value
573 #else
574 #define ADDRA_AVALUE memory[addrA].A_value
575 #define ADDRB_AVALUE memory[addrB].A_value
576 #endif
577 
578       /* execute it! */
579       display_exec(progCnt);
580       switch (IR.opcode) {
581 
582       case OP(MOV, mA):
583 	display_read(addrA);
584 	memory[addrB].A_value = ADDRA_AVALUE;
585 	display_write(addrB);
586 	break;
587 
588       case OP(MOV, mF):
589 	memory[addrB].A_value = ADDRA_AVALUE;
590 	/* FALLTHRU */
591       case OP(MOV, mB):
592 	display_read(addrA);
593 	memory[addrB].B_value = IR.A_value;
594 	display_write(addrB);
595 	break;
596 
597       case OP(MOV, mAB):
598 	display_read(addrA);
599 	memory[addrB].B_value = ADDRA_AVALUE;
600 	display_write(addrB);
601 	break;
602 
603       case OP(MOV, mX):
604 	memory[addrB].B_value = ADDRA_AVALUE;
605 	/* FALLTHRU */
606       case OP(MOV, mBA):
607 	display_read(addrA);
608 	memory[addrB].A_value = IR.A_value;
609 	display_write(addrB);
610 	break;
611 
612 #ifdef PERMUTATE
613   if (SWITCH_P) {
614     permbuf = (int *) malloc((size_t)(warriors * positions * sizeof(int)));
615     if (!permbuf) {
616       errout(outOfMemory);
617       Exit(MEMERR);
618     }
619   }
620 #endif
621 
622       case OP(ADD, mA):
623 	display_read(addrA);
624 	ADDMOD(ADDRB_AVALUE, ADDRA_AVALUE, temp);
625 	memory[addrB].A_value = temp;
626 	display_write(addrB);
627 	break;
628 
629       case OP(ADD, mI):
630       case OP(ADD, mF):
631 	ADDMOD(ADDRB_AVALUE, ADDRA_AVALUE, temp);
632 	memory[addrB].A_value = temp;
633 	/* FALLTHRU */
634       case OP(ADD, mB):
635 	display_read(addrA);
636 	ADDMOD(IR.B_value, IR.A_value, temp);
637 	memory[addrB].B_value = temp;
638 	display_write(addrB);
639 	break;
640 
641       case OP(ADD, mAB):
642 	display_read(addrA);
643 	ADDMOD(IR.B_value, ADDRA_AVALUE, temp);
644 	memory[addrB].B_value = temp;
645 	display_write(addrB);
646 	break;
647 
648       case OP(ADD, mX):
649 	ADDMOD(IR.B_value, ADDRA_AVALUE, temp);
650 	memory[addrB].B_value = temp;
651 	/* FALLTHRU */
652       case OP(ADD, mBA):
653 	display_read(addrA);
654 	ADDMOD(ADDRB_AVALUE, IR.A_value, temp);
655 	memory[addrB].A_value = temp;
656 	display_write(addrB);
657 	break;
658 
659 
660       case OP(SUB, mA):
661 	display_read(addrA);
662 	SUBMOD(ADDRB_AVALUE, ADDRA_AVALUE, temp);
663 	memory[addrB].A_value = temp;
664 	display_write(addrB);
665 	break;
666 
667       case OP(SUB, mI):
668       case OP(SUB, mF):
669 	SUBMOD(ADDRB_AVALUE, ADDRA_AVALUE, temp);
670 	memory[addrB].A_value = temp;
671 	/* FALLTHRU */
672       case OP(SUB, mB):
673 	display_read(addrA);
674 	SUBMOD(IR.B_value, IR.A_value, temp);
675 	memory[addrB].B_value = temp;
676 	display_write(addrB);
677 	break;
678 
679       case OP(SUB, mAB):
680 	display_read(addrA);
681 	SUBMOD(IR.B_value, ADDRA_AVALUE, temp);
682 	memory[addrB].B_value = temp;
683 	display_write(addrB);
684 	break;
685 
686       case OP(SUB, mX):
687 	SUBMOD(IR.B_value, ADDRA_AVALUE, temp);
688 	memory[addrB].B_value = temp;
689 	/* FALLTHRU */
690       case OP(SUB, mBA):
691 	display_read(addrA);
692 	SUBMOD(ADDRB_AVALUE, IR.A_value, temp);
693 	memory[addrB].A_value = temp;
694 	display_write(addrB);
695 	break;
696 
697 
698 	/* the cast prevents overflow */
699       case OP(MUL, mA):
700 	display_read(addrA);
701 	memory[addrB].A_value =
702 	  (U32_T) ADDRB_AVALUE *ADDRA_AVALUE % coreSize;
703 	display_write(addrB);
704 	break;
705 
706       case OP(MUL, mI):
707       case OP(MUL, mF):
708 	memory[addrB].A_value =
709 	  (U32_T) ADDRB_AVALUE *ADDRA_AVALUE % coreSize;
710 	/* FALLTHRU */
711       case OP(MUL, mB):
712 	display_read(addrA);
713 	memory[addrB].B_value =
714 	  (U32_T) IR.B_value * IR.A_value % coreSize;
715 	display_write(addrB);
716 	break;
717 
718       case OP(MUL, mAB):
719 	display_read(addrA);
720 	memory[addrB].B_value =
721 	  (U32_T) IR.B_value * ADDRA_AVALUE % coreSize;
722 	display_write(addrB);
723 	break;
724 
725       case OP(MUL, mX):
726 	memory[addrB].B_value =
727 	  (U32_T) IR.B_value * ADDRA_AVALUE % coreSize;
728 	/* FALLTHRU */
729       case OP(MUL, mBA):
730 	display_read(addrA);
731 	memory[addrB].A_value =
732 	  (U32_T) ADDRB_AVALUE *IR.A_value % coreSize;
733 	display_write(addrB);
734 	break;
735 
736 
737       case OP(DIV, mA):
738 	display_read(addrA);
739 	if (!ADDRA_AVALUE)
740 	  goto die;
741 	memory[addrB].A_value = ADDRB_AVALUE / ADDRA_AVALUE;
742 	display_write(addrB);
743 	break;
744 
745       case OP(DIV, mB):
746 	display_read(addrA);
747 	if (!IR.A_value)
748 	  goto die;
749 	memory[addrB].B_value = IR.B_value / IR.A_value;
750 	display_write(addrB);
751 	break;
752 
753       case OP(DIV, mAB):
754 	display_read(addrA);
755 	if (!ADDRA_AVALUE)
756 	  goto die;
757 	memory[addrB].B_value = IR.B_value / ADDRA_AVALUE;
758 	display_write(addrB);
759 	break;
760 
761       case OP(DIV, mBA):
762 	display_read(addrA);
763 	if (!IR.A_value)
764 	  goto die;
765 	memory[addrB].A_value = ADDRB_AVALUE / IR.A_value;
766 	display_write(addrB);
767 	break;
768 
769       case OP(DIV, mI):
770       case OP(DIV, mF):
771 	display_read(addrA);
772 	if (ADDRA_AVALUE) {
773 	  memory[addrB].A_value = ADDRB_AVALUE / ADDRA_AVALUE;
774 	  display_write(addrB);
775 	  if (!IR.A_value)
776 	    goto die;
777 	  memory[addrB].B_value = IR.B_value / IR.A_value;
778 	  display_write(addrB);
779 	  break;
780 	} else {
781 	  if (!IR.A_value)
782 	    goto die;
783 	  memory[addrB].B_value = IR.B_value / IR.A_value;
784 	  display_write(addrB);
785 	  goto die;
786 	}
787       case OP(DIV, mX):
788 	display_read(addrA);
789 	if (IR.A_value) {
790 	  memory[addrB].A_value = ADDRB_AVALUE / IR.A_value;
791 	  display_write(addrB);
792 	  if (!ADDRA_AVALUE)
793 	    goto die;
794 	  memory[addrB].B_value = IR.B_value / ADDRA_AVALUE;
795 	  display_write(addrB);
796 	  break;
797 	} else {
798 	  if (!ADDRA_AVALUE)
799 	    goto die;
800 	  memory[addrB].B_value = IR.B_value / ADDRA_AVALUE;
801 	  display_write(addrB);
802 	  goto die;
803 	}
804 
805       case OP(MOD, mA):
806 	display_read(addrA);
807 	if (!ADDRA_AVALUE)
808 	  goto die;
809 	memory[addrB].A_value = ADDRB_AVALUE % ADDRA_AVALUE;
810 	display_write(addrB);
811 	break;
812 
813       case OP(MOD, mB):
814 	display_read(addrA);
815 	if (!IR.A_value)
816 	  goto die;
817 	memory[addrB].B_value = IR.B_value % IR.A_value;
818 	display_write(addrB);
819 	break;
820 
821       case OP(MOD, mAB):
822 	display_read(addrA);
823 	if (!ADDRA_AVALUE)
824 	  goto die;
825 	memory[addrB].B_value = IR.B_value % ADDRA_AVALUE;
826 	display_write(addrB);
827 	break;
828 
829       case OP(MOD, mBA):
830 	display_read(addrA);
831 	if (!IR.A_value)
832 	  goto die;
833 	memory[addrB].A_value = ADDRB_AVALUE % IR.A_value;
834 	display_write(addrB);
835 	break;
836 
837       case OP(MOD, mI):
838       case OP(MOD, mF):
839 	display_read(addrA);
840 	if (ADDRA_AVALUE) {
841 	  memory[addrB].A_value = ADDRB_AVALUE % ADDRA_AVALUE;
842 	  display_write(addrB);
843 	  if (!IR.A_value)
844 	    goto die;
845 	  memory[addrB].B_value = IR.B_value % IR.A_value;
846 	  display_write(addrB);
847 	  break;
848 	} else {
849 	  if (!IR.A_value)
850 	    goto die;
851 	  memory[addrB].B_value = IR.B_value % IR.A_value;
852 	  display_write(addrB);
853 	  goto die;
854 	}
855 
856       case OP(MOD, mX):
857 	display_read(addrA);
858 	if (IR.A_value) {
859 	  memory[addrB].A_value = ADDRB_AVALUE % IR.A_value;
860 	  display_write(addrB);
861 	  if (!ADDRA_AVALUE)
862 	    goto die;
863 	  memory[addrB].B_value = IR.B_value % ADDRA_AVALUE;
864 	  display_write(addrB);
865 	  break;
866 	} else {
867 	  if (!ADDRA_AVALUE)
868 	    goto die;
869 	  memory[addrB].B_value = IR.B_value % ADDRA_AVALUE;
870 	  display_write(addrB);
871 	  goto die;
872 	}
873 
874 
875       case OP(JMZ, mA):
876       case OP(JMZ, mBA):
877 	display_read(addrB);
878 	if (ADDRB_AVALUE)
879 	  break;
880 	push(addrA);
881 	goto nopush;
882 
883       case OP(JMZ, mF):
884       case OP(JMZ, mX):
885       case OP(JMZ, mI):
886 	display_read(addrB);
887 	if (ADDRB_AVALUE)
888 	  break;
889 	/* FALLTHRU */
890       case OP(JMZ, mB):
891       case OP(JMZ, mAB):
892 	display_read(addrB);
893 	if (IR.B_value)
894 	  break;
895 	push(addrA);
896 	goto nopush;
897 
898 
899       case OP(JMN, mA):
900       case OP(JMN, mBA):
901 	display_read(addrB);
902 	if (!ADDRB_AVALUE)
903 	  break;
904 	push(addrA);
905 	goto nopush;
906 
907       case OP(JMN, mB):
908       case OP(JMN, mAB):
909 	display_read(addrB);
910 	if (!IR.B_value)
911 	  break;
912 	push(addrA);
913 	goto nopush;
914 
915       case OP(JMN, mF):
916       case OP(JMN, mX):
917       case OP(JMN, mI):
918 	display_read(addrB);
919 	if (!ADDRB_AVALUE && !IR.B_value)
920 	  break;
921 	push(addrA);
922 	goto nopush;
923 
924       case OP(DJN, mA):
925       case OP(DJN, mBA):
926 #ifdef NEW_MODES
927 	if (ISNEG(--memory[addrB].A_value))
928 	  memory[addrB].A_value = coreSize1;
929 	display_dec(addrB);
930 	if (AB_Value == 1)
931 	  break;
932 #else
933 	if (!--memory[addrB].A_value)
934 	  break;
935 	display_dec(addrB);
936 	if (ISNEG(memory[addrB].A_value))
937 	  memory[addrB].A_value = coreSize1;
938 #endif
939 	push(addrA);
940 	goto nopush;
941 
942 
943       case OP(DJN, mB):
944       case OP(DJN, mAB):
945 	if (ISNEG(--memory[addrB].B_value))
946 	  memory[addrB].B_value = coreSize1;
947 	display_dec(addrB);
948 	if (IR.B_value == 1)
949 	  break;
950 	push(addrA);
951 	goto nopush;
952 
953       case OP(DJN, mF):
954       case OP(DJN, mI):
955       case OP(DJN, mX):
956 	if (ISNEG(--memory[addrB].B_value))
957 	  memory[addrB].B_value = coreSize1;
958 	if (ISNEG(--memory[addrB].A_value))
959 	  memory[addrB].A_value = coreSize1;
960 	display_dec(addrB);
961 #ifdef NEW_MODES
962 	if ((AB_Value == 1) && (IR.B_value == 1))
963 	  break;
964 #else
965 	if ((!memory[addrB].A_value) && (IR.B_value == 1))
966 	  break;
967 #endif
968 	push(addrA);
969 	goto nopush;
970 
971 #ifdef NEW_OPCODES
972       case OP(SEQ, mA):
973 #endif
974       case OP(CMP, mA):
975 	display_read(addrB);
976 	display_read(addrA);
977 	if (ADDRB_AVALUE != ADDRA_AVALUE)
978 	  break;
979 	ADDMOD(progCnt, 2, temp);
980 	goto pushtemp;
981 
982 #ifdef NEW_OPCODES
983       case OP(SEQ, mI):
984 #endif
985       case OP(CMP, mI):
986 	display_read(addrB);
987 	display_read(addrA);
988 	if ((memory[addrB].opcode != memory[addrA].opcode) ||
989 	    (memory[addrB].A_mode != memory[addrA].A_mode) ||
990 	    (memory[addrB].B_mode != memory[addrA].B_mode))
991 	  break;
992 	/* FALLTHRU */
993 #ifdef NEW_OPCODES
994       case OP(SEQ, mF):
995 #endif
996       case OP(CMP, mF):
997 	display_read(addrB);
998 	display_read(addrA);
999 	if (ADDRB_AVALUE != ADDRA_AVALUE)
1000 	  break;
1001 	/* FALLTHRU */
1002 #ifdef NEW_OPCODES
1003       case OP(SEQ, mB):
1004 #endif
1005       case OP(CMP, mB):
1006 	display_read(addrB);
1007 	display_read(addrA);
1008 	if (IR.B_value != IR.A_value)
1009 	  break;
1010 	ADDMOD(progCnt, 2, temp);
1011 	goto pushtemp;
1012 
1013 #ifdef NEW_OPCODES
1014       case OP(SEQ, mAB):
1015 #endif
1016       case OP(CMP, mAB):
1017 	display_read(addrB);
1018 	display_read(addrA);
1019 	if (IR.B_value != ADDRA_AVALUE)
1020 	  break;
1021 	ADDMOD(progCnt, 2, temp);
1022 	goto pushtemp;
1023 
1024 #ifdef NEW_OPCODES
1025       case OP(SEQ, mX):
1026 #endif
1027       case OP(CMP, mX):
1028 	display_read(addrB);
1029 	display_read(addrA);
1030 	if (IR.B_value != ADDRA_AVALUE)
1031 	  break;
1032 	/* FALLTHRU */
1033 #ifdef NEW_OPCODES
1034       case OP(SEQ, mBA):
1035 #endif
1036       case OP(CMP, mBA):
1037 	display_read(addrB);
1038 	display_read(addrA);
1039 	if (ADDRB_AVALUE != IR.A_value)
1040 	  break;
1041 	ADDMOD(progCnt, 2, temp);
1042 	goto pushtemp;
1043 
1044 #ifdef NEW_OPCODES
1045       case OP(SNE, mA):
1046 	display_read(addrB);
1047 	display_read(addrA);
1048 	if (ADDRB_AVALUE != ADDRA_AVALUE)
1049 	  goto skip;
1050 	break;
1051     skip:
1052 	ADDMOD(progCnt, 2, temp);
1053 	goto pushtemp;
1054 
1055       case OP(SNE, mI):
1056 	display_read(addrB);
1057 	display_read(addrA);
1058 	if ((memory[addrB].opcode != memory[addrA].opcode) ||
1059 	    (memory[addrB].A_mode != memory[addrA].A_mode) ||
1060 	    (memory[addrB].B_mode != memory[addrA].B_mode))
1061 	  goto skip;
1062 	/* FALLTHRU */
1063       case OP(SNE, mF):
1064 	display_read(addrB);
1065 	display_read(addrA);
1066 	if (ADDRB_AVALUE != ADDRA_AVALUE)
1067 	  goto skip;
1068 	/* FALLTHRU */
1069       case OP(SNE, mB):
1070 	display_read(addrB);
1071 	display_read(addrA);
1072 	if (IR.B_value != IR.A_value)
1073 	  goto skip;
1074 	break;
1075 
1076       case OP(SNE, mAB):
1077 	display_read(addrB);
1078 	display_read(addrA);
1079 	if (IR.B_value != ADDRA_AVALUE)
1080 	  goto skip;
1081 	break;
1082 
1083       case OP(SNE, mX):
1084 	display_read(addrB);
1085 	display_read(addrA);
1086 	if (IR.B_value != ADDRA_AVALUE)
1087 	  goto skip;
1088 	/* FALLTHRU */
1089       case OP(SNE, mBA):
1090 	display_read(addrB);
1091 	display_read(addrA);
1092 	if (ADDRB_AVALUE != IR.A_value)
1093 	  goto skip;
1094 	break;
1095 #endif
1096 
1097       case OP(SLT, mA):
1098 	display_read(addrB);
1099 	display_read(addrA);
1100 	if (ADDRB_AVALUE <= ADDRA_AVALUE)
1101 	  break;
1102 	ADDMOD(progCnt, 2, temp);
1103 	goto pushtemp;
1104 
1105       case OP(SLT, mF):
1106       case OP(SLT, mI):
1107 	display_read(addrB);
1108 	display_read(addrA);
1109 	if (ADDRB_AVALUE <= ADDRA_AVALUE)
1110 	  break;
1111 	/* FALLTHRU */
1112       case OP(SLT, mB):
1113 	display_read(addrB);
1114 	display_read(addrA);
1115 	if (IR.B_value <= IR.A_value)
1116 	  break;
1117 	ADDMOD(progCnt, 2, temp);
1118 	goto pushtemp;
1119 
1120       case OP(SLT, mAB):
1121 	display_read(addrB);
1122 	display_read(addrA);
1123 	if (IR.B_value <= ADDRA_AVALUE)
1124 	  break;
1125 	ADDMOD(progCnt, 2, temp);
1126 	goto pushtemp;
1127 
1128       case OP(SLT, mX):
1129 	display_read(addrB);
1130 	display_read(addrA);
1131 	if (IR.B_value <= ADDRA_AVALUE)
1132 	  break;
1133 	/* FALLTHRU */
1134       case OP(SLT, mBA):
1135 	display_read(addrB);
1136 	display_read(addrA);
1137 	if (ADDRB_AVALUE <= IR.A_value)
1138 	  break;
1139 	ADDMOD(progCnt, 2, temp);
1140 	goto pushtemp;
1141 
1142 
1143       case OP(JMP, mA):
1144       case OP(JMP, mB):
1145       case OP(JMP, mAB):
1146       case OP(JMP, mBA):
1147       case OP(JMP, mF):
1148       case OP(JMP, mX):
1149       case OP(JMP, mI):
1150 	push(addrA);
1151 	goto nopush;
1152 
1153 
1154       case OP(SPL, mA):
1155       case OP(SPL, mB):
1156       case OP(SPL, mAB):
1157       case OP(SPL, mBA):
1158       case OP(SPL, mF):
1159       case OP(SPL, mX):
1160       case OP(SPL, mI):
1161 //        temp = progCnt + 1;
1162 	if ((temp = progCnt + 1) == coreSize)
1163 	  temp = 0;
1164 	push(temp);
1165 
1166 	if (W->tasks >= taskNum)
1167 	  goto nopush;
1168 	++W->tasks;
1169 	display_spl(W - warrior, W->tasks);
1170 	push(addrA);
1171 	goto nopush;
1172 
1173 
1174       case OP(DAT, mA):
1175       case OP(DAT, mB):
1176       case OP(DAT, mAB):
1177       case OP(DAT, mBA):
1178       case OP(DAT, mF):
1179       case OP(DAT, mX):
1180       case OP(DAT, mI):
1181     die:
1182 	display_dat(progCnt, W - warrior, W->tasks);
1183 	if (--W->tasks)
1184 	  goto nopush;
1185 	display_die(W - warrior);
1186 	W->score[warriorsLeft + warriors - 2]++;
1187 	cycle = cycle - 1 - (cycle - 1) / (warriorsLeft--);
1188 	if (warriorsLeft < 2)
1189 	  goto nextround;        /* can't use break because in switch */
1190 
1191 #ifndef SERVER
1192 	if (debugState == BREAK) {
1193 	  sprintf(outs, warriorTerminated, W - warrior, W->name);
1194 	  debugState = cdb(outs);
1195 	}
1196 #endif                                /* SERVER */
1197 	oldW->nextWarrior = W = W->nextWarrior;
1198 	continue;
1199 
1200 	/* $EXT$ insert code for new opcodes here */
1201 
1202 #ifdef NEW_OPCODES
1203       case OP(NOP, mA):
1204       case OP(NOP, mB):
1205       case OP(NOP, mAB):
1206       case OP(NOP, mBA):
1207       case OP(NOP, mF):
1208       case OP(NOP, mX):
1209       case OP(NOP, mI):
1210 	break;
1211 #endif
1212 
1213 #ifdef PSPACE
1214       case OP(LDP, mA):
1215 	display_read(addrA);
1216 	memory[addrB].A_value = get_pspace(ADDRA_AVALUE);
1217 	display_write(addrB);
1218 	break;
1219 
1220       case OP(LDP, mF):
1221       case OP(LDP, mX):
1222       case OP(LDP, mI):
1223       case OP(LDP, mB):
1224 	display_read(addrA);
1225 	memory[addrB].B_value = get_pspace(IR.A_value);
1226 	display_write(addrB);
1227 	break;
1228 
1229       case OP(LDP, mAB):
1230 	display_read(addrA);
1231 	memory[addrB].B_value = get_pspace(ADDRA_AVALUE);
1232 	display_write(addrB);
1233 	break;
1234 
1235       case OP(LDP, mBA):
1236 	display_read(addrA);
1237 	memory[addrB].A_value = get_pspace(IR.A_value);
1238 	display_write(addrB);
1239 	break;
1240 
1241       case OP(STP, mA):
1242 	display_read(addrA);
1243 	set_pspace(ADDRB_AVALUE, ADDRA_AVALUE);
1244 	break;
1245 
1246       case OP(STP, mF):
1247       case OP(STP, mX):
1248       case OP(STP, mI):
1249       case OP(STP, mB):
1250 	display_read(addrA);
1251 	set_pspace(IR.B_value, IR.A_value);
1252 	break;
1253 
1254       case OP(STP, mAB):
1255 	display_read(addrA);
1256 	set_pspace(IR.B_value, ADDRA_AVALUE);
1257 	break;
1258 
1259       case OP(STP, mBA):
1260 	display_read(addrA);
1261 	set_pspace(ADDRB_AVALUE, IR.A_value);
1262 	break;
1263 #endif                                /* PSPACE */
1264       case OP(MOV, mI):
1265 	display_read(addrA);
1266 #ifndef SERVER
1267 	if (!copyDebugInfo)
1268 	  temp = memory[addrB].debuginfo;
1269 #endif
1270 	memory[addrB] = memory[addrA];
1271 #ifndef SERVER
1272 	if (!copyDebugInfo)
1273 	  memory[addrB].debuginfo = temp;
1274 #endif
1275 	memory[addrB].B_value = IR.A_value;
1276 #ifdef NEW_MODES
1277 	memory[addrB].A_value = AA_Value;
1278 #endif
1279 	display_write(addrB);
1280 //        break;
1281 #if 0
1282       default:
1283 	errout(fatalErrorInSimulator);
1284 #ifdef PERMUTATE
1285         if(permbuf) {
1286           free(permbuf);
1287           permbuf = NULL;
1288         }
1289 #endif
1290 #ifndef DOS16
1291 	/* DOS taskQueue may not be free'd because of segment wrap-around */
1292 	free(memory);
1293 	free(taskQueue);
1294 	alloc_p = 0;
1295 #endif
1296 	Exit(SERIOUS);
1297 #endif
1298       }                                /* end switch */
1299 
1300       /* push the next instruction onto queue */
1301  //     temp = progCnt + 1;
1302       if ((temp=progCnt + 1) == coreSize)
1303 	temp = 0;
1304   pushtemp:                        /* push whatever's in temp onto queue */
1305       push(temp);
1306 
1307   nopush:                        /* just go to the next warrior/cycle */
1308       oldW = W;
1309       W = W->nextWarrior;
1310 //      --cycle;
1311     } while (--cycle);                /* next cycle */
1312 nextround:
1313     for (temp = 0; temp < warriors; temp++) {
1314       if (warrior[temp].tasks) {
1315 	warrior[temp].score[warriorsLeft - 1]++;
1316 #ifdef PSPACE
1317 	warrior[temp].lastResult = warriorsLeft;
1318       } else
1319 	warrior[temp].lastResult = 0;
1320 #else
1321       }
1322 #endif
1323     }
1324     if (starter == endWar - 1)
1325       starter = warrior;
1326     else
1327       ++starter;
1328 #ifndef SERVER
1329     if (debugState == BREAK) {
1330       if (warriorsLeft == 1 && warriors != 1)
1331 	sprintf(outs, warriorTerminatedEndOfRound, W - warrior, W->name, round);
1332       else
1333 	sprintf(outs, endOfRound, round);
1334       debugState = cdb(outs);
1335     }
1336 #endif
1337   } while (++round <= rounds);
1338 
1339   display_close();
1340 #ifdef PERMUTATE
1341   if(permbuf) {
1342     free(permbuf);
1343     permbuf = NULL;
1344   }
1345 #endif
1346 #ifndef DOS16
1347   /* DOS taskQueue may not be free'd because of segment wrap-around */
1348   free(memory);
1349   free(taskQueue);
1350   alloc_p = 0;
1351 #endif
1352 }
1353