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