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