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