home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / version-1-0 / BlitzSrc / blitz.c < prev    next >
C/C++ Source or Header  |  2006-09-25  |  285KB  |  9,501 lines

  1. /* The BLITZ Machine Emulator
  2. **
  3. ** Copyright 2001-2006, Harry H. Porter III
  4. **
  5. ** This file may be freely copied, modified and compiled, on the sole
  6. ** conditions that if you modify it...
  7. **
  8. **   (1) Your name and the date of modification is added to this comment
  9. **       under "Modifications by", and
  10. **
  11. **   (2) Your name and the date of modification is added to the
  12. **       "commandLineHelp()" routine under "Modifications by".
  13. **
  14. ** Original Author:
  15. **   02/05/01 - Harry H. Porter III
  16. **
  17. ** Modifcations by:
  18. **   09/28/04 - Harry - Fix bug with randomSeed, disk errno
  19. **   11/26/04 - Harry - Fix bugs with serial input
  20. **   03/15/06 - Harry - Renamed "SPANK" to "BLITZ"
  21. **
  22. ** Please respect the coding and commenting style of this program.
  23. **
  24. */
  25.  
  26. #include <sys/time.h>
  27. #include <sys/types.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <stdarg.h>
  31. #include <string.h>
  32. #include <signal.h>
  33. #include <math.h>
  34. #include <errno.h>
  35.  
  36.  
  37.  
  38. typedef struct TableEntry TableEntry;
  39.  
  40.  
  41.  
  42. /*****  Global variables *****/
  43.  
  44. #define PAGE_SIZE 8192            /* Page Size (8K) */
  45. char * memory;                    /* Where machine memory is stored */
  46. int currentMemoryLock = -1;       /* Address of word holding lock, or -1 */
  47. int userRegisters [16];           /* User regs r0, r1, ... r15 */
  48. int systemRegisters [16];         /* System regs r0, r1, ... r15 */
  49. double floatRegisters [16];       /* Floating regs f0, f1, ... f15 */
  50. int pc;                           /* The current program counter */
  51. int ptbr;                         /* The page table base register */
  52. int ptlr;                         /* The page table length register */
  53. int statusN;                      /* Status register, N bit */
  54. int statusV;                      /* Status register, V bit */
  55. int statusZ;                      /* Status register, Z bit */
  56. int statusP;                      /* Status register, P bit */
  57. int statusS;                      /* Status register, S bit */
  58. int statusI;                      /* Status register, I bit */
  59. int instruction;                  /* The current instruction being executed */
  60. int commandOptionG = 0;           /* Automatically begin emulation, bypass interface */
  61. int commandOptionRaw = 0;         /* Prefer "raw" mode (default is "cooked") */
  62. int commandOptionWait = 0;        /* On 'wait' instruction, with for input */
  63. int commandOptionRand = 0;        /* Set if "-r" was on command line */
  64. int randSeedFromOption;           /* The value following "-r" */
  65. int randomSeed;                   /* The running pseudo-random number */
  66. char * executableFileName = NULL; /* The a.out filename */
  67. FILE * executableFile;            /* The a.out file */
  68. char * diskFileName = NULL;       /* The DISK filename */
  69. FILE * diskFile = NULL;           /* The DISK file, possibly NULL */
  70. char * termInputFileName = NULL;  /* The TERMINPUT filename */
  71. FILE * termInputFile;             /* The TERMINPUT file */
  72. char * termOutputFileName = NULL; /* The TERMOUTPUT filename */
  73. FILE * termOutputFile;            /* The TERMOUTPUT file */
  74. int textAddr;                     /* Starting addr of .text segment */
  75. int dataAddr;                     /* Starting addr of .data segment */
  76. int bssAddr;                      /* Starting addr of .bss segment */
  77. int textSize;                     /* Sum of all .text segment sizes */
  78. int dataSize;                     /* Sum of all .data segment sizes */
  79. int bssSize;                      /* Sum of all .bss segment sizes */
  80. char * pmPtr;
  81. int pmSize;
  82. int pmCount;
  83. int pmRow[16];
  84. int currentAddr;                  /* This is used in commandDis */
  85. int currentFrame;                 /* This is used in commandStackUp, commandStackDown */
  86. char inputBuffer [100];           /* Used for user input */
  87. int interruptsSignaled;           /* 0=none; otherwise one bit per type */
  88. int systemTrapNumber;             /* Set by the syscall exception */
  89. int pageInvalidOffendingAddress;  /* Used by Page Invalid exception */
  90. int pageReadonlyOffendingAddress; /* Used by Page Readonly exception */
  91. int translateCausedException;     /* Set by translate () */
  92. int currentTime;                  /* Measured in "clicks": 1,2,3,... */
  93. int timeSpentAsleep;              /* Incremented by "wait" instruction */
  94. int timeOfNextEvent;              /* Minimum of disk, serial, and timer */
  95. int timeOfNextTimerEvent;         /* Zero = now, MAX = never */
  96. int timeOfNextDiskEvent;          /* Zero = now, MAX = never */
  97. int timeOfNextSerialInEvent;      /* Zero = now, MAX = never */
  98. int timeOfNextSerialOutEvent;     /* Zero = now, MAX = never */
  99. int executionHalted;              /* 0=continue executing; 1=halted */
  100. int controlCPressed;              /* 0=not pressed; 1=pressed */
  101. int wantPrintingInSingleStep;     /* Used by singleStep to control verbosity. */
  102. int q;                            /* Used by the divide() routine */
  103. int r;                            /* Used by the divide() routine */
  104. double POSITIVE_INFINITY;         /* Effectively a constant */
  105. double NEGATIVE_INFINITY;         /* Effectively a constant */
  106. int terminalInRawMode;            /* 1=stdin is in "raw mode" for BLITZ input */
  107. int terminalWantRawProcessing;    /* 1=user wants raw, unbuffered input */
  108. int termInChar;                   /* The input character, zero if none */
  109. int termInCharAvail;              /* Set when key pressed, clr'd when queried */
  110. int termInCharWasUsed;            /* True after BLITZ program looks at char */
  111. int termOutputReady;              /* 1=busy, 0=not busy */
  112. #define TYPE_AHEAD_BUFFER_SIZE 100
  113.                                   /* Characters to be supplied to serial in */
  114. char typeAheadBuffer [TYPE_AHEAD_BUFFER_SIZE];
  115. int typeAheadBufferCount;         /* Number of characters in the buffer */
  116. int typeAheadBufferIn;            /* Next pos to put into */
  117. int typeAheadBufferOut;           /* Next pos to get from */
  118.  
  119.  
  120.  
  121.  
  122. /*****  Simulation Constants  *****
  123. **
  124. ** The following variables are "constants" in the sense that they remain fixed
  125. **   during instruction emulation.  They are set at startup time and when the
  126. **   "reset" command is executed.  If a file called ".blitzrc" exists, their
  127. **   values will be obtained from this; otherwise they will be given default
  128. **   values.  The default values are in the "setSimulationConstants()" routine.
  129. **
  130. ** All times are in terms of instruction "cycles."  Except for interrupts, there
  131. **   will be one instruction executed per cycle.  For a 1MHz machine, each
  132. **   cycle corresponds to 1 microsecond.
  133. **    
  134. ** To simulate human typing on the serial input, we might use
  135. **     KEYBOARD_WAIT_TIME = 1000    KEYBOARD_WAIT_TIME_VARIATION = 100000
  136. ** To simulate an output rate of 19 KBaud on the serial output, we might use
  137. **     TERM_OUT_DELAY = 500         TERM_OUT_DELAY_VARIATION = 10
  138. ** To switch processes about 200 times per second, we might use
  139. **     TIME_SLICE = 5000            TIME_SLICE_VARIATION = 10
  140. **   (To turn off Timer Interrupts, use TIME_SLICE = 0.)
  141. ** DISK_SEEK_TIME is the time to move the disk head one track.
  142. ** DISK_SETTLE_TIME is the time to wait after any head movement.
  143. ** DISK_ROTATIONAL_DELAY is the time for the disk to advance 1 sector.
  144. **   This value must be at least 1.  Transfer time is the rotational delay
  145. **   times the number of sectors.  (Note: we do not model the time for track
  146. **   seek and settle during a multi-sector transfer.)
  147. ** Disk access is the sum of seek, settle, rotational delay and transfer time.
  148. ** There can be a random variation added onto this, given by DISK_ACCESS_VARIATION.
  149. **
  150. ** DISK_READ_ERROR_PROBABILITY is the probability that an I/O error will occur
  151. **   on any one read operation.  It is given as a number like 500, which means
  152. **   1 error in every 500.  A value of 0 means errors never occur.
  153. ** DISK_WRITE_ERROR_PROBABILITY is the probability that an I/O error will occur
  154. **   on any one write operatiorn.
  155. **
  156. ** The MEMORY_SIZE is in bytes.  Typically, this would be something like 16Mbytes.
  157. **
  158. ** The "Memory Mapped Area" is a region of memory that behaves differently than
  159. **   normaly memory; when the program reads or writes bytes in this region, the exact
  160. **   behavior depends on the I/O device specification.  The MEMORY_MAPPED_AREA_LOW
  161. **   is the lowest address and the MEMORY_MAPPED_AREA_HIGH is the highest address
  162. **   in this region.  (E.g., 0x00ffff00, 0x00ffffff).
  163. **
  164. ** The various words in the emory Mapped Area have specific addresses given by
  165. **   SERIAL_STATUS_WORD_ADDRESS
  166. **   SERIAL_DATA_WORD_ADDRESS
  167. **   DISK_STATUS_WORD_ADDRESS
  168. **   DISK_COMMAND_WORD_ADDRESS
  169. **   DISK_MEMORY_ADDRESS_REGISTER
  170. **   DISK_SECTOR_NUMBER_REGISTER
  171. **   DISK_SECTOR_COUNT_REGISTER
  172. **  
  173. */
  174.  
  175. int KEYBOARD_WAIT_TIME = -1;
  176. int KEYBOARD_WAIT_TIME_VARIATION = -1;
  177. int TERM_OUT_DELAY = -1;
  178. int TERM_OUT_DELAY_VARIATION = -1;
  179. int TIME_SLICE = -1;
  180. int TIME_SLICE_VARIATION = -1;
  181. int DISK_SEEK_TIME = -1;
  182. int DISK_SETTLE_TIME = -1;
  183. int DISK_ROTATIONAL_DELAY = -1;
  184. int DISK_ACCESS_VARIATION = -1;
  185. int DISK_READ_ERROR_PROBABILITY = -1;
  186. int DISK_WRITE_ERROR_PROBABILITY = -1;
  187. int INIT_RANDOM_SEED = -1;
  188. int MEMORY_SIZE = -1;
  189. int MEMORY_MAPPED_AREA_LOW = -1;
  190. int MEMORY_MAPPED_AREA_HIGH = -1;
  191. int SERIAL_STATUS_WORD_ADDRESS = -1;
  192. int SERIAL_DATA_WORD_ADDRESS = -1;
  193. int DISK_STATUS_WORD_ADDRESS = -1;
  194. int DISK_COMMAND_WORD_ADDRESS = -1;
  195. int DISK_MEMORY_ADDRESS_REGISTER = -1;
  196. int DISK_SECTOR_NUMBER_REGISTER = -1;
  197. int DISK_SECTOR_COUNT_REGISTER = -1;
  198.  
  199.  
  200.  
  201. /*****  The disk simulation  *****
  202. **
  203. ** The disk is divided into sectors, whose size matches the
  204. ** "PAGE_SIZE" exaclty (i.e., 8Kbytes).  The disk is assumed to have
  205. ** one surface with a single disk head.  In other words, there
  206. ** is only 1 track per cylinder.  Hereafter, we speak only of
  207. ** tracks and ignore the concept of cylinders.  Each track is
  208. ** assumed  to have 16 sectors, giving 128Kbytes per track
  209. ** (= SECTORS_PER_TRACK * PAGE_SIZE).
  210. **
  211. ** The size of the disk is some multiple of tracks, > 0.  The
  212. ** actual size is determined by the size of the disk file.  When
  213. ** the file is opened, we determine the "diskTrackCount" and the
  214. ** "diskSectorCount" (which is 16 times greater).
  215. **
  216. ** At any time time, the disk has a current rotational position
  217. ** "currentDiskSector" which is a sector number between 0 and
  218. ** SECTORS_PER_TRACK-1.
  219. **
  220. ** The status of the disk is given by two variables:
  221. **    currentDiskStatus
  222. **    futureDiskStatus
  223. ** Whenever a disk operation is called for, it is done immediately
  224. ** during a single insrtuction cycle.  However, the simulation calls
  225. ** for the disk to reamin busy for a while.  Thus, the current status
  226. ** will be busy, and a future status (eg, completedOK or completedWithError)
  227. ** will be determined.  An event will be scheduled.  At that event,
  228. ** the status will be changed to the new status, and an interrupt will
  229. ** be signalled.
  230. **
  231. ** The possible values for these status variables are:
  232. **    DiskBusy                      0x00000000
  233. **    OperationCompletedOK          0x00000001
  234. **    OperationCompletedWithError1  0x00000002
  235. **    OperationCompletedWithError2  0x00000003
  236. **    OperationCompletedWithError3  0x00000004
  237. **    OperationCompletedWithError4  0x00000005
  238. **    OperationCompletedWithError5  0x00000006
  239. **
  240. ** All disk operations are in terms of a sector number, between
  241. ** 0 and diskSectorCount-1.  When a disk operation is requested, we
  242. ** will determine the delay, based on the current position of the
  243. ** head (i.e., which track it is on), and the current rotational
  244. ** angle of the disk platter (i.e., which sector within the track
  245. ** it is on).
  246. **
  247. ** The emulator will then go to the DISK file and perform the
  248. ** operation.  Finally, it will schedule a "disk event" to initiate
  249. ** the interrupt that must be signaled when the disk operation is
  250. ** supposed to complete.  In the case of a disk read operation, we
  251. ** also mark the words in memory so the memory manager can signal an
  252. ** error if the BLITZ program happens to read or write them while the
  253. ** disk operation is in progress.  These are given by "diskBufferLow"
  254. ** and "diskBufferHigh".
  255. **
  256. */
  257. #define SECTORS_PER_TRACK                           16
  258.  
  259. #define DISK_BUSY                           0x00000000
  260. #define OPERATION_COMPLETED_OK              0x00000001
  261. #define OPERATION_COMPLETED_WITH_ERROR_1    0x00000002
  262. #define OPERATION_COMPLETED_WITH_ERROR_2    0x00000003
  263. #define OPERATION_COMPLETED_WITH_ERROR_3    0x00000004
  264. #define OPERATION_COMPLETED_WITH_ERROR_4    0x00000005
  265. #define OPERATION_COMPLETED_WITH_ERROR_5    0x00000006
  266.  
  267. #define DISK_READ_COMMAND                   0x00000001
  268. #define DISK_WRITE_COMMAND                  0x00000002
  269.  
  270.  
  271. int diskTrackCount = 0;                          /* The size of the disk */
  272. int diskSectorCount = 0;                         /* The size of the disk */
  273. int currentDiskSector = 0;                       /* The current disk position */
  274. int currentDiskStatus = OPERATION_COMPLETED_OK;  /* Current status */
  275. int futureDiskStatus = OPERATION_COMPLETED_OK;   /* What to become upon next disk event */
  276. int diskBufferLow = 0;                           /* Used to error-check memory accesses */
  277. int diskBufferHigh = 0;                          /* Used to error-check memory accesses */
  278. int diskMemoryAddressRegister = 0x00000000;      /* What to read from memory-mapped area */
  279. int diskSectorNumberRegister = 0x00000000;       /* What to read from memory-mapped area */
  280. int diskSectorCountRegister = 0x00000000;        /* What to read from memory-mapped area */
  281. int numberOfDiskReads = 0;                       /* How many since last reset (not errors) */
  282. int numberOfDiskWrites = 0;                      /* How many since last reset (not errors) */
  283.  
  284.  
  285.  
  286. /*****  Memory-Mapped I/O Addresses  *****
  287. **
  288. ** A special region is physical memory is "memory-mapped I/O".
  289. ** Loads and stores to this region go directly to/from the various
  290. ** I/O devices, rather than the memory.  These are the locations of
  291. ** various special I/O registers that are mapped into the physical
  292. ** memory address space.
  293. **                                  default value
  294. **                                  =============
  295. **     MEMORY_MAPPED_AREA_LOW         0x00ffff00
  296. **     MEMORY_MAPPED_AREA_HIGH        0x00ffffff
  297. **
  298. **     SERIAL_STATUS_WORD_ADDRESS     0x00ffff00
  299. **     SERIAL_DATA_WORD_ADDRESS       0x00ffff04
  300. **
  301. **     DISK_STATUS_WORD_ADDRESS       0x00ffff08
  302. **     DISK_COMMAND_WORD_ADDRESS      0x00ffff08
  303. **     DISK_MEMORY_ADDRESS_REGISTER   0x00ffff0c
  304. **     DISK_SECTOR_NUMBER_REGISTER    0x00ffff10
  305. **     DISK_SECTOR_COUNT_REGISTER     0x00ffff14
  306. */
  307.  
  308.  
  309.  
  310. /*****  Interrupt Codes  *****
  311. **
  312. ** These codes are used to set and test bits in the
  313. ** interruptSignaled flag.  See also
  314. **    getNextInterrupt
  315. **    getVectorNumber
  316. */
  317. #define POWER_ON_RESET                      1
  318. #define TIMER_INTERRUPT                     2
  319. #define DISK_INTERRUPT                      4
  320. #define SERIAL_INTERRUPT                    8
  321. #define HARDWARE_FAULT                     16
  322. #define ILLEGAL_INSTRUCTION                32
  323. #define ARITHMETIC_EXCEPTION               64
  324. #define ADDRESS_EXCEPTION                 128
  325. #define PAGE_INVALID_EXCEPTION            256
  326. #define PAGE_READONLY_EXCEPTION           512
  327. #define PRIVILEGED_INSTRUCTION           1024
  328. #define ALIGNMENT_EXCEPTION              2048
  329. #define EXCEPTION_DURING_INTERRUPT       4096
  330. #define SYSCALL_TRAP                     8192
  331.  
  332.  
  333. #define MAX 2147483647
  334. int MIN;                 /* Initialized in main to -2147483648 */
  335.  
  336.  
  337. /*****  Label Table  *****
  338. **
  339. ** Each label is an identifier (consisting of letters, digits, underscores,
  340. ** and periods).  Each label has a value, which is a 32-bit integer.
  341. ** Label values are absolute, not relative, at run-time.  Each label-value
  342. ** pair is represented with a "TableEntry".  The TableEntries are indexed
  343. ** in two ways.  First, by name:  There is an array ("alphaIndex") which
  344. ** contains pointers to TableEntries.  Second, by value:  There is an array
  345. ** ("valueIndex") which contains pointers to TableEntries.  Both arrays will
  346. ** have the same number of elements, namely, "numberOfLabels", and both
  347. ** arrays are kept in sorted order.
  348. */
  349. struct TableEntry {
  350.   int   value;
  351.   char  string [0];       /* The characters, including \0 at end */
  352. };
  353.  
  354. #define MAX_NUMBER_OF_LABELS 500000
  355. TableEntry * alphaIndex [MAX_NUMBER_OF_LABELS];
  356. TableEntry * valueIndex [MAX_NUMBER_OF_LABELS];
  357. int numberOfLabels = 0;
  358.  
  359.  
  360.  
  361. /*****  Function prototypes  *****/
  362.  
  363. int main (int argc, char ** argv);
  364. void printFinalStats ();
  365. void checkBigEndian ();
  366. void checkArithmetic ();
  367. int isNegZero (double d);
  368. void processCommandLine (int argc, char ** argv);
  369. void badOption (char * msg);
  370. void errorExit ();
  371. void fatalError (char * msg);
  372. void commandLineHelp ();
  373. char * getToken ();
  374. char * trimToken (char * str);
  375. char * toLower (char * str);
  376. int readInteger (FILE * file);
  377. int readByte (FILE * file);
  378. int roundUpToMultipleOf (int i, int p);
  379. void printMemory (char * ptr, int n, int addr);
  380. void get16Bytes ();
  381. int getNextByte ();
  382. void putlong (int i);
  383. void puthalf (int i);
  384. void printline ();
  385. void printByte (int c);
  386. int bytesEqual (char * p, char * q, int lengthP, int lengthQ);
  387. void commandHelp ();
  388. void commandAllRegs ();
  389. void commandAllFloatRegs ();
  390. void printDouble (double d);
  391. void printDoubleVal (double d);
  392. void commandInfo ();
  393. void printPendingInterrupts ();
  394. void commandIO ();
  395. void commandSim ();
  396. void commandRaw ();
  397. void commandCooked ();
  398. void printSerialHelp ();
  399. void commandFormat ();
  400. void commandTest ();
  401. void printNumberNL2 (int i);
  402. void printNumberNL (int i);
  403. void commandDumpMemory ();
  404. void commandSetMemory ();
  405. void commandWriteWord ();
  406. void commandReadWord ();
  407. void commandInput ();
  408. void addToTypeAhead (int ch);
  409. void printTypeAheadBuffer ();
  410. void fancyPrintChar (int ch);
  411. int readHexInt ();
  412. int readDecimalInt ();
  413. double readDouble ();
  414. int readYesNo ();
  415. void commandSetI ();
  416. void commandSetS ();
  417. void commandSetP ();
  418. void commandSetZ ();
  419. void commandSetV ();
  420. void commandSetN ();
  421. void commandClearI ();
  422. void commandClearS ();
  423. void commandClearP ();
  424. void commandClearZ ();
  425. void commandClearV ();
  426. void commandClearN ();
  427. void commandSetPC ();
  428. void commandSetPTBR ();
  429. void commandSetPTLR ();
  430. void commandPrintPageTable ();
  431. void commandTranslate ();
  432. void commandCancel ();
  433. void commandLabels ();
  434. void printStringInWidth (char * string, int width);
  435. void commandInit ();
  436. void commandInit2 ();
  437. void commandSort ();
  438. void commandSort2 ();
  439. void quicksortAlpha (int m, int n);
  440. int partitionAlpha (int l, int r);
  441. void quicksortValue (int m, int n);
  442. int partitionValue (int l, int r);
  443. void commandFind ();
  444. void commandFind2 ();
  445. int findLabel (int value);
  446. int findLabel2 (int value, int low, int high);
  447. TableEntry * findLabelByAlpha (char * string, int low, int high);
  448. void commandAdd ();
  449. void insertLabel (TableEntry * p);
  450. void insertLabelUnsorted (TableEntry * p);
  451. void commandReset ();
  452. void resetState ();
  453. void printInfo ();
  454. void commandReg (int reg);
  455. void commandFloatReg (int reg);
  456. void commandFMem ();
  457. void commandDis ();
  458. void commandDis2 ();
  459. void disassemble (int addr);
  460. void printRa (int instr);
  461. void printRb (int instr);
  462. void printRc (int instr);
  463. void printFRa (int instr);
  464. void printFRb (int instr);
  465. void printFRc (int instr);
  466. void printData16 (int instr);
  467. void printData24 (int instr);
  468. void printComment (int i);
  469. void printComment2 (int i);
  470. void printAboutToExecute ();
  471. void commandStepN ();
  472. void commandGo (int count);
  473. void commandStep ();
  474. void commandStepHigh ();
  475. void commandStepHigh2 ();
  476. void singleStep ();
  477. int getRa (int instr);
  478. int getRb (int instr);
  479. int getRc (int instr);
  480. void putRc (int instr, int value);
  481. int getData16 (int instr);
  482. int getData24 (int instr);
  483. double getFRa (int instr);
  484. double getFRb (int instr);
  485. double getFRc (int instr);
  486. void putFRc (int instr, double value);
  487. int buildStatusWord ();
  488. void setStatusFromWord (int word);
  489. void setSR (int value, int overflow);
  490. int getNextInterrupt ();
  491. int getVectorNumber ();
  492. int physicalAddressOk (int addr);
  493. int isAligned (int addr);
  494. int getPhysicalWord (int addr);
  495. int getPhysicalWordAndLock (int addr);
  496. void putPhysicalWord (int addr, int value);
  497. void putPhysicalWordAndRelease (int addr, int value);
  498. void releaseMemoryLock (int physAddr);
  499. int inMemoryMappedArea (int addr);
  500. int translate (int addr, int reading, int wantPrinting, int doUpdates);
  501. int getMemoryMappedWord (int physAddr);
  502. void putMemoryMappedWord (int physAddr, int value);
  503. void pushOntoStack (int reg, int value);
  504. int popFromStack (int reg);
  505. void commandShowStack ();
  506. void commandFrame ();
  507. void commandStackUp ();
  508. void commandStackDown ();
  509. int printFrame (int frameNumber, int longPrint);
  510. int printAsciiDataInWidth (int ptr, int width);
  511. void commandHex ();
  512. void commandDecimal ();
  513. void commandAscii ();
  514. void printHexDecimalAscii (int i);
  515. void jumpIfTrueRaRb (int cond, int instr);
  516. void jumpIfTrueData24 (int cond, int instr);
  517. void controlC (int sig);
  518. int randomBetween (int lo, int high);
  519. int genRandom ();
  520. void doTimerEvent ();
  521. void doDiskEvent ();
  522. void doSerialInEvent (int waitForKeystroke);
  523. void doSerialOutEvent ();
  524. void updateTimeOfNextEvent ();
  525. void divide (int a, int b);
  526. void turnOnTerminal ();
  527. void turnOffTerminal ();
  528. char checkForInput (int waitForKeystroke);
  529. int characterAvailableOnStdin ();
  530. void initializeDisk ();
  531. void performDiskIO (int command);
  532. void checkDiskBufferError (int physAddr);
  533. void setSimulationConstants ();
  534. void defaultSimulationConstants ();
  535. void printKPLStmtCode ();
  536. void printCurrentFileLineAndFunction ();
  537.  
  538.  
  539. /* main()
  540. **
  541. ** Scan the command line arguments, then enter into the command loop.
  542. */
  543. main (int argc, char ** argv) {
  544.   int i;
  545.   char * command;
  546.  
  547.   checkBigEndian ();
  548.   checkArithmetic ();
  549.   MIN = -MAX - 1;
  550.   POSITIVE_INFINITY = 1.0 / 0.0;
  551.   NEGATIVE_INFINITY = -1.0 / 0.0;
  552.   processCommandLine (argc, argv);
  553.   terminalInRawMode = 0;
  554.   resetState ();
  555.   signal (SIGINT, controlC);
  556.  
  557.   /* If the "auto go" option (-g) was given, the just begin execution. */
  558.   if (commandOptionG) {
  559.     commandGo (MAX);
  560.     if (executionHalted) {
  561.       printFinalStats ();
  562.       exit (0);
  563.     } else {
  564.       fprintf (stderr, "\n\rEntering machine-level debugger...\n\r");
  565.     }
  566.   }
  567.  
  568.   printf (
  569. "======================================================\n"
  570. "=====                                            =====\n"
  571. "=====         The BLITZ Machine Emulator         =====\n"
  572. "=====                                            =====\n"
  573. "=====  Copyright 2001-2006, Harry H. Porter III  =====\n"
  574. "=====                                            =====\n"
  575. "======================================================\n"
  576. "\n"
  577. "Enter a command at the prompt.  Type 'quit' to exit or 'help' for\n"
  578. "info about commands.\n");
  579.  
  580.   /* Each execution of this loop will read and execute one command. */
  581.   while (1) {
  582.     controlCPressed = 0;  /* Forget about any control-C's */
  583.  
  584.     printf ("> ");
  585.     command = toLower (getToken ());
  586.  
  587.     if (!strcmp (command, "quit") || !strcmp (command, "q")) {
  588.       printFinalStats ();
  589.       exit (0);
  590.     } else if (!strcmp (command, "")) {
  591.       // printf ("BLITZ Emulator: You are in the command-line interface.\n");
  592.       /* ignore empty commands */
  593.     } else if (!strcmp (command, "help") || !strcmp (command, "h")) {
  594.       commandHelp ();
  595.     } else if (!strcmp (command, "info") || !strcmp (command, "i")) {
  596.       commandInfo ();
  597.     } else if (!strcmp (command, "io")) {
  598.       commandIO ();
  599.     } else if (!strcmp (command, "sim")) {
  600.       commandSim ();
  601.     } else if (!strcmp (command, "raw")) {
  602.       commandRaw ();
  603.     } else if (!strcmp (command, "cooked")) {
  604.       commandCooked ();
  605.     } else if (!strcmp (command, "format")) {
  606.       commandFormat ();
  607.     } else if (!strcmp (command, "go") || !strcmp (command, "g")) {
  608.       commandGo (MAX);
  609.     } else if (!strcmp (command, "step") || !strcmp (command, "s")) {
  610.       commandStep ();
  611.     } else if (!strcmp (command, "t")) {
  612.       commandStepHigh ();
  613.     } else if (!strcmp (command, "u")) {
  614.       commandStepHigh2 ();
  615.     } else if (!strcmp (command, "stepn")) {
  616.       commandStepN ();
  617.     } else if (!strcmp (command, "dumpmem") || !strcmp (command, "dm")) {
  618.       commandDumpMemory ();
  619.     } else if (!strcmp (command, "setmem")) {
  620.       commandSetMemory ();
  621.     } else if (!strcmp (command, "read")) {
  622.       commandReadWord ();
  623.     } else if (!strcmp (command, "write")) {
  624.       commandWriteWord ();
  625.     } else if (!strcmp (command, "input")) {
  626.       commandInput ();
  627.     } else if (!strcmp (command, "seti")) {
  628.       commandSetI ();
  629.     } else if (!strcmp (command, "sets")) {
  630.       commandSetS ();
  631.     } else if (!strcmp (command, "setp")) {
  632.       commandSetP ();
  633.     } else if (!strcmp (command, "setz")) {
  634.       commandSetZ ();
  635.     } else if (!strcmp (command, "setv")) {
  636.       commandSetV ();
  637.     } else if (!strcmp (command, "setn")) {
  638.       commandSetN ();
  639.     } else if (!strcmp (command, "cleari")) {
  640.       commandClearI ();
  641.     } else if (!strcmp (command, "clears")) {
  642.       commandClearS ();
  643.     } else if (!strcmp (command, "clearp")) {
  644.       commandClearP ();
  645.     } else if (!strcmp (command, "clearz")) {
  646.       commandClearZ ();
  647.     } else if (!strcmp (command, "clearv")) {
  648.       commandClearV ();
  649.     } else if (!strcmp (command, "clearn")) {
  650.       commandClearN ();
  651.     } else if (!strcmp (command, "setpc")) {
  652.       commandSetPC ();
  653.     } else if (!strcmp (command, "setptbr")) {
  654.       commandSetPTBR ();
  655.     } else if (!strcmp (command, "setptlr")) {
  656.       commandSetPTLR ();
  657.     } else if (!strcmp (command, "pt")) {
  658.       commandPrintPageTable ();
  659.     } else if (!strcmp (command, "trans")) {
  660.       commandTranslate ();
  661.     } else if (!strcmp (command, "cancel")) {
  662.       commandCancel ();
  663.     } else if (!strcmp (command, "add")) {
  664.       commandAdd ();
  665. /***
  666.     } else if (!strcmp (command, "init")) {
  667.       commandInit ();
  668.     } else if (!strcmp (command, "init2")) {
  669.       commandInit2 ();
  670.     } else if (!strcmp (command, "sort")) {
  671.       commandSort ();
  672.     } else if (!strcmp (command, "sort2")) {
  673.       commandSort2 ();
  674. ***/
  675.     } else if (!strcmp (command, "labels")) {
  676.       commandLabels ();
  677.     } else if (!strcmp (command, "find")) {
  678.       commandFind ();
  679.     } else if (!strcmp (command, "find2")) {
  680.       commandFind2 ();
  681.     } else if (!strcmp (command, "reset")) {
  682.       commandReset ();
  683.     } else if (!strcmp (command, "float") || !strcmp (command, "f")) {
  684.       commandAllFloatRegs (1);
  685.     } else if (!strcmp (command, "r")) {
  686.       commandAllRegs (1);
  687.     } else if (!strcmp (command, "r1")) {
  688.       commandReg (1);
  689.     } else if (!strcmp (command, "r2")) {
  690.       commandReg (2);
  691.     } else if (!strcmp (command, "r3")) {
  692.       commandReg (3);
  693.     } else if (!strcmp (command, "r4")) {
  694.       commandReg (4);
  695.     } else if (!strcmp (command, "r5")) {
  696.       commandReg (5);
  697.     } else if (!strcmp (command, "r6")) {
  698.       commandReg (6);
  699.     } else if (!strcmp (command, "r7")) {
  700.       commandReg (7);
  701.     } else if (!strcmp (command, "r8")) {
  702.       commandReg (8);
  703.     } else if (!strcmp (command, "r9")) {
  704.       commandReg (9);
  705.     } else if (!strcmp (command, "r10")) {
  706.       commandReg (10);
  707.     } else if (!strcmp (command, "r11")) {
  708.       commandReg (11);
  709.     } else if (!strcmp (command, "r12")) {
  710.       commandReg (12);
  711.     } else if (!strcmp (command, "r13")) {
  712.       commandReg (13);
  713.     } else if (!strcmp (command, "r14")) {
  714.       commandReg (14);
  715.     } else if (!strcmp (command, "r15")) {
  716.       commandReg (15);
  717.     } else if (!strcmp (command, "f0")) {
  718.       commandFloatReg (0);
  719.     } else if (!strcmp (command, "f1")) {
  720.       commandFloatReg (1);
  721.     } else if (!strcmp (command, "f2")) {
  722.       commandFloatReg (2);
  723.     } else if (!strcmp (command, "f3")) {
  724.       commandFloatReg (3);
  725.     } else if (!strcmp (command, "f4")) {
  726.       commandFloatReg (4);
  727.     } else if (!strcmp (command, "f5")) {
  728.       commandFloatReg (5);
  729.     } else if (!strcmp (command, "f6")) {
  730.       commandFloatReg (6);
  731.     } else if (!strcmp (command, "f7")) {
  732.       commandFloatReg (7);
  733.     } else if (!strcmp (command, "f8")) {
  734.       commandFloatReg (8);
  735.     } else if (!strcmp (command, "f9")) {
  736.       commandFloatReg (9);
  737.     } else if (!strcmp (command, "f10")) {
  738.       commandFloatReg (10);
  739.     } else if (!strcmp (command, "f11")) {
  740.       commandFloatReg (11);
  741.     } else if (!strcmp (command, "f12")) {
  742.       commandFloatReg (12);
  743.     } else if (!strcmp (command, "f13")) {
  744.       commandFloatReg (13);
  745.     } else if (!strcmp (command, "f14")) {
  746.       commandFloatReg (14);
  747.     } else if (!strcmp (command, "f15")) {
  748.       commandFloatReg (15);
  749.     } else if (!strcmp (command, "dis")) {
  750.       commandDis ();
  751.     } else if (!strcmp (command, "d")) {
  752.       commandDis2 ();
  753.     } else if (!strcmp (command, "dec")) {
  754.       commandDecimal ();
  755.     } else if (!strcmp (command, "ascii")) {
  756.       commandAscii ();
  757.     } else if (!strcmp (command, "hex")) {
  758.       commandHex ();
  759.     } else if (!strcmp (command, "fmem")) {
  760.       commandFMem ();
  761.     } else if (!strcmp (command, "stack") || !strcmp (command, "st")) {
  762.       commandShowStack ();
  763.     } else if (!strcmp (command, "frame") || !strcmp (command, "fr")) {
  764.       commandFrame ();
  765.     } else if (!strcmp (command, "up")) {
  766.       commandStackUp ();
  767.     } else if (!strcmp (command, "down")) {
  768.       commandStackDown ();
  769.     } else {
  770.       printf ("Unrecognized command.\n");
  771.       printf ("Enter a command at the prompt.  Type 'quit' to exit or 'help' for info about commands.\n");
  772.     }
  773.   }
  774. }
  775.  
  776.  
  777.  
  778. /* printFinalStats ()
  779. **
  780. ** This routine prints the final statistics.
  781. */
  782. void printFinalStats () {
  783.       printf ("Number of Disk Reads    = %d\n", numberOfDiskReads);
  784.       printf ("Number of Disk Writes   = %d\n", numberOfDiskWrites);
  785.       printf ("Instructions Executed   = %d\n", currentTime-timeSpentAsleep);
  786.       printf ("Time Spent Sleeping     = %d\n", timeSpentAsleep);
  787.       printf ("    Total Elapsed Time  = %d\n", currentTime);
  788. }
  789.  
  790.  
  791.  
  792. /* checkBigEndian ()
  793. **
  794. ** This routine checks to make sure the machine running this
  795. ** program uses big-endian byte ordering and aborts if not.
  796. */
  797. void checkBigEndian () {
  798.   union fourBytes {
  799.     char chars [4];
  800.     unsigned int i;
  801.   } fourBytes;
  802.   fourBytes.chars[0] = 0x12;
  803.   fourBytes.chars[1] = 0x34;
  804.   fourBytes.chars[2] = 0x56;
  805.   fourBytes.chars[3] = 0x78;
  806.   if (fourBytes.i != 0x12345678) {
  807.     fatalError ("This program only runs on Big-Endian computers");
  808.   }
  809. }
  810.  
  811.  
  812.  
  813. /* checkArithmetic ()
  814. **
  815. ** This routine checks to make sure the machine running this
  816. ** programs implements "int" integers with 32 bit arithmetic and
  817. ** doubles with 64 bit floating-point numbers.
  818. */
  819. void checkArithmetic () {
  820.   int x;
  821.   x = 0x00005678;
  822.   x = x << 16;
  823.   x = x >> 16;
  824.   if (x != 0x00005678) {
  825.     fatalError ("This machine does not support 32 bit integer arithmetic");
  826.   }
  827.   if (sizeof(int) != 4) {
  828.     fatalError ("This machine does not support 32 bit integer arithmetic");
  829.   }
  830.   if (sizeof(double) != 8) {
  831.     fatalError ("This machine does not support 64 bit double precision");
  832.   }
  833. }
  834.  
  835.  
  836.  
  837. /* isNegZero (double)  -->  bool
  838. **
  839. ** This routine returns true if the double is negative-zero.
  840. */
  841. int isNegZero (double d) {
  842.   int * p;
  843.   p = (int *) &d;
  844.   if ((*p == 0x80000000) && (*(++p) == 0x00000000)) {
  845.     return 1;
  846.   } else {
  847.     return 0;
  848.   }
  849. }
  850.  
  851.  
  852.  
  853. /* processCommandLine (argc, argv)
  854. **
  855. ** This routine processes the command line options.
  856. */
  857. void processCommandLine (int argc, char ** argv) {
  858.   int argCount;
  859.   int len;
  860.   int gotGOption = 0;
  861.   int gotRawOption = 0;
  862.   int gotWaitOption = 0;
  863.  
  864.   /* Each iteration of this loop looks at the next argument.  In some
  865.      cases (like "-o a.out") one iteration will scan two tokens. */
  866.   for (argc--, argv++; argc > 0; argc -= argCount, argv += argCount) {
  867.     argCount = 1;
  868.  
  869.     /* Scan the -h option */
  870.     if (!strcmp (*argv, "-h")) {
  871.       commandLineHelp ();
  872.       exit (1);
  873.  
  874.     /* Scan the -g option */
  875.     } else if (!strcmp (*argv, "-g")) {
  876.       commandOptionG = 1;
  877.       if (gotGOption) {
  878.         badOption ("Multiple occurences of the -g option");
  879.       } else {
  880.         gotGOption = 1;
  881.       }
  882.  
  883.     /* Scan the -raw option */
  884.     } else if (!strcmp (*argv, "-raw")) {
  885.       commandOptionRaw = 1;
  886.       if (gotRawOption) {
  887.         badOption ("Multiple occurences of the -raw option");
  888.       } else {
  889.         gotRawOption = 1;
  890.       }
  891.  
  892.     /* Scan the -wait option */
  893.     } else if (!strcmp (*argv, "-wait")) {
  894.       commandOptionWait = 1;
  895.       if (gotWaitOption) {
  896.         badOption ("Multiple occurences of the -wait option");
  897.       } else {
  898.         gotWaitOption = 1;
  899.       }
  900.  
  901.     /* Scan the -r option */
  902.     } else if (!strcmp (*argv, "-r")) {
  903.       if (argc <= 1) {
  904.         badOption ("Expecting integer after -r option");
  905.       } else {
  906.         argCount++;
  907.         randSeedFromOption = atoi (*(argv+1));  /* Extra chars after int ignored */
  908.         if (randSeedFromOption <= 0) {
  909.           badOption ("Invalid integer after -r option");
  910.         }
  911.         if (commandOptionRand) {
  912.           badOption ("Multiple occurences of the -r option");
  913.         } else {
  914.           commandOptionRand = 1;
  915.         }
  916.       }
  917.  
  918.     /* Scan the -d option, which should be followed by a file name */
  919.     } else if (!strcmp (*argv, "-d")) {
  920.       if (argc <= 1) {
  921.         badOption ("Expecting filename after -d option");
  922.       } else {
  923.         argCount++;
  924.         if (diskFileName == NULL) {
  925.           diskFileName = *(argv+1);
  926.         } else {
  927.           badOption ("Invalid command line - multiple DISK files");
  928.         }
  929.       }
  930.  
  931.     /* Scan the -i option, which should be followed by a file name */
  932.     } else if (!strcmp (*argv, "-i")) {
  933.       if (argc <= 1) {
  934.         badOption ("Expecting filename after -i option");
  935.       } else {
  936.         argCount++;
  937.         if (termInputFileName == NULL) {
  938.           termInputFileName = *(argv+1);
  939.         } else {
  940.           badOption ("Multiple occurences of the -i option");
  941.         }
  942.       }
  943.  
  944.     /* Scan the -o option, which should be followed by a file name */
  945.     } else if (!strcmp (*argv, "-o")) {
  946.       if (argc <= 1) {
  947.         badOption ("Expecting filename after -o option");
  948.       } else {
  949.         argCount++;
  950.         if (termOutputFileName == NULL) {
  951.           termOutputFileName = *(argv+1);
  952.         } else {
  953.           badOption ("Multiple occurences of the -o option");
  954.         }
  955.       }
  956.  
  957.     /* Deal with any invalid options that begin with "-", such as "-qwerty" */
  958.     } else if ((*argv)[0] == '-') {
  959.       fprintf (
  960.         stderr,
  961.         "BLITZ Emulator Error: Invalid command line option (%s); Use -h for help display\n",
  962.         *argv);
  963.       exit (1);
  964.     /* This token will be interpreted as the a.out file name. */
  965.     } else {
  966.       if (executableFileName == NULL) {
  967.         executableFileName = *argv;
  968.       } else {
  969.         badOption ("Invalid command line - multiple input files");
  970.       }
  971.  
  972.     }
  973.   }
  974.  
  975.   /* Check that -raw and -i don't both occur. */
  976.   if (commandOptionRaw && (termInputFileName != NULL)) {
  977.     badOption ("Options -raw and -i are incompatible");
  978.   }
  979.  
  980.   /* Figure out the name of the a.out file. */
  981.   if (executableFileName == NULL) {
  982.     executableFileName = "a.out";
  983.   }
  984.  
  985.   /* Open the a.out file. */
  986.   executableFile = fopen (executableFileName, "r");
  987.   if (executableFile == NULL) {
  988.     fprintf (stderr,
  989.              "BLITZ Emulator Error: Input file \"%s\" could not be opened\n",
  990.              executableFileName);
  991.     exit (1);
  992.   }
  993.  
  994.   /* Figure out the name of the DISK file. */
  995.   if (diskFileName == NULL) {
  996.     diskFileName = "DISK";
  997.   }
  998.  
  999.   /* Open the TERM INPUT file. */
  1000.   if (termInputFileName == NULL) {
  1001.     termInputFile = stdin;
  1002.   } else {
  1003.     if (termOutputFileName != NULL) {
  1004.       if (strcmp(termInputFileName, termOutputFileName) == 0) {
  1005.         fprintf (stderr,
  1006.                  "BLITZ Emulator Error: Terminal input and output files must be different\n");
  1007.         exit (1);
  1008.       }
  1009.     }
  1010.     termInputFile = fopen (termInputFileName, "r");
  1011.     if (termInputFile == NULL) {
  1012.       fprintf (stderr,
  1013.                "BLITZ Emulator Error: Input file \"%s\" could not be opened for reading\n",
  1014.                termInputFileName);
  1015.       exit (1);
  1016.     }
  1017.   }
  1018.  
  1019.   /* Open the TERM OUTPUT file. */
  1020.   if (termOutputFileName == NULL) {
  1021.     termOutputFile = stdout;
  1022.   } else {
  1023.     termOutputFile = fopen (termOutputFileName, "w");
  1024.     if (termOutputFile == NULL) {
  1025.       fprintf (stderr,
  1026.                "BLITZ Emulator Error: Output file \"%s\" could not be opened for writing\n",
  1027.                termOutputFileName);
  1028.       exit (1);
  1029.     }
  1030.   }
  1031. }
  1032.  
  1033.  
  1034.  
  1035. /* badOption (msg)
  1036. **
  1037. ** This routine prints a message on stderr and then aborts this program.
  1038. */
  1039. void badOption (char * msg) {
  1040.   fprintf (stderr, "BLITZ Emulator Error: %s;  Use -h for help display\n", msg);
  1041.   exit (1);
  1042. }
  1043.  
  1044.  
  1045.  
  1046. /* fatalError (msg)
  1047. **
  1048. ** This routine prints the given error message on stderr and calls errorExit().
  1049. */
  1050. void fatalError (char * msg) {
  1051.   turnOffTerminal ();
  1052.   fprintf (stderr, "\nBLITZ Emulator Error: %s\n", msg);
  1053.   /* raise (SIGSEGV);  Produce a core dump. */
  1054.   errorExit ();
  1055. }
  1056.  
  1057.  
  1058.  
  1059. /* errorExit ()
  1060. **
  1061. ** This routine performs any final cleanup and calls exit(1).
  1062. */
  1063. void errorExit () {
  1064.   exit (1);
  1065. }
  1066.  
  1067.  
  1068.  
  1069. /* commandLineHelp ()
  1070. **
  1071. ** This routine prints some documentation.  It is invoked whenever
  1072. ** the -h option is used on the command line.
  1073. */
  1074. void commandLineHelp () {
  1075.   printf (
  1076. "========================================\n"
  1077. "=====                              =====\n"
  1078. "=====  The BLITZ Machine Emulator  =====\n"
  1079. "=====                              =====\n"
  1080. "========================================\n"
  1081. "\n"
  1082. "Copyright 2001-2006, Harry H. Porter III\n"
  1083. "========================================\n"
  1084. "  Original Author:\n"
  1085. "    02/05/01 - Harry H. Porter III\n"
  1086. /*
  1087.    "  Modifcations by:\n"
  1088.    "    09/28/04 - Harry - Fix bug with randomSeed, disk errno\n"
  1089.    "    11/26/04 - Harry - Fix bugs with serial input\n"
  1090.    "    03/15/06 - Harry - Renamed SPANK to BLITZ\n"
  1091. */
  1092. "\n"
  1093. "Command Line Options\n"
  1094. "====================\n"
  1095. "  These command line options may be given in any order.\n"
  1096. "    filename\n"
  1097. "       The input executable file.  If missing, \"a.out\" will be used.\n"
  1098. "    -h\n"
  1099. "       Print this help info.  Ignore other options and exit.\n"
  1100. "    -d filename\n"
  1101. "       Disk file name.  If missing, \"DISK\" will be used.\n"
  1102. "    -g\n"
  1103. "       Automatically begin emulation of the a.out program, bypassing\n"
  1104. "       the command line interface.\n"
  1105. "    -i filename\n"
  1106. "       Terminal input file name.  If missing, \"stdin\" will be used.\n"
  1107. "    -o filename\n"
  1108. "       Terminal output file name.  If missing, \"stdout\" will be used.\n"
  1109. "    -r integer\n"
  1110. "       Set the random seed to the given integer, which must be > 0.\n"
  1111. "    -raw\n"
  1112. "       User input for BLITZ terminal I/O will be in \"raw\" mode; the\n"
  1113. "       default is \"cooked\", in which case the running BLITZ code\n"
  1114. "       is relieved from echoing keystrokes, processing backspaces, etc.\n"
  1115. "    -wait\n"
  1116. "       This option applies only when input is coming from an interactive\n"
  1117. "       terminal and a 'wait' instruction is executed with no other pending\n"
  1118. "       interrupts.  Without this option, execution will halt; with it the\n"
  1119. "       emulator will wait for input.\n"
  1120. );
  1121.  
  1122. }
  1123.  
  1124.  
  1125.  
  1126. /* getToken ()
  1127. **
  1128. ** This routine reads a single token from the input and returns it.
  1129. ** A token is any sequence of characters not containing whitespace.
  1130. ** Leading and trailing white space is removed.
  1131. */
  1132. char * getToken () {
  1133.   int i;
  1134.   fflush (stdout);
  1135.   fgets (inputBuffer, sizeof(inputBuffer), stdin);
  1136.  
  1137. /***
  1138.   printf ("inputBuffer = \n");
  1139.   for (i=0; inputBuffer[i] != '\0'; i++) {
  1140.     printf ("%02X ", (int) inputBuffer[i]);
  1141.   }
  1142.   printf ("\n");
  1143. ***/
  1144.  
  1145.   if (feof (stdin)) {
  1146.     printf ("EOF ignored: Type 'q' to exit.\n");
  1147.     fseek (stdin, 0l, SEEK_SET);
  1148.     inputBuffer [0] = '\0';
  1149.     return inputBuffer;
  1150.     /*  exit (0);  */
  1151.   }
  1152.   /* Overwrite the \n with \0 to remove it. */
  1153.   inputBuffer [strlen (inputBuffer)-1] = '\0';
  1154.   return trimToken (inputBuffer);
  1155. }
  1156.  
  1157.  
  1158.  
  1159. /* trimToken (str)
  1160. **
  1161. ** This routine is passed a pointer to a string.  It trims leading and
  1162. ** trailing whitespace off of the string and returns a pointer to the
  1163. ** new string.  The string is updated in place: a \0 character is written
  1164. ** into the string to trim trailing white space.  The string is assumed to
  1165. ** contain a single token, and an error is printed if there is more than one
  1166. ** token.
  1167. */
  1168. char * trimToken (char * str) {
  1169.   char * p, * end;
  1170.   char * start = str;
  1171.   /* Set start to point to the first non-whitespace character. */
  1172.   while (1) {
  1173.     if ((*start != ' ') && (*start != '\t')) {
  1174.       break;
  1175.     }
  1176.     start++;
  1177.   }
  1178.   /* Set p to point to the next whitespace or \0 character. */
  1179.   p = start;
  1180.   while (1) {
  1181.     if ((*p == ' ') || (*p == '\t') || (*p == '\0')) {
  1182.       break;
  1183.     }
  1184.     p++;
  1185.   }
  1186.   end = p;
  1187.   /* Make sure that there is nothing but whitespace until the \0 character. */
  1188.   while (*p != '\0') {
  1189.     if ((*p != ' ') && (*p != '\t')) {
  1190.       printf ("WARNING: Input characters (\"%s\") after the first word were ignored.\n", p);
  1191.       break;
  1192.     }
  1193.     p++;
  1194.   }
  1195.   /* Store \0 character after the last character of the token. */
  1196.   *end = '\0';
  1197.   return start;
  1198. }
  1199.  
  1200.  
  1201.  
  1202. /* toLower (str)
  1203. **
  1204. ** This routine is passed a string.  It runs through it, converting any
  1205. ** uppercase letters to lowercase.  It changes the string in place.  It
  1206. ** returns a pointer to the string.
  1207. */
  1208. char * toLower (char * str) {
  1209.   char * p = str;
  1210.   while (*p) {
  1211.     if (('A' <= *p) && (*p <= 'Z')) {
  1212.       *p = *p + ('a' - 'A');
  1213.     }
  1214.     p++;
  1215.   }
  1216.   return str;
  1217. }
  1218.  
  1219.  
  1220.  
  1221. /* readInteger (file)
  1222. **
  1223. ** Read an integer (4-bytes, binary) from the given file and return it.
  1224. */
  1225. int readInteger (FILE * file) {
  1226.   int i, numItemsRead;
  1227.   errno = 0;
  1228.   numItemsRead = fread (&i, 4, 1, file);
  1229.   if (numItemsRead != 1) {
  1230.     if (errno) perror ("Error when reading from binary file");
  1231.     fatalError ("Problem reading from file");
  1232.   }
  1233.   return i;
  1234. }
  1235.  
  1236.  
  1237.  
  1238. /* readByte (file)
  1239. **
  1240. ** Read 1 byte from the given file and return it as an integer.
  1241. */
  1242. int readByte (FILE * file) {
  1243.   int i, numBytesRead;
  1244.   char c;
  1245.   errno = 0;
  1246.   numBytesRead = fread (&c, 1, 1, file);
  1247.   if (numBytesRead != 1) {
  1248.     if (errno) perror ("Error when reading from binary file");
  1249.     fatalError ("Problem reading from file");
  1250.   }
  1251.   i = c;
  1252.   return i;
  1253. }
  1254.  
  1255.  
  1256.  
  1257. /* roundUpToMultipleOf (i, p)
  1258. **
  1259. ** This routine rounds i up to a multiple of p and returns the result.
  1260. */
  1261. int roundUpToMultipleOf (int i, int p) {
  1262.   if ((i < 0) || (p <= 0)) {
  1263.     fatalError ("PROGRAM LOGIC ERROR: Bad arg in roundUpToMultipleOf()");
  1264.   }
  1265.   if (i % p > 0) {
  1266.     return (i / p + 1) * p;
  1267.   }
  1268.   return i;
  1269. }
  1270.  
  1271.  
  1272.  
  1273. /* printMemory (ptr, n, addr)
  1274. **
  1275. ** This routine dumps n bytes of memory (located at "ptr") in hex.  It
  1276. ** Labels the bytes starting with "addr".
  1277. */
  1278. void printMemory (char * ptr, int n, int addr) {
  1279.    pmCount = n;
  1280.    pmPtr = ptr;
  1281.  
  1282.    /* Each execution of this loop prints a single output line. */
  1283.    get16Bytes ();
  1284.    while (pmSize > 0) {
  1285.      /* The following test doesn't work well, since Unix uses huge output
  1286.         buffers and these tend to get filled quickly. */
  1287.      if (controlCPressed) {
  1288.        controlCPressed = 0;
  1289.        return;
  1290.      }
  1291.      putlong (addr);
  1292.      printf (":  ");
  1293.      printline ();
  1294.      addr = addr + 16;
  1295.      get16Bytes ();
  1296.    }
  1297.  
  1298. }
  1299.  
  1300.  
  1301.  
  1302. /* get16Bytes ()
  1303. **
  1304. ** This routine reads in the next 16 bytes from memory and
  1305. ** places them in the array named "pmRow", setting "pmSize" to
  1306. ** be the number of bytes moved.  "pmSize" will be less than
  1307. ** 16 if EOF was encountered, and may possibly be 0.
  1308. */
  1309. void get16Bytes () {
  1310.   int c;
  1311.   pmSize = 0;
  1312.   c = getNextByte ();
  1313.   while (c != -999) {
  1314.     pmRow [pmSize++] = c;
  1315.     if (pmSize >= 16) break;
  1316.     c = getNextByte ();
  1317.   }
  1318. }
  1319.  
  1320.  
  1321.  
  1322. /* getNextByte () 
  1323. **
  1324. ** Get the next byte from memory, from the location pointed to by
  1325. ** "pmPtr", incrementing "pmPtr" and decrementing the counter "pmCount."
  1326. ** This routine will return it as an integer, or return -999 if pmCount <= 0.
  1327. */
  1328. int getNextByte () {
  1329.   if (pmCount <= 0) return -999;
  1330.   pmCount--;
  1331.   return *(pmPtr++);
  1332. }
  1333.  
  1334.  
  1335.  
  1336. /* putlong (i)
  1337. **
  1338. ** This routine is passed an integer, which it prints as 8 hex digits.
  1339. */
  1340. void putlong (int i) {
  1341.   printByte ((i>>24) & 0x000000ff);
  1342.   printByte ((i>>16) & 0x000000ff);
  1343.   printByte ((i>>8) & 0x000000ff);
  1344.   printByte ((i>>0) & 0x000000ff);
  1345. }
  1346.  
  1347.  
  1348.  
  1349. /* puthalf (i)
  1350. **
  1351. ** This routine is passed an integer, which it prints as 4 hex digits.
  1352. */
  1353. void puthalf (int i) {
  1354.   printByte ((i>>8) & 0x000000ff);
  1355.   printByte ((i>>0) & 0x000000ff);
  1356. }
  1357.  
  1358.  
  1359.  
  1360. /* printline ()
  1361. **
  1362. ** This routine prints the current 'pmRow'.
  1363. */
  1364. void printline () {
  1365.   int i, c;
  1366.   if (pmSize > 0) {
  1367.     i = 0;
  1368.     while (i<16) {
  1369.       if (i < pmSize) {
  1370.         printByte (pmRow[i]);
  1371.       } else {
  1372.         printf ("  ");
  1373.       }
  1374.       i++;
  1375.       if ((i%2) == 0) {
  1376.         putchar (' ');
  1377.       }
  1378.       if ((i%4) == 0) {
  1379.         putchar (' ');
  1380.       }
  1381.     }
  1382.     printf ("  ");
  1383.     for (i=0; i<pmSize; i++) {
  1384.       c = pmRow[i];
  1385.       if ((c>=' ') && (c <= '~')) {
  1386.         putchar (c);
  1387.       } else {
  1388.         putchar ('.');
  1389.       }
  1390.     }
  1391.     printf ("\n");
  1392.   }
  1393. }
  1394.  
  1395.  
  1396.  
  1397. /* printByte (c)
  1398. **
  1399. ** This routine is passed a byte (i.e., an integer -128..255) which
  1400. ** it prints as 2 hex characters.  If passed a number out of that
  1401. ** range, it outputs nothing.
  1402. */
  1403. void printByte (int c) {
  1404.   int i;
  1405.   if (c<0) c = c + 256;
  1406.   if ((c >= 0) && (c <= 255)) {
  1407.     i = (c & 0x000000f0) >> 4;
  1408.     if (i < 10) {
  1409.       putchar ('0' + i);
  1410.     } else {
  1411.       putchar ('A' + i - 10);
  1412.     }
  1413.     i = (c & 0x0000000f) >> 0;
  1414.     if (i < 10) {
  1415.       putchar ('0' + i);
  1416.     } else {
  1417.       putchar ('A' + i - 10);
  1418.     }
  1419.   }
  1420. }
  1421.  
  1422.  
  1423.  
  1424. /* bytesEqual (p, q, lengthP, lengthQ)
  1425. **
  1426. ** This function is passed two pointers to blocks of bytes, and a
  1427. ** length.  It compares the two sequences of bytes and returns true iff
  1428. ** they are both equal.
  1429. */
  1430. int bytesEqual (char * p, char * q, int lengthP, int lengthQ) {
  1431.   if (lengthP != lengthQ) return 0;
  1432.   for (; lengthP>0; lengthP--, p++, q++) {
  1433.     if (*p != *q) return 0;
  1434.   }
  1435.   return 1;
  1436. }
  1437.  
  1438.  
  1439.  
  1440. /* commandHelp ()
  1441. **
  1442. ** This routine prints the help command material.
  1443. */
  1444. void commandHelp () {
  1445.   printf (
  1446. "===========================================================================\n"
  1447. "This program accepts commands typed into the terminal.  Each command\n"
  1448. "should be typed without any arguments; the commands will prompt for\n"
  1449. "arguments when needed.  Case is not significant.  Some abbreviations\n"
  1450. "are allowed, as shown.  Typing control-C will halt execution.\n"
  1451. "\n"
  1452. "The available commands are:\n"
  1453. "\n"
  1454. "  quit    - Terminate this program\n"
  1455. "  q         \n"
  1456. "  help    - Produce this display\n"
  1457. "  h         \n"
  1458. "  info    - Display the current state of the machine\n"
  1459. "  i         \n"
  1460. "  dumpMem - Display the contents of memory\n"
  1461. "  dm        \n"
  1462. "  setmem  - Used to alter memory contents\n"
  1463. "  fmem    - Display floating point values from memory\n"
  1464. "  go      - Begin or resume BLITZ instruction execution\n"
  1465. "  g         \n"
  1466. "  step    - Single step; execute one machine-level instruction\n"
  1467. "  s         \n"
  1468. "  t       - Single step; execute one KPL statement\n"
  1469. "  u       - Execute continuously until next KPL call, send, or return statement\n"
  1470. "  stepn   - Execute N machine-level instructions\n"
  1471. "  r       - Display all the integer registers\n"
  1472. "  r1      - Change the value of register r1\n"
  1473. "   ...       \n"
  1474. "  r15     - Change the value of register r15\n"
  1475. "  float   - Display all the floating-point registers\n"
  1476. "  f         \n"
  1477. "  f0      - Change the value of floating-point register f0\n"
  1478. "   ...       \n"
  1479. "  f15     - Change the value of floating-point register f15\n"
  1480. "  dis     - Disassemble several instructions\n"
  1481. "  d       - Disassemble several instructions from the current location\n"
  1482. "  hex     - Convert a user-entered hex number into decimal and ascii\n"
  1483. "  dec     - Convert a user-entered decimal number into hex and ascii\n"
  1484. "  ascii   - Convert a user-entered ascii char into hex and decimal\n"
  1485. "  setI    - Set the I bit in the Status Register\n"
  1486. "  setS    - Set the S bit in the Status Register\n"
  1487. "  setP    - Set the P bit in the Status Register\n"
  1488. "  setZ    - Set the Z bit in the Status Register\n"
  1489. "  setV    - Set the V bit in the Status Register\n"
  1490. "  setN    - Set the N bit in the Status Register\n"
  1491. "  clearI  - Clear the I bit in the Status Register\n"
  1492. "  clearS  - Clear the S bit in the Status Register\n"
  1493. "  clearP  - Clear the P bit in the Status Register\n"
  1494. "  clearZ  - Clear the Z bit in the Status Register\n"
  1495. "  clearV  - Clear the V bit in the Status Register\n"
  1496. "  clearN  - Clear the N bit in the Status Register\n"
  1497. "  setPC   - Set the Program Counter (PC)\n"
  1498. "  setPTBR - Set the Page Table Base Register (PTBR)\n"
  1499. "  setPTLR - Set the Page Table Length Register (PTLR)\n"
  1500. "  pt      - Display the Page Table\n"
  1501. "  trans   - Perform page table translation on a single address\n"
  1502. "  cancel  - Cancel all pending interrupts\n"
  1503. "  labels  - Display the label table\n"
  1504. "  find    - Find a label by name\n"
  1505. "  find2   - Find a label by value\n"
  1506. "  add     - Add a new label, inserting it into the indexes\n"
  1507. "  reset   - Reset the machine state and re-read the a.out file\n"
  1508. "  io      - Display the state of the I/O devices\n"
  1509. "  read    - Read a word from memory-mapped I/O region\n"
  1510. "  write   - Write a word to memory-mapped I/O region\n"
  1511. "  raw     - Switch serial input to raw mode\n"
  1512. "  cooked  - Switch serial input to cooked mode\n"
  1513. "  input   - Enter input characters for future serial I/O input\n"
  1514. "  format  - Create and format a BLITZ disk file\n"
  1515. "  sim     - Display the current simulation constants\n"
  1516. "  stack   - Display the KPL calling stack\n"
  1517. "  st        \n"
  1518. "  frame   - Display the current activation frame\n"
  1519. "  fr        \n"
  1520. "  up      - Move up in the activation frame stack\n"
  1521. "  down    - Move down in the activation frame stack\n"
  1522. "\n"
  1523. "===========================================================================\n");
  1524.  
  1525. }
  1526.  
  1527.  
  1528.  
  1529. /* commandAllRegs ()
  1530. **
  1531. ** This routine prints the registers (either User or Sytstem, depending
  1532. ** on the current mode.
  1533. */
  1534. void commandAllRegs () {
  1535.   int i;
  1536.   if (!statusS) {
  1537.     printf ("=====  USER REGISTERS  =====\n");
  1538.     for (i=0; i<=9; i++) {
  1539.       printf ("  r%d  = ", i);
  1540.       printNumberNL (userRegisters [i]);
  1541.     }
  1542.     for (i=10; i<=15; i++) {
  1543.       printf ("  r%d = ", i);
  1544.       printNumberNL (userRegisters [i]);
  1545.     }
  1546.   } else {
  1547.     printf ("=====  SYSTEM REGISTERS  =====\n");
  1548.     for (i=0; i<=9; i++) {
  1549.       printf ("  r%d  = ", i);
  1550.       printNumberNL (systemRegisters [i]);
  1551.     }
  1552.     for (i=10; i<=15; i++) {
  1553.       printf ("  r%d = ", i);
  1554.       printNumberNL (systemRegisters [i]);
  1555.     }
  1556.   }
  1557.   printf ("==============================\n");
  1558. }
  1559.  
  1560.  
  1561.  
  1562. /* commandAllFloatRegs ()
  1563. **
  1564. ** This routine prints the floating-point registers.
  1565. */
  1566. void commandAllFloatRegs () {
  1567.   int i;
  1568.   double d;
  1569.   printf ("=====  FLOATING-POINT REGISTERS  =====\n");
  1570.   for (i=0; i<=9; i++) {
  1571.     d = floatRegisters [i];
  1572.     printf ("  f%d  = ", i);
  1573.     printDouble (d);
  1574.   }
  1575.   for (i=10; i<=15; i++) {
  1576.     d = floatRegisters [i];
  1577.     printf ("  f%d = ", i);
  1578.     printDouble (d);
  1579.   }
  1580.   printf ("======================================\n");
  1581. }
  1582.  
  1583.  
  1584.  
  1585. /* printDouble (d)
  1586. **
  1587. ** This rouinte prints out a floating-point number.  It checks for
  1588. ** NAN, POSITIVE-INFINITY, and NEGATIVE-INFINITY and prints them
  1589. ** appropriately.  Numbers are printed in the form:
  1590. **
  1591. **       4484ea0c eff1a9b4   ( value = 1.23456e+22 )
  1592. */
  1593. void printDouble (double d) {
  1594.   double value = d;
  1595.   int * p;
  1596.   p = (int *) (& value);
  1597.   printf ("0x");
  1598.   putlong (*p);
  1599.   printf (" ");
  1600.   putlong (*(p+1));
  1601.   printf ("   ( value = ", *p, *(p+1));
  1602.   printDoubleVal (value);
  1603.   printf (" )\n");
  1604. }
  1605.  
  1606.  
  1607.  
  1608. /* printDoubleVal (d)
  1609. **
  1610. ** This routine is passed a floating-point number.  It checks for
  1611. ** NAN, POSITIVE-INFINITY, and NEGATIVE-INFINITY and prints them
  1612. ** appropriately.  Numbers are printed in the form:
  1613. **
  1614. **       1.23456e+22
  1615. **       Not-a-number
  1616. **       Positive-Infinity
  1617. **       Negative-Infinity
  1618. **       0
  1619. **       Negative-Zero
  1620. */
  1621. void printDoubleVal (double d) {
  1622.   if (isnan(d)) {
  1623.     printf ("Not-a-Number");
  1624.   } else if (d == POSITIVE_INFINITY) {
  1625.     printf ("Positive-Infinity");
  1626.   } else if (d == NEGATIVE_INFINITY) {
  1627.     printf ("Negative-Infinity");
  1628.   } else if (isNegZero (d)) {
  1629.     printf ("Negative-Zero");
  1630.   } else {
  1631.     printf ("%.15g", d);
  1632.   }
  1633. }
  1634.  
  1635.  
  1636.  
  1637.  
  1638. /* commandInfo ()
  1639. **
  1640. ** This routine prints the current state of the machine.
  1641. */
  1642. void commandInfo () {
  1643.   int i;
  1644.   printf ("============================\n");
  1645.   printInfo ();
  1646.   printf ("=====  USER REGISTERS  =====\n");
  1647.   for (i=0; i<=9; i++) {
  1648.     printf ("  r%d  = ", i);
  1649.     printNumberNL (userRegisters [i]);
  1650.   }
  1651.   for (i=10; i<=15; i++) {
  1652.     printf ("  r%d = ", i);
  1653.     printNumberNL (userRegisters [i]);
  1654.   }
  1655.   printf ("=====  SYSTEM REGISTERS  =====\n");
  1656.   for (i=0; i<=9; i++) {
  1657.     printf ("  r%d  = ", i);
  1658.     printNumberNL (systemRegisters [i]);
  1659.   }
  1660.   for (i=10; i<=15; i++) {
  1661.     printf ("  r%d = ", i);
  1662.     printNumberNL (systemRegisters [i]);
  1663.   }
  1664.   commandAllFloatRegs ();
  1665.   printf ("  PC   = ");
  1666.   printNumberNL (pc);
  1667.   printf ("  PTBR = ");
  1668.   printNumberNL (ptbr);
  1669.   printf ("  PTLR = ");
  1670.   printNumberNL (ptlr);
  1671.   printf ("                        ---- ----  ---- ----  ---- ----  --IS PZVN\n");
  1672.   printf ("  SR   = 0x%08X  =  0000 0000  0000 0000  0000 0000  00",
  1673.           buildStatusWord ());
  1674.   if (statusI) printf ("1");   else printf ("0");
  1675.   if (statusS) printf ("1 ");   else printf ("0 ");
  1676.   if (statusP) printf ("1");  else printf ("0");
  1677.   if (statusZ) printf ("1");   else printf ("0");
  1678.   if (statusV) printf ("1");   else printf ("0");
  1679.   if (statusN) printf ("1\n"); else printf ("0\n");
  1680.   if (statusI)
  1681.       printf ("           I = 1   Interrupts Enabled\n");
  1682.     else
  1683.       printf ("           I = 0   Interrupts Disabled\n");
  1684.   if (statusS)
  1685.       printf ("           S = 1   System Mode\n");
  1686.     else
  1687.       printf ("           S = 0   User Mode\n");
  1688.   if (statusP)
  1689.       printf ("           P = 1   Paging Enabled\n");
  1690.     else
  1691.       printf ("           P = 0   Paging Disabled\n");
  1692.   if (statusZ)
  1693.       printf ("           Z = 1   Zero\n");
  1694.     else
  1695.       printf ("           Z = 0   Not Zero\n");
  1696.   if (statusV)
  1697.       printf ("           V = 1   Overflow Occurred\n");
  1698.     else
  1699.       printf ("           V = 0   No Overflow\n");
  1700.   if (statusN)
  1701.       printf ("           N = 1   Negative\n");
  1702.     else
  1703.       printf ("           N = 0   Not Negative\n");
  1704.   printf ("==============================\n");
  1705.   printPendingInterrupts ();
  1706.   printf ("  System Trap Number                = 0x%08X\n", systemTrapNumber);
  1707.   printf ("  Page Invalid Offending Address    = 0x%08X\n", pageInvalidOffendingAddress);
  1708.   printf ("  Page Readonly Offending Address   = 0x%08X\n", pageReadonlyOffendingAddress);
  1709.   printf ("  Time of next timer event          = %d\n", timeOfNextTimerEvent);
  1710.   printf ("  Time of next disk event           = %d\n", timeOfNextDiskEvent);
  1711.   printf ("  Time of next serial in event      = %d\n", timeOfNextSerialInEvent);
  1712.   printf ("  Time of next serial out event     = %d\n", timeOfNextSerialOutEvent);
  1713.   printf ("    Current Time                    = %d\n", currentTime);
  1714.   printf ("    Time of next event              = %d\n", timeOfNextEvent);
  1715.   printf ("    Time Spent Sleeping             = %d\n", timeSpentAsleep);
  1716.   printf ("      Instructions Executed         = %d\n", currentTime-timeSpentAsleep);
  1717.   printf ("  Number of Disk Reads              = %d\n", numberOfDiskReads);
  1718.   printf ("  Number of Disk Writes             = %d\n", numberOfDiskWrites);
  1719.   printf ("==============================\n");
  1720.   printAboutToExecute ();
  1721.   printKPLStmtCode ();
  1722. }
  1723.  
  1724.  
  1725.  
  1726. /* printPendingInterrupts ()
  1727. **
  1728. ** This routine prints the current state of "interruptsSignaled".
  1729. */
  1730. void printPendingInterrupts () {
  1731.   printf ("  Pending Interrupts                = 0x%08X\n", interruptsSignaled);
  1732.   if (interruptsSignaled & POWER_ON_RESET)
  1733.     printf ("    POWER_ON_RESET\n");
  1734.   if (interruptsSignaled & TIMER_INTERRUPT)
  1735.     printf ("    TIMER_INTERRUPT\n");
  1736.   if (interruptsSignaled & DISK_INTERRUPT)
  1737.     printf ("    DISK_INTERRUPT\n");
  1738.   if (interruptsSignaled & SERIAL_INTERRUPT)
  1739.     printf ("    SERIAL_INTERRUPT\n");
  1740.   if (interruptsSignaled & HARDWARE_FAULT)
  1741.     printf ("    HARDWARE_FAULT\n");
  1742.   if (interruptsSignaled & ILLEGAL_INSTRUCTION)
  1743.     printf ("    ILLEGAL_INSTRUCTION\n");
  1744.   if (interruptsSignaled & ARITHMETIC_EXCEPTION)
  1745.     printf ("    ARITHMETIC_EXCEPTION_EXCEPTION\n");
  1746.   if (interruptsSignaled & ADDRESS_EXCEPTION)
  1747.     printf ("    ADDRESS_EXCEPTION\n");
  1748.   if (interruptsSignaled & PAGE_INVALID_EXCEPTION)
  1749.     printf ("    PAGE_INVALID_EXCEPTION\n");
  1750.   if (interruptsSignaled & PAGE_READONLY_EXCEPTION)
  1751.     printf ("    PAGE_READONLY_EXCEPTION\n");
  1752.   if (interruptsSignaled & PRIVILEGED_INSTRUCTION)
  1753.     printf ("    PRIVILEGED_INSTRUCTION\n");
  1754.   if (interruptsSignaled & ALIGNMENT_EXCEPTION)
  1755.     printf ("    ALIGNMENT_EXCEPTION\n");
  1756.   if (interruptsSignaled & EXCEPTION_DURING_INTERRUPT)
  1757.     printf ("    EXCEPTION_DURING_INTERRUPT\n");
  1758.   if (interruptsSignaled & SYSCALL_TRAP)
  1759.     printf ("    SYSCALL_TRAP\n");
  1760. }
  1761.  
  1762.  
  1763.  
  1764. /* commandIO ()
  1765. **
  1766. ** This routine prints the current state of the I/O devices.
  1767. */
  1768. void commandIO () {
  1769.   int i;
  1770.   printf ("==========  Serial I/O  ==========\n");
  1771.   if (termOutputReady) {
  1772.     printf ("  Output Status:       Ready\n");
  1773.   } else {
  1774.     printf ("  Output Status:       Not Ready\n");
  1775.   }
  1776.   if (termInCharAvail) {
  1777.     printf ("  Input Status:        Character Available\n");
  1778.   } else {
  1779.     printf ("  Input Status:        Character Not Available\n");
  1780.   }
  1781.   printf ("  Current Input Char:  \'");
  1782.   fancyPrintChar (termInChar);
  1783.   if (termInCharWasUsed) {
  1784.     printf ("\'    (already fetched by CPU)\n");
  1785.   } else {
  1786.     printf ("\'    (not yet fetched by CPU)\n");
  1787.   }
  1788.   printf ("    The following characters are currently in the type-ahead buffer:\n      ");
  1789.   printTypeAheadBuffer ();
  1790.   if (termInputFile == stdin) {
  1791.     printf ("  Input coming from: stdin\n");
  1792.     if (terminalWantRawProcessing) {
  1793.       printf ("    Input Mode: Raw\n");
  1794.     } else {
  1795.       printf ("    Input Mode: Cooked\n");
  1796.     }
  1797.   } else {
  1798.     printf ("  Input to the serial device is coming from file \"%s\".\n",
  1799.             termInputFileName);
  1800.   }
  1801.  
  1802.   printf ("==========  Disk I/O  ==========\n");
  1803.   printf ("  The file used for the disk: \"%s\"\n", diskFileName);
  1804.   if (diskFile == NULL) {
  1805.     printf ("    DISK File is currently closed.\n");
  1806.   } else {
  1807.     printf ("    DISK File is currently opened.\n");
  1808.   }
  1809.   printf ("  Disk size:\n");
  1810.   printf ("    Total Tracks = %d\n", diskTrackCount);
  1811.   printf ("    Total Sectors = %d\n", diskSectorCount);
  1812.   printf ("    Sectors per track = %d\n", SECTORS_PER_TRACK);
  1813.   printf ("  Current Status:\n");
  1814.   printf ("    Positioned at Sector = %d\n", currentDiskSector);
  1815.   if (currentDiskStatus == DISK_BUSY) {
  1816.     printf ("    Current Disk Status  = DISK_BUSY\n");
  1817.   } else if (currentDiskStatus == OPERATION_COMPLETED_OK) {
  1818.     printf ("    Current Disk Status  = OPERATION_COMPLETED_OK\n");
  1819.   } else if (currentDiskStatus == OPERATION_COMPLETED_WITH_ERROR_1) {
  1820.     printf ("    Current Disk Status  = OPERATION_COMPLETED_WITH_ERROR_1\n");
  1821.   } else if (currentDiskStatus == OPERATION_COMPLETED_WITH_ERROR_2) {
  1822.     printf ("    Current Disk Status  = OPERATION_COMPLETED_WITH_ERROR_2\n");
  1823.   } else if (currentDiskStatus == OPERATION_COMPLETED_WITH_ERROR_3) {
  1824.     printf ("    Current Disk Status  = OPERATION_COMPLETED_WITH_ERROR_3\n");
  1825.   } else if (currentDiskStatus == OPERATION_COMPLETED_WITH_ERROR_4) {
  1826.     printf ("    Current Disk Status  = OPERATION_COMPLETED_WITH_ERROR_4\n");
  1827.   } else if (currentDiskStatus == OPERATION_COMPLETED_WITH_ERROR_5) {
  1828.     printf ("    Current Disk Status  = OPERATION_COMPLETED_WITH_ERROR_5\n");
  1829.   } else {
  1830.     printf ("    Current Disk Status  = ***************  ERROR  ***************\n");
  1831.   }
  1832.   if (futureDiskStatus == DISK_BUSY) {
  1833.     printf ("    Future Disk Status   = DISK_BUSY\n");
  1834.   } else if (futureDiskStatus == OPERATION_COMPLETED_OK) {
  1835.     printf ("    Future Disk Status   = OPERATION_COMPLETED_OK\n");
  1836.   } else if (futureDiskStatus == OPERATION_COMPLETED_WITH_ERROR_1) {
  1837.     printf ("    Future Disk Status   = OPERATION_COMPLETED_WITH_ERROR_1\n");
  1838.   } else if (futureDiskStatus == OPERATION_COMPLETED_WITH_ERROR_2) {
  1839.     printf ("    Future Disk Status   = OPERATION_COMPLETED_WITH_ERROR_2\n");
  1840.   } else if (futureDiskStatus == OPERATION_COMPLETED_WITH_ERROR_3) {
  1841.     printf ("    Future Disk Status   = OPERATION_COMPLETED_WITH_ERROR_3\n");
  1842.   } else if (futureDiskStatus == OPERATION_COMPLETED_WITH_ERROR_4) {
  1843.     printf ("    Future Disk Status   = OPERATION_COMPLETED_WITH_ERROR_4\n");
  1844.   } else if (futureDiskStatus == OPERATION_COMPLETED_WITH_ERROR_5) {
  1845.     printf ("    Future Disk Status   = OPERATION_COMPLETED_WITH_ERROR_5\n");
  1846.   } else {
  1847.     printf ("    Future Disk Status   = ***************  ERROR  ***************\n");
  1848.   }
  1849.   printf ("  Area of memory being read from / written to:\n");
  1850.   printf ("    diskBufferLow  = 0x%08X\n", diskBufferLow);
  1851.   printf ("    diskBufferHigh = 0x%08X\n", diskBufferHigh);
  1852.   printf ("  Memory-Mapped Register Contents:\n");
  1853.   printf ("    DISK_MEMORY_ADDRESS_REGISTER = 0x%08X\n", diskMemoryAddressRegister);
  1854.   printf ("    DISK_SECTOR_NUMBER_REGISTER  = 0x%08X\n", diskSectorNumberRegister);
  1855.   printf ("    DISK_SECTOR_COUNT_REGISTER   = 0x%08X\n", diskSectorCountRegister);
  1856.   printf ("  Number of Disk Reads  = %d\n", numberOfDiskReads);
  1857.   printf ("  Number of Disk Writes = %d\n", numberOfDiskWrites);
  1858.  
  1859.   printf ("==============================\n");
  1860.   printf ("  CPU status:\n");
  1861.   if (statusI)
  1862.       printf ("    Interrupts:   Enabled\n");
  1863.     else
  1864.       printf ("    Interrupts:   Disabled\n");
  1865.   if (statusS)
  1866.       printf ("    Mode:         System\n");
  1867.     else
  1868.       printf ("    Mode:         User\n");
  1869.   printf ("    Pending Interrupts:\n");
  1870.   if (interruptsSignaled & POWER_ON_RESET)
  1871.     printf ("      POWER_ON_RESET\n");
  1872.   if (interruptsSignaled & TIMER_INTERRUPT)
  1873.     printf ("      TIMER_INTERRUPT\n");
  1874.   if (interruptsSignaled & DISK_INTERRUPT)
  1875.     printf ("      DISK_INTERRUPT\n");
  1876.   if (interruptsSignaled & SERIAL_INTERRUPT)
  1877.     printf ("      SERIAL_INTERRUPT\n");
  1878.   if (interruptsSignaled & HARDWARE_FAULT)
  1879.     printf ("      HARDWARE_FAULT\n");
  1880.   if (interruptsSignaled & ILLEGAL_INSTRUCTION)
  1881.     printf ("      ILLEGAL_INSTRUCTION\n");
  1882.   if (interruptsSignaled & ARITHMETIC_EXCEPTION)
  1883.     printf ("      ARITHMETIC_EXCEPTION_EXCEPTION\n");
  1884.   if (interruptsSignaled & ADDRESS_EXCEPTION)
  1885.     printf ("      ADDRESS_EXCEPTION\n");
  1886.   if (interruptsSignaled & PAGE_INVALID_EXCEPTION)
  1887.     printf ("      PAGE_INVALID_EXCEPTION\n");
  1888.   if (interruptsSignaled & PAGE_READONLY_EXCEPTION)
  1889.     printf ("      PAGE_READONLY_EXCEPTION\n");
  1890.   if (interruptsSignaled & PRIVILEGED_INSTRUCTION)
  1891.     printf ("      PRIVILEGED_INSTRUCTION\n");
  1892.   if (interruptsSignaled & ALIGNMENT_EXCEPTION)
  1893.     printf ("      ALIGNMENT_EXCEPTION\n");
  1894.   if (interruptsSignaled & EXCEPTION_DURING_INTERRUPT)
  1895.     printf ("      EXCEPTION_DURING_INTERRUPT\n");
  1896.   if (interruptsSignaled & SYSCALL_TRAP)
  1897.     printf ("      SYSCALL_TRAP\n");
  1898.   printf ("  Time of next timer event........ %d\n", timeOfNextTimerEvent);
  1899.   printf ("  Time of next disk event......... %d\n", timeOfNextDiskEvent);
  1900.   printf ("  Time of next serial in event.... %d\n", timeOfNextSerialInEvent);
  1901.   printf ("  Time of next serial out event... %d\n", timeOfNextSerialOutEvent);
  1902.   printf ("    Current Time.................. %d\n", currentTime);
  1903.   printf ("    Time of next event............ %d\n", timeOfNextEvent);
  1904.   printf ("==============================\n");
  1905. }
  1906.  
  1907.  
  1908.  
  1909. /* commandSim ()
  1910. **
  1911. ** This routine prints the current simulation constants.
  1912. */
  1913. void commandSim () {
  1914.   int ans;
  1915.   FILE * file;
  1916.  
  1917.   printf ("=========================  Simulation Constants  ==============================\n");
  1918.  
  1919.   printf ("  KEYBOARD_WAIT_TIME           %11 d\n", KEYBOARD_WAIT_TIME);
  1920.   printf ("  KEYBOARD_WAIT_TIME_VARIATION %11 d\n", KEYBOARD_WAIT_TIME_VARIATION);
  1921.  
  1922.   printf ("  TERM_OUT_DELAY               %11 d\n", TERM_OUT_DELAY);
  1923.   printf ("  TERM_OUT_DELAY_VARIATION     %11 d\n", TERM_OUT_DELAY_VARIATION);
  1924.  
  1925.   printf ("  TIME_SLICE                   %11 d (0=no timer interrutps)\n", TIME_SLICE);
  1926.   printf ("  TIME_SLICE_VARIATION         %11 d\n", TIME_SLICE_VARIATION);
  1927.  
  1928.   printf ("  DISK_SEEK_TIME               %11 d\n", DISK_SEEK_TIME);
  1929.   printf ("  DISK_SETTLE_TIME             %11 d\n", DISK_SETTLE_TIME);
  1930.   printf ("  DISK_ROTATIONAL_DELAY        %11 d\n", DISK_ROTATIONAL_DELAY);    /* Minimum is 1 */
  1931.   printf ("  DISK_ACCESS_VARIATION        %11 d\n", DISK_ACCESS_VARIATION);
  1932.  
  1933.   printf ("  DISK_READ_ERROR_PROBABILITY  %11 d (0=never, 1=always, n=\"about 1/n\")\n",
  1934.                                                     DISK_READ_ERROR_PROBABILITY);
  1935.   printf ("  DISK_WRITE_ERROR_PROBABILITY %11 d (0=never, 1=always, n=\"about 1/n\")\n",
  1936.                                                     DISK_WRITE_ERROR_PROBABILITY);
  1937.  
  1938.   printf ("  INIT_RANDOM_SEED             %11 d (between 1 and 2147483646)\n", INIT_RANDOM_SEED);
  1939.   if (commandOptionRand) {
  1940.     printf ("    (overridden with -r option %11 d)\n", randSeedFromOption);
  1941.   }
  1942.  
  1943.   printf ("  MEMORY_SIZE                   0x%08X (decimal: %d)\n", MEMORY_SIZE, MEMORY_SIZE);
  1944.  
  1945.   printf ("  MEMORY_MAPPED_AREA_LOW        0x%08X\n", MEMORY_MAPPED_AREA_LOW);
  1946.   printf ("  MEMORY_MAPPED_AREA_HIGH       0x%08X\n", MEMORY_MAPPED_AREA_HIGH);
  1947.  
  1948.   printf ("  SERIAL_STATUS_WORD_ADDRESS    0x%08X\n", SERIAL_STATUS_WORD_ADDRESS);
  1949.   printf ("  SERIAL_DATA_WORD_ADDRESS      0x%08X\n", SERIAL_DATA_WORD_ADDRESS);
  1950.  
  1951.   printf ("  DISK_STATUS_WORD_ADDRESS      0x%08X\n", DISK_STATUS_WORD_ADDRESS);
  1952.   printf ("  DISK_COMMAND_WORD_ADDRESS     0x%08X\n", DISK_COMMAND_WORD_ADDRESS);
  1953.   printf ("  DISK_MEMORY_ADDRESS_REGISTER  0x%08X\n", DISK_MEMORY_ADDRESS_REGISTER);
  1954.   printf ("  DISK_SECTOR_NUMBER_REGISTER   0x%08X\n", DISK_SECTOR_NUMBER_REGISTER);
  1955.   printf ("  DISK_SECTOR_COUNT_REGISTER    0x%08X\n", DISK_SECTOR_COUNT_REGISTER);
  1956.  
  1957.   printf ("===============================================================================\n");
  1958.  
  1959.   printf ("\n"
  1960.           "The simulation constants will be read in from the file \".blitzrc\" if it exists\n"
  1961.           "when the emulator starts up.  If the file does not exist at startup, defaults\n"
  1962.           "will be used.  You may edit the \".blitzrc\" file to change the values and then\n"
  1963.           "restart the emulator.\n"
  1964.           "\n"
  1965.           "Would you like me to write these values out to the file \".blitzrc\" now? ");
  1966.  
  1967.   ans = readYesNo ();
  1968.   if (ans) {
  1969.  
  1970.     // Open the file, creating it if it does not exist, overwriting it if it does...
  1971.     file = fopen (".blitzrc", "w");
  1972.     if (file == NULL) {
  1973.       printf ("The \".blitzrc\" file could not be opened for writing!\n");
  1974.       perror ("Host error");
  1975.       return;
  1976.     }
  1977.  
  1978.     // Write out the contents of the file...
  1979.     fprintf (file,
  1980.              "! BLITZ Simulation Constants\n"
  1981.              "!\n"
  1982.              "! This file is read by the BLITZ emulator when it starts up and after a\n"
  1983.              "! \"reset\" command.  This file is used to initialize various values that\n"
  1984.              "! will be used by the emulator.\n"
  1985.              "!\n"
  1986.              "! This file was produced by the emulator (with the \"sim\" command).  It may\n"
  1987.              "! be edited to change any or all values.\n"
  1988.              "!\n"
  1989.              "! Each line has variable name followed by an integer value.  A value may\n"
  1990.              "! be specified in either decimal (e.g., \"1234\") or hex (e.g., \"0x1234abcd\").\n"
  1991.              "! Values may be left out if desired, in which case a default will be used.\n"
  1992.              "! In the case of the random seed, any value specified here will override a\n"
  1993.              "! value given with a command line option (-r).\n"
  1994.              "!\n"
  1995.              "!\n"
  1996.       );
  1997.  
  1998.     fprintf (file, "KEYBOARD_WAIT_TIME           %11 d\n", KEYBOARD_WAIT_TIME);
  1999.     fprintf (file, "KEYBOARD_WAIT_TIME_VARIATION %11 d\n", KEYBOARD_WAIT_TIME_VARIATION);
  2000.  
  2001.     fprintf (file, "TERM_OUT_DELAY               %11 d\n", TERM_OUT_DELAY);
  2002.     fprintf (file, "TERM_OUT_DELAY_VARIATION     %11 d\n", TERM_OUT_DELAY_VARIATION);
  2003.  
  2004.     fprintf (file, "\n");
  2005.     fprintf (file, "TIME_SLICE                   %11 d\n", TIME_SLICE);
  2006.     fprintf (file, "TIME_SLICE_VARIATION         %11 d\n", TIME_SLICE_VARIATION);
  2007.  
  2008.     fprintf (file, "\n");
  2009.     fprintf (file, "DISK_SEEK_TIME               %11 d\n", DISK_SEEK_TIME);
  2010.     fprintf (file, "DISK_SETTLE_TIME             %11 d\n", DISK_SETTLE_TIME);
  2011.     fprintf (file, "DISK_ROTATIONAL_DELAY        %11 d\n", DISK_ROTATIONAL_DELAY);
  2012.     fprintf (file, "DISK_ACCESS_VARIATION        %11 d\n", DISK_ACCESS_VARIATION);
  2013.  
  2014.     fprintf (file, "DISK_READ_ERROR_PROBABILITY  %11 d\n", DISK_READ_ERROR_PROBABILITY);
  2015.     fprintf (file, "DISK_WRITE_ERROR_PROBABILITY %11 d\n", DISK_WRITE_ERROR_PROBABILITY);
  2016.  
  2017.     fprintf (file, "\n");
  2018.     fprintf (file, "INIT_RANDOM_SEED             %11 d\n", INIT_RANDOM_SEED);
  2019.  
  2020.     fprintf (file, "\n");
  2021.     fprintf (file, "MEMORY_SIZE                   0x%08X\n", MEMORY_SIZE);
  2022.  
  2023.     fprintf (file, "\n");
  2024.     fprintf (file, "MEMORY_MAPPED_AREA_LOW        0x%08X\n", MEMORY_MAPPED_AREA_LOW);
  2025.     fprintf (file, "MEMORY_MAPPED_AREA_HIGH       0x%08X\n", MEMORY_MAPPED_AREA_HIGH);
  2026.  
  2027.     fprintf (file, "\n");
  2028.     fprintf (file, "SERIAL_STATUS_WORD_ADDRESS    0x%08X\n", SERIAL_STATUS_WORD_ADDRESS);
  2029.     fprintf (file, "SERIAL_DATA_WORD_ADDRESS      0x%08X\n", SERIAL_DATA_WORD_ADDRESS);
  2030.  
  2031.     fprintf (file, "\n");
  2032.     fprintf (file, "DISK_STATUS_WORD_ADDRESS      0x%08X\n", DISK_STATUS_WORD_ADDRESS);
  2033.     fprintf (file, "DISK_COMMAND_WORD_ADDRESS     0x%08X\n", DISK_COMMAND_WORD_ADDRESS);
  2034.     fprintf (file, "DISK_MEMORY_ADDRESS_REGISTER  0x%08X\n", DISK_MEMORY_ADDRESS_REGISTER);
  2035.     fprintf (file, "DISK_SECTOR_NUMBER_REGISTER   0x%08X\n", DISK_SECTOR_NUMBER_REGISTER);
  2036.     fprintf (file, "DISK_SECTOR_COUNT_REGISTER    0x%08X\n", DISK_SECTOR_COUNT_REGISTER);
  2037.  
  2038.     fclose (file);
  2039.   }
  2040.  
  2041. }
  2042.  
  2043.  
  2044.  
  2045. /* commandRaw ()
  2046. **
  2047. ** This routine changes the raw/cooked mode.
  2048. */
  2049. void commandRaw () {
  2050.   if (termInputFileName != NULL) {
  2051.     printSerialHelp ();
  2052.     printf ("*****  Serial I/O is coming from the file \"%s\"  *****\n",
  2053.              termInputFileName);
  2054.   } else if (terminalWantRawProcessing) {
  2055.     printSerialHelp ();
  2056.     printf ("*****  The terminal is already in \"raw\" mode  *****\n");
  2057.   } else {
  2058.     printf ("Future terminal input will be \"raw\".\n");
  2059.     terminalWantRawProcessing = 1;
  2060.   }
  2061. }
  2062.  
  2063.  
  2064.  
  2065. /* commandCooked ()
  2066. **
  2067. ** This routine changes the raw/cooked mode.
  2068. */
  2069. void commandCooked () {
  2070.   if (termInputFileName != NULL) {
  2071.     printSerialHelp ();
  2072.     printf ("*****  Serial I/O is coming from the file \"%s\"  *****\n",
  2073.              termInputFileName);
  2074.   } else if (!terminalWantRawProcessing) {
  2075.     printSerialHelp ();
  2076.     printf ("*****  The terminal is already in \"cooked\" mode  *****\n");
  2077.   } else {
  2078.     printf ("Future terminal input will be \"cooked\".\n");
  2079.     terminalWantRawProcessing = 0;
  2080.   }
  2081. }
  2082.  
  2083.  
  2084.  
  2085. /* printSerialHelp ()
  2086. **
  2087. ** This routine prints a description of how the serial interface works.
  2088. */
  2089. void printSerialHelp () {
  2090.     printf (
  2091. "=============================================================================\n"
  2092. "From time to time a running BLITZ program may read characters from\n"
  2093. "  the \"Serial I/O\" device, which is intended to simulate an ASCII\n"
  2094. "  terminal.  The character data to be supplied to the running BLITZ\n"
  2095. "  program will come from either a file (which is specified using the\n"
  2096. "  \"-i filename\" command line option when the emulator is started) or\n"
  2097. "  from the interactive user-interface running here.\n"
  2098. "With this second option, you may enter characters on \"stdin\" at any\n"
  2099. "  time during the emulation of a running BLITZ program.  These\n"
  2100. "  characters will be supplied to the running BLITZ program (via the\n"
  2101. "  emulated Serial I/O device).  If the emulator seems to hang, it may\n"
  2102. "  be because the emulator is waiting for you to type additional\n"
  2103. "  characters.  (It may also be because the BLITZ program has gotten\n"
  2104. "  into an infinite loop.)\n"
  2105. "At any time you may always hit control-C to suspend instruction execution\n"
  2106. "  and re-enter the emulator command interface.\n"
  2107. "Normally a host OS like UNIX will process user input by echoing characters\n"
  2108. "  on the screen, buffering entire lines, and processing special characters\n"
  2109. "  like backspaces, etc.  This is called \"cooked\" input.  In \"raw\" mode\n"
  2110. "  each character is delivered as-is immediately after the key is pressed,\n"
  2111. "  with no buffering and without the normal echoing and processing of\n"
  2112. "  special characters.\n"
  2113. "The BLITZ emulator runs in either \"raw\" mode or \"cooked\" mode.\n"
  2114. "  The mode can be changed with the \"raw\" and \"cooked\" commands.\n"
  2115. "  This only affects typed input to be delivered to the running BLITZ\n"
  2116. "  program; typed input to the emulator itself is always in cooked mode.\n"
  2117. "In cooked mode, the host OS will suspend the emulator until you enter a\n"
  2118. "  complete line of data and hit ENTER.  Then, if the BLITZ program is\n"
  2119. "  echoing character data properly, you will see all the characters echoed,\n"
  2120. "  resulting in a second, identical line.  A good BLITZ program should echo\n"
  2121. "  all character data, so this duplication of input is normal in cooked\n"
  2122. "  mode.\n"
  2123. "In raw mode, the normal echoing of keystrokes by the host OS is turned\n"
  2124. "  off.  A good BLITZ program should echo all characters, so you *should*\n"
  2125. "  see each keystroke echoed properly.  But of course your BLITZ program\n"
  2126. "  may not be working properly.  It may fail to echo characters because\n"
  2127. "  it has a bug.  Also, the running BLITZ program may not handle\n"
  2128. "  backspaces, newlines, CRs, etc., exactly as you and your terminal\n"
  2129. "  expect.  It may be helpful to recall \\n=Control-J, \\r=Control-M, and\n"
  2130. "  Backspace=Control-H.  On some terminals, the ENTER key is \\r, while many\n"
  2131. "  programs expect to use \\n for END-OF-LINE.\n");
  2132.   if (termInputFileName != NULL) {
  2133.     printf ("Input for the Serial I/O device will come from file..... \"%s\"\n",
  2134.              termInputFileName);
  2135.   } else if (terminalWantRawProcessing) {
  2136.     printf ("Input for the Serial I/O device will come from..... \"stdin\"\n");
  2137.     printf ("The current input mode is.......................... \"raw\"\n");
  2138.   } else {
  2139.     printf ("Input for the Serial I/O device will come from...... \"stdin\"\n");
  2140.     printf ("The current input mode is........................... \"cooked\"\n");
  2141.   }
  2142.   printf (
  2143. "=============================================================================\n");
  2144. }
  2145.  
  2146.  
  2147.  
  2148. /* commandFormat ()
  2149. **
  2150. ** This routine is used to create a new DISK file or to change the size of an
  2151. ** existing DISK file.  When a DISK file is enlarged, its data is initialized.
  2152. */
  2153. void commandFormat () {
  2154.   int oldSectorCount, length, i, newByteLen, sec,
  2155.   newNumberOfSectors, newNumberOfTracks;
  2156.   long len;
  2157.   int magic = 0x424C5A64;   /* ASCII for "BLZd" */
  2158.   char sectorData [8192];
  2159.   char * charPtr;
  2160. #define BEGIN_MESS "<---BEGINNING OF SECTOR---------------"
  2161. #define END_MESS "-------------------------END OF SECTOR--->"
  2162.   char sectorMess [100];
  2163.  
  2164.   printf (
  2165.     "================================================================================\n"
  2166.     "This command is used to create or modify a file to be used by the BLITZ emulator\n"
  2167.     "for the disk.  By default, this file will be called \"DISK\".  The filename may\n"
  2168.     "be specified on the emulator command line with the \"-d filename\" option.  This\n"
  2169.     "command will create the file if it does not exist.  It will set the file to the\n"
  2170.     "desired size and initialize all newly allocated space.\n"
  2171.     "\n"
  2172.     "The size of the disk file is an integral number of tracks.  Each track will\n"
  2173.     "contain %d sectors.  The size of each sector is the same as the page size.\n"
  2174.     "Thus, the sector size is %d bytes.  The actual file size will be the number\n"
  2175.     "tracks times the number of sectors per track times the sector size, plus an\n"
  2176.     "additional 4 bytes, which will contain a \"magic number\".  The magic number\n"
  2177.     "is 0x%08X (decimal: %d, ASCII: \"%c%c%c%c\") and is used to identify this\n"
  2178.     "file as a BLITZ disk file.\n"
  2179.     "\n"
  2180.     "Initialization consists of writing the magic number in the first 4 bytes of the\n"
  2181.     "file and adjusting the file length.  Any data previously stored in the file will\n"
  2182.     "be preserved and any additional sectors created will be initialized.\n"
  2183.     "================================================================================\n\n",
  2184.     SECTORS_PER_TRACK , PAGE_SIZE, magic, magic,
  2185.     (magic>>24) & 0x000000ff,
  2186.     (magic>>16) & 0x000000ff,
  2187.     (magic>>8) & 0x000000ff,
  2188.     (magic>>0) & 0x000000ff
  2189. );
  2190.  
  2191.   // Display the file name...
  2192.   printf ("The name of the disk file is \"%s\".\n", diskFileName);
  2193.  
  2194.   // If open, close it...
  2195.   if (diskFile != NULL) {
  2196.     fclose (diskFile);
  2197.   }
  2198.  
  2199.   // Try to open the file as an existing file...
  2200.   diskFile = fopen (diskFileName, "r");
  2201.   if (diskFile == NULL) {
  2202.     errno = 0;
  2203.     printf ("The file \"%s\" did not previously exist.  (It could not be opened for reading.)\n", diskFileName);
  2204.     oldSectorCount = 0;
  2205.  
  2206.   // If the file already exists...
  2207.   } else {
  2208.     printf ("The file \"%s\" existed previously.\n", diskFileName);
  2209.     fseek (diskFile, 0l, SEEK_END);
  2210.     len = ftell (diskFile);
  2211.  
  2212.     // Check for length > MAX...
  2213.     if (len > ((long) MAX)) {
  2214.       printf ("ERROR: The  maximum integer is %d.\n", MAX);
  2215.       printf ("ERROR: The DISK file size exceeds the maximum; Please delete the file and try again.\n");
  2216.       initializeDisk ();
  2217.       return;
  2218.     }
  2219.  
  2220.     // Print statistics about the old file...
  2221.     length = (int) len;
  2222.     printf ("    Old File Length = %d bytes\n", length);
  2223.     if (length < (SECTORS_PER_TRACK * PAGE_SIZE + 4)) {
  2224.       printf ("      The existing DISK file is too small; it must be large enough for at least 1 track.\n");
  2225.       printf ("      The minimum DISK file size is 1 track + 4 bytes (where SectorSize = %d bytes and SectorsPerTrack = %d).\n", PAGE_SIZE, SECTORS_PER_TRACK);
  2226.     }
  2227.     oldSectorCount = (length - 4) / PAGE_SIZE;
  2228.     if (oldSectorCount * PAGE_SIZE + 4 != length) {
  2229.       printf ("      The existing DISK file size is not an even number of tracks plus 4 bytes.\n");
  2230.       printf ("      (SectorSize = %d bytes, SectorsPerTrack = %d, DISK file size = %d bytes)\n", PAGE_SIZE, SECTORS_PER_TRACK, length);
  2231.     }
  2232.     printf ("    Old Sector Count = %d\n", oldSectorCount);
  2233.     printf ("    Old Track Count = %d\n", oldSectorCount / SECTORS_PER_TRACK);
  2234.  
  2235.     // Close the old file...
  2236.     fclose (diskFile);
  2237.     diskFile = NULL;
  2238.   }
  2239.  
  2240.   // Ask for the new length...
  2241.   printf ("Enter the number of tracks (e.g., 1000; type 0 to abort):\n");
  2242.   newNumberOfTracks = readDecimalInt ();
  2243.  
  2244.   // If < 0 then abort this command...
  2245.   if (newNumberOfTracks <= 0) {
  2246.     printf ("Aborting; file not changed!\n");
  2247.     initializeDisk ();
  2248.     return;
  2249.  
  2250.   // Otherwise...
  2251.   } else {
  2252.  
  2253.     // Compute and print statistics about the new file...
  2254.     printf ("Desired number of tracks = %d\n", newNumberOfTracks);
  2255.     newNumberOfSectors = newNumberOfTracks * SECTORS_PER_TRACK;
  2256.     newByteLen = newNumberOfSectors * PAGE_SIZE;
  2257.     printf ("  New number of sectors = %d\n", newNumberOfSectors);
  2258.     printf ("  New number of tracks = %d\n", newNumberOfTracks);
  2259.     printf ("  New number of data bytes = %d\n", newByteLen);
  2260.  
  2261.     // Create the file if it does not exist...
  2262.     diskFile = fopen (diskFileName, "a+");
  2263.     if (diskFile == NULL) {
  2264.       printf ("The file could not be created!\n");
  2265.       initializeDisk ();
  2266.       return;
  2267.     }
  2268.     fclose (diskFile);
  2269.  
  2270.     // Alter the file's length, if necessary...
  2271.     errno = 0;
  2272.     i = truncate (diskFileName, (off_t) newByteLen+4);    // off_t is "long long" in sys/types.h
  2273.     if (i == 0) {
  2274.       printf ("    The magic number will consume 4 additional bytes.\n", newByteLen+4);
  2275.       printf ("File length changed to %d bytes.\n", newByteLen+4);
  2276.     } else {
  2277.       printf ("Problems during call to 'truncate'; Disk I/O has been disabled!\n");
  2278.       if (errno) perror ("Error");
  2279.       fclose (diskFile);
  2280.       diskFile = NULL;
  2281.       return;
  2282.     }
  2283.  
  2284.     // Open the file for updating...
  2285.     diskFile = fopen (diskFileName, "r+");
  2286.     if (diskFile == NULL) {
  2287.       printf ("The file could not be opened!\n");
  2288.       initializeDisk ();
  2289.       return;
  2290.     }
  2291.  
  2292.     // Write the magic number...
  2293.     errno = 0;
  2294.     if (fseek (diskFile, 0l, SEEK_SET)) {
  2295.       if (errno) perror ("Error on DISK file");
  2296.       fclose (diskFile);
  2297.       diskFile = NULL;
  2298.       return;
  2299.     }
  2300.     fwrite (&magic, 4, 1, diskFile);
  2301.     if (errno) perror ("Error writing to DISK file");
  2302.  
  2303.     // Print a message...
  2304.     if (newNumberOfSectors > oldSectorCount) {
  2305.       printf ("Initializing sectors %d through %d...\n", oldSectorCount, newNumberOfSectors-1);
  2306.     } else if (newNumberOfSectors < oldSectorCount) {
  2307.       printf ("The pre-existing data in sectors 0 through %d will be preserved...\n", newNumberOfSectors-1);
  2308.     }
  2309.  
  2310.     // In a loop, write each new sector data out...
  2311.     for (sec = oldSectorCount; sec < newNumberOfSectors; sec++) {
  2312.  
  2313.       // printf ("Initializing sector %d...\n", sec);
  2314.  
  2315.       // Initialize the default data for the sector...
  2316.       sprintf (sectorMess, "disk sector %06d ", sec);
  2317.       charPtr = sectorMess;
  2318.       for (i=0; i<8192; i++) {
  2319.         sectorData [i] = *(charPtr++);
  2320.         if (*charPtr == '\0') charPtr = sectorMess;
  2321.       }
  2322.       charPtr = BEGIN_MESS;
  2323.       for (i = 0; i < strlen (BEGIN_MESS); i++) {
  2324.         sectorData[i] = *(charPtr++);
  2325.       }
  2326.       charPtr = END_MESS;
  2327.       for (i = 0; i < strlen (END_MESS); i++) {
  2328.         sectorData[8192 - strlen(END_MESS) + i] = *(charPtr++);
  2329.       }
  2330.       sprintf (sectorMess, "disk sector %06d ", 123);
  2331.  
  2332.       // Seek to the proper location in the file...
  2333.       errno = 0;
  2334.       if (fseek (diskFile, ((long) ((sec * PAGE_SIZE) + 4)), SEEK_SET)) {
  2335.         printf ("Error from fseek for DISK file; Disk I/O has been disabled!\n");
  2336.         if (errno) perror ("Error");
  2337.         fclose (diskFile);
  2338.         diskFile = NULL;
  2339.         return;
  2340.       }
  2341.  
  2342.       // Write out a sector of data...
  2343.       errno = 0;
  2344.       fwrite (sectorData, 8192, 1, diskFile);
  2345.       if (errno) perror ("Error writing to DISK file");
  2346.     }
  2347.   }
  2348.  
  2349.   // Close the file.
  2350.   errno = 0;
  2351.   fclose (diskFile);
  2352.   if (errno) perror ("Error closing DISK file");
  2353.   diskFile = NULL;
  2354.  
  2355.   // Call "initializeDisk()" to set up the disk file...
  2356.   printf ("Successful completion.\n");
  2357.   initializeDisk ();
  2358.   return;
  2359. }
  2360.  
  2361.  
  2362.  
  2363. /* printNumberNL2 (i)
  2364. **
  2365. ** This routine prints a number in the form
  2366. **       0x1234abcd   ( decimal: 395441741 )
  2367. ** followed by a newline.
  2368. */
  2369. void printNumberNL2 (int i) {
  2370.   char str [100];
  2371.   char c;
  2372.   TableEntry * tableEntry;
  2373.   int index;
  2374.   printf ("0x");
  2375.   putlong (i);
  2376.   sprintf (str, "%d", i);
  2377.   printf ("     ( decimal: ");
  2378.   printStringInWidth (str, 11);
  2379.   printf (" )\n");
  2380. }
  2381.  
  2382.  
  2383.  
  2384. /* printNumberNL (i)
  2385. **
  2386. ** This routine prints a number in the form
  2387. **       0x1234abcd   ( decimal: 395441741     ascii: ".4.."   _my_label )
  2388. ** followed by a newline.
  2389. */
  2390. void printNumberNL (int i) {
  2391.   char str [100];
  2392.   char c;
  2393.   TableEntry * tableEntry;
  2394.   int index;
  2395.   if (i == 0) {
  2396.     printf ("0x00000000     ( decimal: 0 )\n");
  2397.     return;
  2398.   }
  2399.   printf ("0x");
  2400.   putlong (i);
  2401.   sprintf (str, "%d", i);
  2402.   printf ("     ( decimal: ");
  2403.   printStringInWidth (str, 11);
  2404.   if ((i >= ' ') && (i <= '~')) {
  2405.     printf (" ascii: \'");
  2406.     putchar (i & 0x000000ff);
  2407.     printf ("\'");
  2408.   }
  2409. /****
  2410.   printf (" ascii: \"");
  2411.   c = (i >> 24) & 0x000000ff;
  2412.   if ((c>=' ') && (c <= '~')) {
  2413.     putchar (c);
  2414.   } else {
  2415.     putchar ('.');
  2416.   }
  2417.   c = (i >> 16) & 0x000000ff;
  2418.   if ((c>=' ') && (c <= '~')) {
  2419.     putchar (c);
  2420.   } else {
  2421.     putchar ('.');
  2422.   }
  2423.   c = (i >> 8) & 0x000000ff;
  2424.   if ((c>=' ') && (c <= '~')) {
  2425.     putchar (c);
  2426.   } else {
  2427.     putchar ('.');
  2428.   }
  2429.   c = i & 0x000000ff;
  2430.   if ((c>=' ') && (c <= '~')) {
  2431.     putchar (c);
  2432.   } else {
  2433.     putchar ('.');
  2434.   }
  2435.   printf ("\"");
  2436. ****/
  2437.   index = findLabel (i);
  2438.   if (index != -1) {
  2439.     tableEntry = valueIndex [index];
  2440.     printf ("     %s", tableEntry->string);
  2441.   }
  2442.   printf (" )\n");
  2443. }
  2444.  
  2445.  
  2446.  
  2447. /* commandDumpMemory ()
  2448. **
  2449. ** This routine asks for a starting address and a length.  It then dumps
  2450. ** that many bytes of physical memory.
  2451. */
  2452. void commandDumpMemory () {
  2453.   int addr, len;
  2454.   printf ("Enter the starting (physical) memory address in hex: ");
  2455.   addr = readHexInt ();
  2456.   if (addr < 0 ) {
  2457.     printf ("Address must not be negative.\n");
  2458.     return;
  2459.   }
  2460.   if (addr >= MEMORY_SIZE) {
  2461.     printf ("This address is beyond the upper limit of physical memory.\n");
  2462.     printf ("The address of the upper-most byte is ");
  2463.     printNumberNL (MEMORY_SIZE - 1);
  2464.     return;
  2465.   }
  2466.   printf ("Enter the number of bytes in hex (or 0 to abort): ");
  2467.   len = readHexInt ();
  2468.   if (len <= 0 ) return;
  2469.   if (addr+len > MEMORY_SIZE) {
  2470.     printf ("This request extends beyond the upper limit of physical memory.\n");
  2471.     printf ("The maximum length from this address is ");
  2472.     printNumberNL (MEMORY_SIZE - addr);
  2473.     return;
  2474.   }
  2475.   printMemory (& memory [addr], len, addr);
  2476. }
  2477.  
  2478.  
  2479.  
  2480. /* commandSetMemory ()
  2481. **
  2482. ** This routine asks for a starting address and a value.  It then alters
  2483. ** a single word of physical memory.
  2484. */
  2485. void commandSetMemory () {
  2486.   int addr, val;
  2487.   printf ("Enter the (physical) memory address in hex of the word to be modified: ");
  2488.   addr = readHexInt ();
  2489.   if (addr < 0 ) {
  2490.     printf ("Address must not be negative.\n");
  2491.     return;
  2492.   }
  2493.   if (!physicalAddressOk (addr)) {
  2494.     printf ("This is not a legal physical address.\n");
  2495.     return;
  2496.   }
  2497.   if (!isAligned (addr)) {
  2498.     printf ("This is address is not word-aligned.\n");
  2499.     return;
  2500.   }
  2501.   printf ("The old value is:\n");
  2502.   printf ("0x%06X: 0x%08X\n", addr, getPhysicalWord (addr));
  2503.   printf ("Enter the new value (4 bytes in hex): ");
  2504.   val = readHexInt ();
  2505.   putPhysicalWord (addr, val);
  2506.   printf ("0x%06X: 0x%08X\n", addr, getPhysicalWord (addr));
  2507. }
  2508.  
  2509.  
  2510.  
  2511. /* commandWriteWord ()
  2512. **
  2513. ** This routine asks for an address and a value.  It then does a clean
  2514. ** write to a single word of physical memory.  This can be used to
  2515. ** test the memory-mapped I/O regions.
  2516. */
  2517. void commandWriteWord () {
  2518.   int addr, val;
  2519.   printf ("This command can be used to write to a word of memory that is in the\n");
  2520.   printf ("    memory-mapped I/O region, sending data or commands to the I/O device.\n");
  2521.   printf ("Enter the (physical) memory address in hex of the word to be written to: ");
  2522.   addr = readHexInt ();
  2523.   if (addr < 0 ) {
  2524.     printf ("Address must not be negative.\n");
  2525.     return;
  2526.   }
  2527.   if (!physicalAddressOk (addr)) {
  2528.     printf ("This is not a legal physical address.\n");
  2529.     return;
  2530.   }
  2531.   if (!isAligned (addr)) {
  2532.     printf ("This is address is not word-aligned.\n");
  2533.     return;
  2534.   }
  2535.   printf ("Enter the new value (4 bytes in hex): ");
  2536.   val = readHexInt ();
  2537.   putPhysicalWord (addr, val);
  2538.   printf ("Writing word...   address = 0x%06X    value = 0x%08X\n", addr, val);
  2539. }
  2540.  
  2541.  
  2542.  
  2543. /* commandReadWord ()
  2544. **
  2545. ** This routine asks for an address and a value.  It then does a clean
  2546. ** read from to a single word of physical memory.  This can be used to
  2547. ** test the memory-mapped I/O regions.
  2548. */
  2549. void commandReadWord () {
  2550.   int addr, val;
  2551.   printf ("This command can be used to read a word of memory that is in the\n");
  2552.   printf ("    memory-mapped I/O region, retrieving I/O device status or data.\n");
  2553.   printf ("Enter the (physical) memory address in hex of the word to be read from: ");
  2554.   addr = readHexInt ();
  2555.   if (addr < 0 ) {
  2556.     printf ("Address must not be negative.\n");
  2557.     return;
  2558.   }
  2559.   if (!physicalAddressOk (addr)) {
  2560.     printf ("This is not a legal physical address.\n");
  2561.     return;
  2562.   }
  2563.   if (!isAligned (addr)) {
  2564.     printf ("This is address is not word-aligned.\n");
  2565.     return;
  2566.   }
  2567.   val = getPhysicalWord (addr);
  2568.   printf ("Reading word...   address = 0x%06X    value = 0x%08X\n", addr, val);
  2569. }
  2570.  
  2571.  
  2572.  
  2573. /* commandInput ()
  2574. **
  2575. ** This command allows the user to type several characters, which will
  2576. ** be supplied to the serial input of the BLITZ machine as they are needed.
  2577. */
  2578. void commandInput () {
  2579.   int ch, i;
  2580.   char terminalBuffer [1];
  2581.  
  2582.   /* Make sure the serial input is not coming from a file. */
  2583.   if (termInputFile != stdin) {
  2584.     printf ("You cannot type in input since it comes from file \"%s\".\n",
  2585.             termInputFileName);
  2586.     return;
  2587.   }
  2588.  
  2589.   printf ("The following characters will be supplied as input to the BLITZ serial\n"
  2590.           "input before querying the terminal:\n  ");
  2591.   printTypeAheadBuffer ();
  2592.   printf ("You may add to this type-ahead buffer now.\n");
  2593.   if (terminalWantRawProcessing) {
  2594.     printf ("The terminal is now in \"raw\" mode.\nEnter characters followed by control-D...\n");
  2595.   } else {
  2596.     printf ("The terminal is now in \"cooked\" mode.\nEnter characters followed by control-D...\n");
  2597.   }
  2598.  
  2599.   /* Read in a bunch of characters. */
  2600.   fflush (stdout);
  2601.   turnOnTerminal ();
  2602.   while (1) {
  2603.     /* Get the next character. */
  2604.     i = fread (terminalBuffer, 1, 1, termInputFile);
  2605.     if (i == 1) {
  2606.       ch = terminalBuffer [0];
  2607.     } else {
  2608.       break;  /* Should not occur... */
  2609.     }
  2610.     /* Exit if EOF (i.e., control-D) was entered. */
  2611.     if (ch == 4) {
  2612.       break;
  2613.     }
  2614.     if (feof (termInputFile)) {
  2615.       break;
  2616.     }
  2617.     /* Echo the character. */
  2618.     if (terminalInRawMode) {
  2619.       fancyPrintChar (ch);
  2620.     }
  2621.     /* Add this character to the type-ahead buffer. */
  2622.     addToTypeAhead (ch);
  2623.   }
  2624.   turnOffTerminal ();
  2625.   printf ("\n");
  2626.   printf ("The following characters will be supplied as input to the BLITZ serial\n"
  2627.           "input before querying the terminal:\n  ");
  2628.   printTypeAheadBuffer ();
  2629. }
  2630.  
  2631.  
  2632.  
  2633. /* addToTypeAhead (ch)
  2634. **
  2635. ** This routine is passed a character.  It adds it to the type-ahead
  2636. ** buffer.  If the buffer is full, a fatal error occurs.
  2637. */
  2638. void addToTypeAhead (int ch) {
  2639.   if (typeAheadBufferCount < TYPE_AHEAD_BUFFER_SIZE) {
  2640.     typeAheadBufferCount++;
  2641.     typeAheadBuffer [typeAheadBufferIn++] = ch;
  2642.     if (typeAheadBufferIn >= TYPE_AHEAD_BUFFER_SIZE) {
  2643.       typeAheadBufferIn = 0;
  2644.     }
  2645.   } else {
  2646.     fatalError ("The type-ahead buffer has overflowed!");
  2647.   }
  2648. }
  2649.  
  2650.  
  2651.  
  2652. /* printTypeAheadBuffer ()
  2653. **
  2654. ** This routine prints out the type-ahead buffer.
  2655. */
  2656. void printTypeAheadBuffer () {
  2657.   int i, j, ch;
  2658.   printf ("\"");
  2659.   j = typeAheadBufferOut;
  2660.   for (i=typeAheadBufferCount; i>0; i--) {
  2661.     ch = typeAheadBuffer[j++];
  2662.     fancyPrintChar (ch);
  2663.     if (j >= TYPE_AHEAD_BUFFER_SIZE) {
  2664.       j = 0;
  2665.     }
  2666.   }
  2667.   printf ("\"\n");
  2668. }
  2669.  
  2670.  
  2671.  
  2672. /* fancyPrintChar (ch)
  2673. **
  2674. ** This routine is passed a character.  It prints it on stdout.  If
  2675. ** the character is a non-graphic, it is print using these escapes:
  2676. **     \"  \'  \\  \0  \a  \b  \t  \n  \v  \f  \r  \xFF
  2677. ** The last form is a variation on the \377 octal notation of "C", but
  2678. ** in hex instead.
  2679. */
  2680. void fancyPrintChar (int ch) {
  2681.  
  2682. /*****
  2683.   if (ch == 0) {
  2684.     printf ("\\0");
  2685.   } else if (ch == 8) {
  2686.     printf ("\\b");
  2687.   } else if (ch == 92) {
  2688.     printf ("\\\\");
  2689.   } else if (ch == 10) {
  2690.     printf ("\\n");
  2691.   } else if (ch == 9) {
  2692.     printf ("\\t");
  2693.   } else if (ch == 13) {
  2694.     printf ("\\r");
  2695.   } else if (ch == 34) {
  2696.     printf ("\\\"");
  2697.   } else if ((ch >= 32) && (ch < 127)) {
  2698.     printf ("%c", ch);
  2699.   } else {
  2700.     printf ("\\x%02X", ch);
  2701.   }
  2702. *****/
  2703.  
  2704.   if (ch == '\"') {
  2705.     printf ("\\\"");
  2706.   } else if (ch == '\'') {
  2707.     printf ("\\\'");
  2708.   } else if (ch == '\\') {
  2709.     printf ("\\\\");
  2710.   } else if ((ch >= 32) && (ch < 127)) {
  2711.     printf ("%c", ch);
  2712.   } else if (ch == '\0') {
  2713.     printf ("\\0");
  2714.   } else if (ch == '\a') {
  2715.     printf ("\\a");
  2716.   } else if (ch == '\b') {
  2717.     printf ("\\b");
  2718.   } else if (ch == '\t') {
  2719.     printf ("\\t");
  2720.   } else if (ch == '\n') {
  2721.     printf ("\\n");
  2722.   } else if (ch == '\v') {
  2723.     printf ("\\v");
  2724.   } else if (ch == '\f') {
  2725.     printf ("\\f");
  2726.   } else if (ch == '\r') {
  2727.     printf ("\\r");
  2728.   } else {
  2729.     printf ("\\x%02X", ch);
  2730.   }
  2731. }
  2732.  
  2733.  
  2734.  
  2735. /* readHexInt ()
  2736. **
  2737. ** This routine reads in an integer from the terminal and returns it.
  2738. ** This version is preliminary.  Eventually, we would like to be able to
  2739. ** read an arbitary expression, evaluate it, and then return the integer.
  2740. */
  2741. int readHexInt () {
  2742.   int i = 0;
  2743.   char * str = getToken ();
  2744.   sscanf (str, "%x", &i);
  2745.   return i;
  2746. }
  2747.  
  2748.  
  2749.  
  2750. /* readDecimalInt ()
  2751. **
  2752. ** This routine reads in an integer from the terminal and returns it.
  2753. ** This version is preliminary.  Eventually, we would like to be able to
  2754. ** read an arbitary expression, evaluate it, and then return the integer.
  2755. */
  2756. int readDecimalInt () {
  2757.   int i;
  2758.   char * str = getToken ();
  2759.   sscanf (str, "%d", &i);
  2760.   return i;
  2761. }
  2762.  
  2763.  
  2764.  
  2765. /* readDouble ()
  2766. **
  2767. ** Read a floating-point number from the user and return it as a double.
  2768. */
  2769. double readDouble () {
  2770.   double x = 0.0;
  2771.   char * str = toLower (getToken ());
  2772.   if (!strcmp (str, "nan")) {
  2773.     return 0.0 / 0.0;
  2774.   } else if (!strcmp (str, "inf")) {
  2775.     return 1.0 / 0.0;
  2776.   } else if (!strcmp (str, "-inf")) {
  2777.     return -1.0 / 0.0;
  2778.   }
  2779.   sscanf (str, "%lg", &x);
  2780.   return x;
  2781. }
  2782.  
  2783.  
  2784.  
  2785. /* readYesNo ()
  2786. **
  2787. ** This routine reads either "yes" or "no" from the user and returns
  2788. ** true if yes, false if no.
  2789. */
  2790. int readYesNo () {
  2791.   char * command;
  2792.   while (1) {
  2793.     command = toLower (getToken ());
  2794.     if (!strcmp (command, "yes")) return 1;
  2795.     if (!strcmp (command, "y")) return 1;
  2796.     if (!strcmp (command, "no")) return 0;
  2797.     if (!strcmp (command, "n")) return 0;
  2798.     printf ("INVLAID ENTRY:  Please enter \"y\" or \"n\"...");
  2799.   }
  2800. }
  2801.  
  2802.  
  2803.  
  2804. /* commandSetI ()
  2805. ** commandSetS ()
  2806. ** commandSetP ()
  2807. ** commandSetZ ()
  2808. ** commandSetV ()
  2809. ** commandSetN ()
  2810. **
  2811. ** commandClearI ()
  2812. ** commandClearS ()
  2813. ** commandClearP ()
  2814. ** commandClearZ ()
  2815. ** commandClearV ()
  2816. ** commandClearN ()
  2817. **
  2818. ** These commands set and clear the indicated bit in the status register.
  2819. */
  2820. void commandSetI () {
  2821.   statusI = 1;
  2822.   printf ("The I bit is now 1: Interrupts Enabled.\n");
  2823. }
  2824. void commandSetS () {
  2825.   statusS = 1;
  2826.   printf ("The S bit is now 1: System Mode.\n");
  2827. }
  2828. void commandSetP () {
  2829.   statusP = 1;
  2830.   printf ("The P bit is now 1: Paging Enabled.\n");
  2831.   printAboutToExecute ();
  2832. }
  2833. void commandSetZ () {
  2834.   statusZ = 1;
  2835.   printf ("The Z bit is now 1: Zero.\n");
  2836. }
  2837. void commandSetV () {
  2838.   statusV = 1;
  2839.   printf ("The V bit is now 1: Overflow Occurred.\n");
  2840. }
  2841. void commandSetN () {
  2842.   statusN = 1;
  2843.   printf ("The N bit is now 1: Negative.\n");
  2844. }
  2845.  
  2846. void commandClearI () {
  2847.   statusI = 0;
  2848.   printf ("The I bit is now 0: Interrupts Disabled.\n");
  2849. }
  2850. void commandClearS () {
  2851.   statusS = 0;
  2852.   printf ("The S bit is now 0: User Mode.\n");
  2853. }
  2854. void commandClearP () {
  2855.   statusP = 0;
  2856.   printf ("The P bit is now 0: Paging Disabled.\n");
  2857.   printAboutToExecute ();
  2858. }
  2859. void commandClearZ () {
  2860.   statusZ = 0;
  2861.   printf ("The Z bit is now 0: Not Zero.\n");
  2862. }
  2863. void commandClearV () {
  2864.   statusV = 0;
  2865.   printf ("The V bit is now 0: No Overflow.\n");
  2866. }
  2867. void commandClearN () {
  2868.   statusN = 0;
  2869.   printf ("The N bit is now 0: Not Negative.\n");
  2870. }
  2871.  
  2872.  
  2873.  
  2874. /* commandSetPC ()
  2875. **
  2876. ** This command is used to set the PC register.
  2877. */
  2878. void commandSetPC () {
  2879.   int i;
  2880.   printf ("Please enter the new value for the program counter (PC): ");
  2881.   i = readHexInt ();
  2882.   if (i%4 != 0) {
  2883.     printf ("ERROR: The PC must always be word aligned.  No change.\n");
  2884.     return;
  2885.   }
  2886.   pc = i;
  2887.   printf ("  PC   = ");
  2888.   printNumberNL (pc);
  2889.   printAboutToExecute ();
  2890. }
  2891.  
  2892.  
  2893.  
  2894. /* commandSetPTBR ()
  2895. **
  2896. ** This command is used to set the PTBR register.
  2897. */
  2898. void commandSetPTBR () {
  2899.   int i;
  2900.   printf ("Enter the new value for the Page Table Base Register (PTBR) in hex: ");
  2901.   i = readHexInt ();
  2902.   if (i%4 != 0) {
  2903.     printf ("ERROR: The PTBR must always be word aligned.  No change.\n");
  2904.     return;
  2905.   }
  2906.   ptbr = i;
  2907.   printf ("  PTBR = ");
  2908.   printNumberNL (ptbr);
  2909. }
  2910.  
  2911.  
  2912.  
  2913. /* commandSetPTLR ()
  2914. **
  2915. ** This command is used to set the PTLR register.
  2916. */
  2917. void commandSetPTLR () {
  2918.   int i;
  2919.   printf ("Enter the new value for the Page Table Length Register (PTLR) in hex: ");
  2920.   i = readHexInt ();
  2921.   if (i%4 != 0) {
  2922.     printf ("ERROR: The PTLR must always be word aligned.  No change.\n");
  2923.     return;
  2924.   }
  2925.   ptlr = i;
  2926.   printf ("  PTLR = ");
  2927.   printNumberNL (ptlr);
  2928. }
  2929.  
  2930.  
  2931.  
  2932. /* commandPrintPageTable ()
  2933. **
  2934. ** This command is used to print the page table.
  2935. */
  2936. void commandPrintPageTable () {
  2937.   int tableEntryAddr, tableEntry, frameNumber, i, addInfo;
  2938.  
  2939.   printf ("  Page Table:\n");
  2940.   printf ("    base   (PTBR) = 0x%08X\n", ptbr);
  2941.   printf ("    length (PTLR) = 0x%08X\n", ptlr);
  2942.   printf ("    This table describes a logical address space with 0x%08X (decimal %d) bytes (i.e., %d pages)\n", ptlr * PAGE_SIZE / 4,  ptlr * PAGE_SIZE / 4, ptlr / 4);
  2943.   printf ("\n");
  2944.  
  2945.   printf ("    addr      entry        Logical  Physical  Undefined Bits  Dirty  Referenced  Writeable  Valid\n");
  2946.   printf ("  ========   ========     ========  ========  ==============  =====  ==========  =========  =====\n");
  2947.  
  2948.   i = 0;
  2949.   for (tableEntryAddr = ptbr;
  2950.        tableEntryAddr < ptbr + ptlr;
  2951.        tableEntryAddr = tableEntryAddr + 4) {
  2952.  
  2953.     /* Check for an address exception.  If found, signal it and return. */
  2954.     if (!physicalAddressOk (tableEntryAddr)) {
  2955.       printf ("   This page table entry is not within physical memory!\n");
  2956.       break;
  2957.     }
  2958.  
  2959.     /* Get the page table entry. */
  2960.     /*   (tableEntryAddr must be aligned since ptbr is aligned.) */
  2961.     tableEntry = getPhysicalWord (tableEntryAddr);
  2962.     frameNumber = tableEntry & 0xffffe000;
  2963.     addInfo = (tableEntry & 0x00001ff0) >> 4;
  2964.  
  2965.     printf ("  %08X:  %08X     %08X", tableEntryAddr, tableEntry, i<<13);
  2966.     printf ("  %08X ", frameNumber);
  2967.     printf ("      %03x   ", addInfo);
  2968.     /* Print Dirty Bit */
  2969.     if (tableEntry & 0x00000008) {
  2970.       printf ("       1");
  2971.     } else {
  2972.       printf ("       0");
  2973.     }
  2974.     /* Print Referenced Bit */
  2975.     if (tableEntry & 0x00000004) {
  2976.       printf ("        1");
  2977.     } else {
  2978.       printf ("        0");
  2979.     }
  2980.     /* Print Writeable Bit */
  2981.     if (tableEntry & 0x00000002) {
  2982.       printf ("           1");
  2983.     } else {
  2984.       printf ("           0");
  2985.     }
  2986.     /* Print Valid Bit */
  2987.     if (tableEntry & 0x00000001) {
  2988.       printf ("        1");
  2989.     } else {
  2990.       printf ("        0");
  2991.     }
  2992.  
  2993.     if (!physicalAddressOk (frameNumber)) {
  2994.       printf ("    *** Bad physical address! ***\n");
  2995.     } else {
  2996.       printf ("\n");
  2997.     }
  2998.  
  2999.     i++;
  3000.     if (controlCPressed) {
  3001.       controlCPressed = 0;
  3002.       break;
  3003.     }
  3004.  
  3005.   }
  3006. }
  3007.  
  3008.  
  3009.  
  3010. /* commandTranslate ()
  3011. **
  3012. ** This command command asks for a logical address.  It the perform
  3013. ** address translation on it.
  3014. */
  3015. void commandTranslate () {
  3016.   int logicalAddr, physAddr, reading, doUpdates;
  3017.   char * str;
  3018.   printf ("Please enter a logical address: ");
  3019.   logicalAddr = readHexInt ();
  3020.   printf ("Will this be a read-only operation (y/n)? ");
  3021.   reading = readYesNo ();
  3022.   printf ("After figuring out the affect of this memory access, do you want me to update the\n"
  3023.           "page table and signal exceptions, if any, as if this operation were performed (y/n)? ");
  3024.   doUpdates = readYesNo ();
  3025.   /*   printf ("reading = %d   doUpdates=%d\n", reading, doUpdates);   */
  3026.   printf ("Calling:\n    translate (logicalAddr=0x%08X, reading=", logicalAddr);
  3027.   if (reading) {
  3028.     printf ("TRUE");
  3029.   } else {
  3030.     printf ("FALSE");
  3031.   }
  3032.   printf (", wantPrinting=TRUE, doUpdates=");
  3033.   if (doUpdates) {
  3034.     printf ("TRUE");
  3035.   } else {
  3036.     printf ("FALSE");
  3037.   }
  3038.   printf (")\n");
  3039.  
  3040.   physAddr = translate (logicalAddr, reading, 1, doUpdates);
  3041.  
  3042.   if (translateCausedException) {
  3043.     printf ("An exception occurred during translation.\n");
  3044.     if (!doUpdates) {
  3045.       printf ("  This exception will be ignored: The processor state has not been modified.\n");
  3046.     } else {
  3047.       printf ("  The processor state has been modified: this exception is now pending.\n");
  3048.     }
  3049.     return;
  3050.   }
  3051.   printf ("The value of the target word in physical memory was not changed.  It is...\n");
  3052.   printf ("  0x%06X: 0x%08X\n", physAddr, getPhysicalWord (physAddr));
  3053.   if (doUpdates && statusP) {
  3054.     printf ("The page table may have been modified by this command.\n");
  3055.   } else {
  3056.     printf ("The page table has not been modified by this command.\n");
  3057.   }
  3058. }
  3059.  
  3060.  
  3061.  
  3062. /* commandCancel ()
  3063. **
  3064. ** This routine cancels all pending interrupts.
  3065. */
  3066. void commandCancel () {
  3067.   interruptsSignaled = 0;
  3068.   systemTrapNumber = 0;
  3069.   pageInvalidOffendingAddress = 0;
  3070.   pageReadonlyOffendingAddress = 0;
  3071.   printf ("All pending interrupts have been cancelled.\n");
  3072. }
  3073.  
  3074.  
  3075.  
  3076. /* commandLabels ()
  3077. **
  3078. ** This routine prints the label tables, first by the alphaIndex, then
  3079. ** by the valueIndex.
  3080. */
  3081. void commandLabels () {
  3082.   int i, j;
  3083.   TableEntry * p;
  3084.   printf ("Ordered alphabetically:\n");
  3085.   printf ("    Label                          Hex Value  (in decimal)\n");
  3086.   printf ("    ============================== =========  ============\n");
  3087.   for (i=0; i<numberOfLabels; i++) {
  3088.     p = alphaIndex [i];
  3089.     printf ("    ");
  3090.     printStringInWidth (p->string, 30);
  3091.     printf ("  %08X   %11d\n", p->value, p->value);
  3092.   }
  3093.   printf ("Ordered by value:\n");
  3094.   printf ("    Label                          Hex Value  (in decimal)\n");
  3095.   printf ("    ============================== =========  ============\n");
  3096.   for (i=0; i<numberOfLabels; i++) {
  3097.     p = valueIndex [i];
  3098.     printf ("    ");
  3099.     printStringInWidth (p->string, 30);
  3100.     printf ("  %08X   %11d\n", p->value, p->value);
  3101.   }
  3102. }
  3103.  
  3104.  
  3105.  
  3106. /* printStringInWidth (string, width)
  3107. **
  3108. ** This routine prints this string.  It is passed a field width in
  3109. ** characters.  It will print exactly that many characters.  Shorter
  3110. ** strings will be padded with blanks; longer string will be truncated.
  3111. ** If the string length is larger than the available space, the string
  3112. ** will print like this:
  3113. **       aVeryLongAndBor...tring
  3114. **
  3115. */
  3116. void printStringInWidth (char * string, int width) {
  3117.   int i;
  3118.   int len = strlen (string);
  3119.   if (len <= width) {
  3120.     printf ("%s", string);
  3121.     for (i=width; i>len; i--) {
  3122.       printf (" ");
  3123.     }
  3124.   } else if (width < 6) {
  3125.     for (i=0; i<width; i++) {
  3126.       printf ("%c", string[i]);
  3127.     }
  3128.   } else if (width < 20) {
  3129.     for (i=0; i<width-3; i++) {
  3130.       printf ("%c", string[i]);
  3131.     }
  3132.     printf ("...");
  3133.   } else {
  3134.     for (i=0; i<width-8; i++) {
  3135.       printf ("%c", string[i]);
  3136.     }
  3137.     printf ("...");
  3138.     for (i=len-5; i<len; i++) {
  3139.       printf ("%c", string[i]);
  3140.     }
  3141.   }
  3142. }
  3143.  
  3144.  
  3145.  
  3146. /* commandInit ()
  3147. **
  3148. ** This command reinitializes the label table.  It then allows the user to
  3149. ** enter several new entries.
  3150. */
  3151. void commandInit () {
  3152.   int j;
  3153.   char * str;
  3154.   char c, * p;
  3155.   TableEntry * tableEntry;
  3156.   int value = 100;
  3157.  
  3158.   numberOfLabels = 0;
  3159.   while (1) {
  3160.     if (numberOfLabels >= MAX_NUMBER_OF_LABELS) {
  3161.       printf ("Implementation Restriction: Maximum number of labels would be exceeded; aborted.\n");
  3162.       return;
  3163.     }
  3164.     printf ("Enter the name of the next label (\"\" to terminate): ");
  3165.     str = getToken ();
  3166.     if (strlen (str) == 0) return;
  3167.     /* Check to make sure it contains legal characters only. */
  3168.     p = str;
  3169.     while ((c = *p) != 0) {
  3170.       if (c>='a' && c<='z') {
  3171.       } else if (c>='A' && c<='Z') {
  3172.       } else if (c>='0' && c<='9') {
  3173.       } else if (c=='_' || c=='.') {
  3174.       } else {
  3175.         printf ("Labels must contain letters, digits, '_' and '.' only; aborted.\n");
  3176.         return;
  3177.       }
  3178.       p++;
  3179.     }
  3180.   
  3181.     tableEntry = (TableEntry *)
  3182.                      calloc (1, sizeof (TableEntry) + strlen (str) + 1);
  3183.     if (tableEntry == 0) {
  3184.       fatalError ("Calloc failed - insufficient memory available");
  3185.     }
  3186.     tableEntry -> value = genRandom () % 100;
  3187.     strcpy (tableEntry->string, str);
  3188.     alphaIndex [numberOfLabels] = tableEntry;
  3189.     valueIndex [numberOfLabels++] = tableEntry;
  3190.   }
  3191. }
  3192.  
  3193.  
  3194.  
  3195. /* commandInit2 ()
  3196. **
  3197. ** This command reinitializes the label table.  It then allows the user to
  3198. ** enter several new entries.
  3199. */
  3200. void commandInit2 () {
  3201.   int j;
  3202.   char string [100];
  3203.   char c, * p;
  3204.   TableEntry * tableEntry;
  3205.   int value;
  3206.  
  3207.   numberOfLabels = 0;
  3208.   while (1) {
  3209.     if (numberOfLabels >= MAX_NUMBER_OF_LABELS) {
  3210.       printf ("Implementation Restriction: Maximum number of labels would be exceeded; aborted.\n");
  3211.       return;
  3212.     }
  3213.     printf ("Enter the value of the next label in decimal (-999 to terminate): ");
  3214.     value = readDecimalInt ();
  3215.     if (value == -999) return;
  3216.  
  3217.     sprintf (string, "sym_%d", value);
  3218.     tableEntry = (TableEntry *)
  3219.                      calloc (1, sizeof (TableEntry) + strlen (string) + 1);
  3220.     if (tableEntry == 0) {
  3221.       fatalError ("Calloc failed - insufficient memory available");
  3222.     }
  3223.     tableEntry -> value = value;
  3224.     strcpy (tableEntry->string, string);
  3225.     alphaIndex [numberOfLabels] = tableEntry;
  3226.     valueIndex [numberOfLabels++] = tableEntry;
  3227.   }
  3228. }
  3229.  
  3230.  
  3231.  
  3232. /* commandSort ()
  3233. **
  3234. ** Perform a quicksort on the label table, sorting by alpha index.
  3235. */
  3236. void commandSort () {
  3237.   quicksortAlpha (0, numberOfLabels-1);
  3238.   commandLabels ();
  3239. }
  3240.  
  3241.  
  3242.  
  3243. /* commandSort2 ()
  3244. **
  3245. ** Perform a quicksort on the label table, sorting by value index.
  3246. */
  3247. void commandSort2 () {
  3248.   quicksortValue (0, numberOfLabels-1);
  3249.   commandLabels ();
  3250. }
  3251.  
  3252.  
  3253.  
  3254. /* quicksortAlpha ()
  3255. **
  3256. ** This routine sorts the elements in the array from m through n (inclusive).
  3257. ** The sort is on the alphaIndex.
  3258. */
  3259. void quicksortAlpha (int m, int n) {
  3260.   int i;
  3261.   if (n>m) {
  3262.     i = partitionAlpha (m, n);
  3263.     quicksortAlpha (m, i-1);
  3264.     quicksortAlpha (i+1, n);
  3265.   }
  3266. }
  3267.  
  3268.  
  3269.  
  3270. /* partitionAlpha (l, r)
  3271. **
  3272. ** This function is used in quicksorting the array.  It is passed two
  3273. ** indexes ("l" and "r") which elements of the array are to be examined
  3274. ** and rearranged.  This routine will rearrange the elements in the
  3275. ** selected portion of the array, such that, after the partitioning,
  3276. ** all elements with indexes between "l" and "i" (inclusive) will be <=
  3277. ** a[i] and all elements with indexes between "i" and "r" (inclusive)
  3278. ** will be >= a[i].  This routine will compute and return an "i" that
  3279. ** satisfies the above conditions.
  3280. */
  3281. int partitionAlpha (int l, int r) {
  3282.   int i, j;
  3283.   TableEntry * v, * t;
  3284. /***
  3285.   printf ("==== Partition (%d, %d)\n", l, r);
  3286.   dump ();
  3287. ***/
  3288.   v = alphaIndex[r];
  3289.   i = l-1;
  3290.   j = r;
  3291.   while (1) {
  3292.     i++;
  3293.     while (strcmp (alphaIndex[i]->string , v->string) < 0) {
  3294.       i++;
  3295.     }
  3296.     j--;
  3297.     while ((j>=l) && (strcmp (alphaIndex[j]->string , v->string) > 0)) {
  3298.       j--;
  3299.     }
  3300.     t = alphaIndex[i];
  3301.     alphaIndex[i] = alphaIndex[j];
  3302.     alphaIndex[j] = t;
  3303.     if (j<=i) break;
  3304.   }
  3305.   alphaIndex[j] = alphaIndex[i];
  3306.   alphaIndex[i] = alphaIndex[r];
  3307.   alphaIndex[r] = t;
  3308. /***
  3309.   dump ();
  3310.   printf ("====  returns i=  %d\n", i);
  3311. ***/
  3312.   return i;
  3313. }
  3314.  
  3315.  
  3316.  
  3317. /* quicksortValue ()
  3318. **
  3319. ** This routine sorts the elements in the array from m through n (inclusive).
  3320. ** The sort is on the valueIndex.
  3321. */
  3322. void quicksortValue (int m, int n) {
  3323.   int i;
  3324.   if (n>m) {
  3325.     i = partitionValue (m, n);
  3326.     quicksortValue (m, i-1);
  3327.     quicksortValue (i+1, n);
  3328.   }
  3329. }
  3330.  
  3331.  
  3332.  
  3333. /* partitionValue (l, r)
  3334. **
  3335. ** This function is used in quicksorting the array.  It is passed two
  3336. ** indexes ("l" and "r") which elements of the array are to be examined
  3337. ** and rearranged.  This routine will rearrange the elements in the
  3338. ** selected portion of the array, such that, after the partitioning,
  3339. ** all elements with indexes between "l" and "i" (inclusive) will be <=
  3340. ** a[i] and all elements with indexes between "i" and "r" (inclusive)
  3341. ** will be >= a[i].  This routine will compute and return an "i" that
  3342. ** satisfies the above conditions.
  3343. */
  3344. int partitionValue (int l, int r) {
  3345.   int i, j;
  3346.   TableEntry * v, * t;
  3347. /***
  3348.   printf ("==== Partition (%d, %d)\n", l, r);
  3349.   dump ();
  3350. ***/
  3351.   v = valueIndex[r];
  3352.   i = l-1;
  3353.   j = r;
  3354.   while (1) {
  3355.     i++;
  3356.     while (valueIndex[i]->value < v->value) {
  3357.       i++;
  3358.     }
  3359.     j--;
  3360.     while ((j>=l) && (valueIndex[j]->value>v->value)) {
  3361.       j--;
  3362.     }
  3363.     t = valueIndex[i];
  3364.     valueIndex[i] = valueIndex[j];
  3365.     valueIndex[j] = t;
  3366.     if (j<=i) break;
  3367.   }
  3368.   valueIndex[j] = valueIndex[i];
  3369.   valueIndex[i] = valueIndex[r];
  3370.   valueIndex[r] = t;
  3371. /***
  3372.   dump ();
  3373.   printf ("====  returns i=  %d\n", i);
  3374. ***/
  3375.   return i;
  3376. }
  3377.  
  3378.  
  3379.  
  3380. /* commandFind ()
  3381. **
  3382. ** Find a label by name and print it.
  3383. */
  3384. void commandFind () {
  3385.   int i, prefixLength;
  3386.   char * str;
  3387.   TableEntry * tableEntry;
  3388.   printf ("Enter the first few characters of the label; all matching labels will be printed: ");
  3389.   str = getToken ();
  3390.   prefixLength = strlen (str);
  3391.   printf ("    Label                          Hex Value  (in decimal)\n");
  3392.   printf ("    ============================== =========  ============\n");
  3393.   for (i=0; i<numberOfLabels; i++) {
  3394.     tableEntry = alphaIndex [i];
  3395.     if (strlen (tableEntry->string) >= prefixLength) {
  3396.       if (bytesEqual (str, tableEntry->string, prefixLength, prefixLength)) {
  3397.         printf ("    ");
  3398.         printStringInWidth (tableEntry->string, 30);
  3399.         printf ("  %08X   %11d\n", tableEntry->value, tableEntry->value);
  3400.       }
  3401.     }
  3402.   }
  3403.  
  3404. /*****
  3405.   tableEntry = findLabelByAlpha (str, 0, numberOfLabels-1);
  3406.   if (tableEntry == NULL) {
  3407.     printf ("  Nothing found\n");
  3408.   } else {
  3409.     printf ("  %08X   (decimal: %d)   %s\n",
  3410.             tableEntry->value, tableEntry->value, tableEntry->string);
  3411.   }
  3412. *****/
  3413. }
  3414.  
  3415.  
  3416.  
  3417. /* commandFind2 ()
  3418. **
  3419. ** Find a label by value and print it.
  3420. */
  3421. void commandFind2 () {
  3422.   int value, j, index;
  3423.   TableEntry * tableEntry;
  3424.   printf ("Enter the value to find (in hex): ");
  3425.   value = readHexInt ();
  3426.   index = findLabel (value);
  3427.   index = findLabel (value);
  3428.   if (index == -1) {
  3429.     printf ("  Nothing found\n");
  3430.   } else {
  3431.     while (1) {
  3432.       if (index == -1) break;
  3433.       if (index >= numberOfLabels) break;
  3434.       tableEntry = valueIndex [index++];
  3435.       if (tableEntry->value != value) break;
  3436.       printf ("  %08X   (decimal: %d)   %s\n",
  3437.             tableEntry->value, tableEntry->value, tableEntry->string);
  3438.     }
  3439.   }
  3440. }
  3441.  
  3442.  
  3443.  
  3444. /* findLabel (value)
  3445. **
  3446. ** This routine is passed a value.  It searches the label table for a
  3447. ** label with that value.  If one is found, it returns the index within
  3448. ** valueIndex of the entry.  There may be several labels with the desired
  3449. ** value; this routine will return the one with the lowest index.  If the
  3450. ** table is empty or contains no entries equal to value, it returns
  3451. ** index = -1.
  3452. */
  3453. int findLabel (int value) {
  3454.   /* Do the binary search to find a matching label.  */
  3455.   int index = findLabel2 (value, 0, numberOfLabels-1);
  3456.   /* If none at all, return. */
  3457.   if (index == -1) return index;
  3458.   /* Find the lowest numbered index that matches. */
  3459.   while (1) {
  3460.     if (index == 0) return index;
  3461.     if (valueIndex[index-1]->value != value) return index;
  3462.     index--;
  3463.   }
  3464. }
  3465.  
  3466.  
  3467.  
  3468. /* findLabel2 (value, low, high)
  3469. **
  3470. ** This routine is passed a value.  It searches the label table for a
  3471. ** label with that value.  If one is found, it returns the index within
  3472. ** valueIndex of the entry.  There may be several labels with the desired
  3473. ** value; this routine will return an arbitrary on.  If the table is empty
  3474. ** or contains no entries equal to value, it returns index = -1.
  3475. **
  3476. ** This routine uses a binary search.  It is passed "low" and "high" which
  3477. ** indicate which portion of the valueIndex to search.
  3478. **
  3479. ** The initial call should look like this:
  3480. **      i = findLabel2 (value, 0, numberOfLabels-1);
  3481. */
  3482. int findLabel2 (int value, int low, int high) {
  3483.   int mid;
  3484.   if (high - low > 2) {
  3485.     mid = ((high - low) / 2) + low;
  3486.     if (valueIndex [mid]->value <= value) {
  3487.       return findLabel2 (value, mid, high);
  3488.     } else {
  3489.       return findLabel2 (value, low, mid-1);
  3490.     }
  3491.   } else if (high - low == 2) {
  3492.     if (valueIndex [high]->value == value) return high; 
  3493.     if (valueIndex [high-1]->value == value) return high-1;
  3494.     if (valueIndex [low]->value == value) return low;
  3495.     return -1;
  3496.   } else if (high - low == 1) {
  3497.     if (valueIndex [high]->value == value) return high;
  3498.     if (valueIndex [low]->value == value) return low;
  3499.     return -1;
  3500.   } else if (high == low) {
  3501.     if (valueIndex [high]->value == value) return high;
  3502.     return -1;
  3503.   } else {
  3504.     return -1;
  3505.   }
  3506. }
  3507.  
  3508.  
  3509.  
  3510. /* findLabelByAlpha (string, low, high)
  3511. **
  3512. ** This routine is passed a label string.  It searches the label table
  3513. ** and returns a ptr to the TableEntry of the label with that string.
  3514. ** If none matches exactly, it returns NULL.
  3515. **
  3516. ** This routine uses a binary search.  It is passed "low" and "high" which
  3517. ** indicate which portion of the alphaIndex to search.
  3518. **
  3519. ** The initial call should look like this:
  3520. **    p = findLabelByAlpha (string, 0, numberOfLabels-1);
  3521. */
  3522. TableEntry * findLabelByAlpha (char * string, int low, int high) {
  3523.   int mid;
  3524.   if (high - low > 2) {
  3525.     mid = ((high - low) / 2) + low;
  3526.     if (strcmp (alphaIndex [mid]->string , string) <= 0) {
  3527.       return findLabelByAlpha (string, mid, high);
  3528.     } else {
  3529.       return findLabelByAlpha (string, low, mid-1);
  3530.     }
  3531.   } else if (high - low == 2) {
  3532.     if (strcmp (alphaIndex [high]->string , string) == 0)
  3533.       return alphaIndex [high];
  3534.     if (strcmp (alphaIndex [high-1]->string , string) == 0)
  3535.       return alphaIndex [high-1];
  3536.     if (strcmp (alphaIndex [low]->string , string) == 0)
  3537.       return alphaIndex [low];
  3538.     return NULL;
  3539.   } else if (high - low == 1) {
  3540.     if (strcmp (alphaIndex [high]->string , string) == 0)
  3541.       return alphaIndex [high];
  3542.     if (strcmp (alphaIndex [low]->string , string) == 0)
  3543.       return alphaIndex [low];
  3544.     return NULL;
  3545.   } else if (high == low) {
  3546.     if (strcmp (alphaIndex [high]->string , string) == 0)
  3547.       return alphaIndex [high];
  3548.     return NULL;
  3549.   } else {
  3550.     return NULL;
  3551.   }
  3552. }
  3553.  
  3554.  
  3555.  
  3556. /* commandAdd ()
  3557. **
  3558. ** This command prompts for a new label and value.  Then it adds it to
  3559. ** the label table.
  3560. */
  3561. void commandAdd () {
  3562.   int j;
  3563.   char * str;
  3564.   char c, * p;
  3565.   TableEntry * tableEntry;
  3566.  
  3567.   printf ("Enter the name of the new label: ");
  3568.   str = getToken ();
  3569.  
  3570.   /* Check to make sure it contains legal characters only. */
  3571.   p = str;
  3572.   if (strlen (p) <= 0) {
  3573.     printf ("Null string -- command aborted\n");
  3574.     return;
  3575.   }
  3576.   while ((c = *p) != 0) {
  3577.     if (c>='a' && c<='z') {
  3578.     } else if (c>='A' && c<='Z') {
  3579.     } else if (c>='0' && c<='9') {
  3580.     } else if (c=='_' || c=='.') {
  3581.     } else {
  3582.       printf ("Labels must contain letters, digits, '_' and '.' only; aborted.\n");
  3583.       return;
  3584.     }
  3585.     p++;
  3586.   }
  3587.  
  3588.   /* See if this label already exists and abort if so. */
  3589.   tableEntry = findLabelByAlpha (str, 0, numberOfLabels-1);
  3590.   if (tableEntry != NULL) {
  3591.     printf ("  ERROR: Label already exists. You may not delete or change existing labels.\n");
  3592.     return;
  3593.   }
  3594.  
  3595.   /* Create a new TableEntry. */
  3596.   tableEntry = (TableEntry *)
  3597.                    calloc (1, sizeof (TableEntry) + strlen (str) + 1);
  3598.   if (tableEntry == 0) {
  3599.     fatalError ("Calloc failed - insufficient memory available");
  3600.   }
  3601.   strcpy (tableEntry->string, str);
  3602.  
  3603.   /* Get the new label's value. */
  3604.   printf ("Enter the value of the new label (in hex): ");
  3605.   tableEntry -> value = readHexInt ();
  3606.  
  3607.   /* Now insert this label into the alphaIndex and the valueIndex. */
  3608.   insertLabel (tableEntry);
  3609.  
  3610.   printf ("Label \"%s\" has been added.\n", tableEntry->string);
  3611. }
  3612.  
  3613.  
  3614.  
  3615. /* insertLabel (p)
  3616. **
  3617. ** This routine is passed a pointer to a new TableEntry.  It inserts
  3618. ** an index for it into the alphaIndex and into the valueIndex.  If there
  3619. ** is no room, this routine will call fatalError().
  3620. */
  3621. void insertLabel (TableEntry * p) {
  3622.   int i;
  3623.   if (numberOfLabels >= MAX_NUMBER_OF_LABELS) {
  3624.     fatalError ("Implementation restriction - the label table is full");
  3625.   }
  3626.   /* Shift all the labels in the valueIndex up to open up a slot. */
  3627.   i = numberOfLabels;
  3628.   while (i>0) {
  3629.     if (valueIndex[i-1]->value <= p->value) break;
  3630.     valueIndex [i] = valueIndex [i-1];
  3631.     i--;
  3632.   }
  3633.   /* Now i points to the vacant entry; put the new label there. */
  3634.   valueIndex [i] = p;
  3635.   /* Shift all the labels in the alphaIndex up to open up a slot. */
  3636.   i = numberOfLabels;
  3637.   while (i>0) {
  3638.     if (strcmp (alphaIndex[i-1]->string , p->string) <= 0) break;
  3639.     alphaIndex [i] = alphaIndex [i-1];
  3640.     i--;
  3641.   }
  3642.   /* Now i points to the vacant entry; put the new label there. */
  3643.   alphaIndex [i] = p;
  3644.   /* Increment the number of labels. */
  3645.   numberOfLabels++;
  3646. }
  3647.  
  3648.  
  3649.  
  3650. /* insertLabelUnsorted (p)
  3651. **
  3652. ** This routine is passed a pointer to a new TableEntry.  It adds
  3653. ** an index for it to the alphaIndex and to the valueIndex.  This label
  3654. ** is simply placed at the end of the array; there is no sorted insert.
  3655. ** If there is no room, this routine will call fatalError().
  3656. */
  3657. void insertLabelUnsorted (TableEntry * p) {
  3658.   if (numberOfLabels >= MAX_NUMBER_OF_LABELS) {
  3659.     fatalError ("Implementation restriction - the label table is full");
  3660.   }
  3661.   valueIndex [numberOfLabels] = p;
  3662.   alphaIndex [numberOfLabels] = p;
  3663.   numberOfLabels++;
  3664. }
  3665.  
  3666.  
  3667.  
  3668. /* commandReset ()
  3669. **
  3670. ** This command resets the entire machine state and re-reads the
  3671. ** a.out file into memory.
  3672. */
  3673. void commandReset () {
  3674.   printf ("Resetting all CPU registers and re-reading file \"%s\"...\n",
  3675.     executableFileName);
  3676.   resetState ();
  3677.   /* printInfo (); */
  3678. }
  3679.  
  3680.  
  3681.  
  3682. /* resetState ()
  3683. **
  3684. ** This routine resets the entire machine state and re-reads the a.out
  3685. ** file into memory.
  3686. */
  3687. void resetState () {
  3688.   int i, magic, len;
  3689.   char * targetAddr, * p;
  3690.   TableEntry * tableEntry;
  3691.   char buffer [2];
  3692.   FILE * blitzrc;
  3693.   char * first, * second;
  3694.  
  3695.   setSimulationConstants ();
  3696.  
  3697.   if (commandOptionRand) {
  3698.     randomSeed = randSeedFromOption;
  3699.   } else {
  3700.     randomSeed = INIT_RANDOM_SEED;
  3701.   }
  3702.  
  3703.   numberOfDiskReads = 0;
  3704.   numberOfDiskWrites = 0;
  3705.  
  3706.   /* Clear currentAddr, which is used in commandDis. */
  3707.   currentAddr = 0;
  3708.  
  3709.   /* Clear currentFrame, which is used in commandStackUp, commandStackDown. */
  3710.   currentFrame = 0;
  3711.  
  3712.   /* Clear out the label table. */
  3713.   numberOfLabels = 0;
  3714.  
  3715.   /* Reset misc. CPU registers. */
  3716.   pc = 0;
  3717.   ptbr = 0;
  3718.   ptlr = 0;
  3719.   statusN = 0;
  3720.   statusV = 0;
  3721.   statusZ = 0;
  3722.   statusP = 0;
  3723.   statusS = 1;
  3724.   statusI = 0;
  3725.  
  3726.   /* Reset any signalled interrupts. */
  3727.   interruptsSignaled = 0;
  3728.   systemTrapNumber = 0;
  3729.   pageInvalidOffendingAddress = 0;
  3730.   pageReadonlyOffendingAddress = 0;
  3731.  
  3732.   currentTime = 0;
  3733.   timeSpentAsleep = 0;
  3734.   timeOfNextTimerEvent = MAX;
  3735.   timeOfNextDiskEvent = MAX;
  3736.   timeOfNextSerialInEvent = 0;
  3737.   timeOfNextSerialOutEvent = MAX;
  3738.   doTimerEvent ();
  3739.   executionHalted = 0;
  3740.   controlCPressed = 0;
  3741.  
  3742.   /* Reset the disk */
  3743.   initializeDisk ();
  3744.  
  3745.   /* Clear out the typeAheadBuffer. */
  3746.   typeAheadBufferCount = 0;
  3747.   typeAheadBufferIn = 0;
  3748.   typeAheadBufferOut = 0;
  3749.  
  3750.   /* Position the terminal input file to the beginning. */
  3751.   if (termInputFile != stdin) {
  3752.     errno = 0;
  3753.     if (fseek (termInputFile, 0l, SEEK_SET)) {
  3754.       if (errno) perror ("Error on terminal input");
  3755.       fatalError ("Error from fseek for terminal input file");
  3756.     }
  3757.   }
  3758.  
  3759.   /* Reset the serial device. */
  3760.   terminalWantRawProcessing = commandOptionRaw;   /* Default is to have buffered input */
  3761.   termInChar = 0;                   /* Last keyboard key pressed */
  3762.   termInCharAvail = 0;              /* No input available at this time */
  3763.   termInCharWasUsed = 1;            /* Last character was absorbed ok */
  3764.   termOutputReady = 1;              /* Output device is not busy */
  3765.  
  3766.   updateTimeOfNextEvent ();
  3767.  
  3768.   /* If we have already allocated memory, free it. */
  3769.   if (memory != NULL) {
  3770.     free (memory);
  3771.   }
  3772.  
  3773.   /* Allocate a chunk of memory which will hold the BLITZ machine memory. */
  3774.   memory = (char *) calloc (1, MEMORY_SIZE);
  3775.   fflush (stdout);
  3776.   if (memory == 0) {
  3777.     fatalError ("Calloc failed - insufficient memory available");
  3778.   }
  3779.   currentMemoryLock = -1;
  3780.  
  3781.   /* Initialize all integer and floating-point registers to zero. */
  3782.   for (i=0; i<=15; i++) {
  3783.     userRegisters [i] = 0;
  3784.     systemRegisters [i] = 0;
  3785.     floatRegisters [i] = 0.0;
  3786.   }
  3787.  
  3788.   /* Reposition the a.out file to the beginning. */
  3789.   errno = 0;
  3790.   if (fseek (executableFile, 0l, SEEK_SET)) {
  3791.     if (errno) perror ("Error on a.out file");
  3792.     fatalError ("Error from fseek for a.out file");
  3793.   }
  3794.  
  3795.   /* Check the magic number. */
  3796.   magic = readInteger (executableFile);
  3797.   if (magic != 0x424C5A78) {
  3798.     fatalError ("Error in 'a.out' executable file: Magic number is not 'BLZx'");
  3799.   }
  3800.  
  3801.   /* Read in the header info. */
  3802.   textSize = readInteger (executableFile);
  3803.   dataSize = readInteger (executableFile);
  3804.   bssSize = readInteger (executableFile);
  3805.   textAddr = readInteger (executableFile);
  3806.   dataAddr = readInteger (executableFile);
  3807.   bssAddr = readInteger (executableFile);
  3808.  
  3809.   /* Compute the maximum address used and check that this will fit
  3810.      into available memory. */
  3811.   if (textAddr + textSize > MEMORY_SIZE) {
  3812.     fatalError ("The text segment will not fit into memory");
  3813.   }
  3814.   if (dataAddr + dataSize > MEMORY_SIZE) {
  3815.     fatalError ("The data segment will not fit into memory");
  3816.   }
  3817.   if (bssAddr + bssSize > MEMORY_SIZE) {
  3818.     fatalError ("The bss segment will not fit into memory");
  3819.   }
  3820.  
  3821.   /* Read in **** separator. */
  3822.   magic = readInteger (executableFile);
  3823.   if (magic != 0x2a2a2a2a) {
  3824.     fatalError ("Invalid file format - missing \"****\" separator");
  3825.   }
  3826.  
  3827.   /* Read in the text segment. */
  3828.   targetAddr = memory + textAddr;
  3829.   errno = 0;
  3830.   i = fread (targetAddr, 1, textSize, executableFile);
  3831.   if (i != textSize) {
  3832.     if (errno) perror ("Error reading from a.out file");
  3833.     fatalError ("Problems reading text segment from a.out file");
  3834.   }
  3835.  
  3836.   /* Read in **** separator. */
  3837.   magic = readInteger (executableFile);
  3838.   if (magic != 0x2a2a2a2a) {
  3839.     fatalError ("Invalid file format - missing \"****\" separator");
  3840.   }
  3841.  
  3842.   /* Read in the data segment. */
  3843.   targetAddr = memory + dataAddr;
  3844.   errno = 0;
  3845.   i = fread (targetAddr, 1, dataSize, executableFile);
  3846.   if (i != dataSize) {
  3847.     if (errno) perror ("Error reading from a.out file");
  3848.     fatalError ("Problems reading data segment from a.out file");
  3849.   }
  3850.  
  3851.   /* Read in **** separator. */
  3852.   magic = readInteger (executableFile);
  3853.   if (magic != 0x2a2a2a2a) {
  3854.     fatalError ("Invalid file format - missing \"****\" separator");
  3855.   }
  3856.  
  3857.   /* There is nothing to do for the bss segment, since the calloc will
  3858.      have cleared the memory to zero already. */
  3859.  
  3860.   /* Read in the labels and add to the end of the label table. */
  3861.   while (1) {
  3862.     len = readInteger (executableFile);
  3863.     if (len <= 0) break;
  3864.     tableEntry = (TableEntry *)
  3865.                      calloc (1, sizeof (TableEntry) + len + 1);
  3866.     if (tableEntry == 0) {
  3867.       fatalError ("Calloc failed - insufficient memory available");
  3868.     }
  3869.     tableEntry -> value = readInteger (executableFile);
  3870.     p = &( tableEntry->string[0] );
  3871.     for (; len>0; len--) {
  3872.       *p++ = readByte (executableFile);
  3873.     }
  3874.     p = 0;
  3875.     insertLabelUnsorted (tableEntry);
  3876.   }
  3877.  
  3878.   /* Sort the label table by alpha and value. */
  3879.   quicksortAlpha (0, numberOfLabels-1);
  3880.   quicksortValue (0, numberOfLabels-1);
  3881.  
  3882.   /* Read in **** separator. */
  3883.   magic = readInteger (executableFile);
  3884.   if (magic != 0x2a2a2a2a) {
  3885.     fatalError ("Invalid file format - missing \"****\" separator");
  3886.   }
  3887.  
  3888.   /* Finally, set the PC to the first address in the .text segment. */
  3889.   pc = textAddr;
  3890.  
  3891. }
  3892.  
  3893.  
  3894.  
  3895. /* printInfo ()
  3896. **
  3897. ** This routine prints out misc. info about the state of memory.
  3898. */
  3899. void printInfo () {
  3900.   printf ("Memory size = ");
  3901.   printNumberNL2 (MEMORY_SIZE);
  3902.   printf ("Page size   = ");
  3903.   printNumberNL2 (PAGE_SIZE);
  3904. /***
  3905.   printf ("Memory loc  = ");
  3906.   printNumberNL2 ((int) memory);
  3907. ***/
  3908.  
  3909.   printf (".text Segment\n");
  3910.   printf ("    addr    = ");
  3911.   printNumberNL2 (textAddr);
  3912.   printf ("    size    = ");
  3913.   printNumberNL2 (textSize);
  3914.  
  3915.   printf (".data Segment\n");
  3916.   printf ("    addr    = ");
  3917.   printNumberNL2 (dataAddr);
  3918.   printf ("    size    = ");
  3919.   printNumberNL2 (dataSize);
  3920.  
  3921.   printf (".bss Segment\n");
  3922.   printf ("    addr    = ");
  3923.   printNumberNL2 (bssAddr);
  3924.   printf ("    size    = ");
  3925.   printNumberNL2 (bssSize);
  3926. }
  3927.  
  3928.  
  3929.  
  3930. /* commandReg (reg)
  3931. **
  3932. ** This command allows the user to change the value of one of the
  3933. ** registers, r1..r15.  It looks at the status register mode bit
  3934. ** and either changes a system register or a user register.
  3935. */
  3936. void commandReg (int reg) {
  3937.   int value;
  3938.  
  3939.   /* Print out the old value. */
  3940.   if (statusS == 1) {
  3941.     printf ("  SYSTEM r%d = ", reg);
  3942.     printNumberNL (systemRegisters [reg]);
  3943.   } else {
  3944.     printf ("  USER r%d = ", reg);
  3945.     printNumberNL (userRegisters [reg]);
  3946.   }
  3947.  
  3948.   /* Read in the new value. */
  3949.   printf ("Enter the new value (in hex): ");
  3950.   value = readHexInt ();
  3951.  
  3952.   /* Change the register and print out the new value. */
  3953.   if (statusS == 1) {
  3954.     systemRegisters [reg] = value;
  3955.     printf ("  SYSTEM r%d = ", reg);
  3956.     printNumberNL (systemRegisters [reg]);
  3957.   } else {
  3958.     userRegisters [reg] = value;
  3959.     printf ("  USER r%d = ", reg);
  3960.     printNumberNL (userRegisters [reg]);
  3961.   }
  3962. }
  3963.  
  3964.  
  3965.  
  3966. /* commandFloatReg (reg)
  3967. **
  3968. ** This command allows the user to change the value of one of the
  3969. ** floating-point registers, f0..f15.
  3970. */
  3971. void commandFloatReg (int reg) {
  3972.   double value, d;
  3973.  
  3974.   /* Print out the old value. */
  3975.   d = floatRegisters [reg];
  3976.   printf ("  f%d = ", reg);
  3977.   printDouble (d);
  3978.  
  3979.   /* Read in the new value. */
  3980.   printf ("Enter the new value (e.g., 1.1, -123.456e-10, nan, inf, -inf): ");
  3981.   value = readDouble ();
  3982.  
  3983.   /* Change the register and print out the new value. */
  3984.   floatRegisters [reg] = value;
  3985.   printf ("  f%d = ", reg);
  3986.   printDouble (value);
  3987. }
  3988.  
  3989.  
  3990.  
  3991. /* commandFMem ()
  3992. **
  3993. ** This command allows the user to dump memory, interpreting the
  3994. ** contents as floating point numbers.
  3995. */
  3996. void commandFMem () {
  3997.   int i, count, index, implAddr, physAddr, from, to;
  3998.   double d;
  3999.   TableEntry * tableEntry;
  4000.  
  4001.   printf ("Enter the beginning phyical address (in hex): ");
  4002.   physAddr = readHexInt ();
  4003.   physAddr = physAddr & 0xfffffffc;
  4004.   if (!physicalAddressOk (physAddr)) {
  4005.     printf ("This is not a valid physical memory address.\n");
  4006.     return;
  4007.   }
  4008.   count = 32;  /* Display 32 floating point numbers. */
  4009.   printf ("Dumping 256 bytes as 32 double-precision floating-points...\n");
  4010.   physAddr = physAddr & 0xfffffffc;
  4011.   for (i=0; i<count; i++) {
  4012.  
  4013.     /* Check the address to make sure it is legal. */
  4014.     if (!physicalAddressOk (physAddr) || !isAligned (physAddr)) {
  4015.       printf ("Bad address - aborting.\n");
  4016.       return;
  4017.     }
  4018.  
  4019.     /* Fetch the data. */
  4020.     implAddr = ((int) memory) + physAddr;
  4021.     to = (int) & d;
  4022.     * (int *) (to + 0) = * (int *) (implAddr+0);
  4023.     * (int *) (to + 4) = * (int *) (implAddr+4);
  4024.  
  4025.     /* Print out the label(s) if any. */
  4026.     index = findLabel (physAddr);
  4027.     while (1) {
  4028.       if (index == -1) break;
  4029.       if (index >= numberOfLabels) break;
  4030.       tableEntry = valueIndex [index++];
  4031.       if (tableEntry->value != physAddr) break;
  4032.       printf ("%s:\n", tableEntry->string);
  4033.     }
  4034.  
  4035.     /* Print out the address and the value. */
  4036.     printf ("   %06X: %08X %08X   value = %.15g\n",
  4037.       physAddr,
  4038.       * (int *) implAddr,
  4039.       * (int *) (implAddr + 4),
  4040.       d);
  4041.  
  4042.     physAddr = physAddr + 8;
  4043.   }
  4044.  
  4045. }
  4046.  
  4047.  
  4048.  
  4049. /* commandDis ()
  4050. **
  4051. ** This routine disassembles BLITZ instructions.  It asks the users
  4052. ** where to begin.
  4053. */
  4054. void commandDis () {
  4055.   printf ("Enter the beginning phyical address (in hex): ");
  4056.   currentAddr = readHexInt ();
  4057.   currentAddr = currentAddr & 0xfffffffc;
  4058.   if (!physicalAddressOk (currentAddr)) {
  4059.     printf ("This is not a valid physical memory address.\n");
  4060.     currentAddr = 0;
  4061.     return;
  4062.   }
  4063.   commandDis2 ();
  4064. }
  4065.  
  4066.  
  4067.  
  4068. /* commandDis2 ()
  4069. **
  4070. ** This routine disassembles several BLITZ instructions from the current
  4071. ** address.
  4072. */
  4073. void commandDis2 () {
  4074.   int i, count, index;
  4075.   TableEntry * tableEntry;
  4076.   count = 30;
  4077.   currentAddr = currentAddr & 0xfffffffc;
  4078.   for (i=0; i<count; i++) {
  4079.     if (!physicalAddressOk (currentAddr)) {
  4080.       printf ("Physical memory limit exceeded.\n");
  4081.       currentAddr = 0;
  4082.       return;
  4083.     }
  4084.     disassemble (currentAddr);
  4085.     currentAddr = currentAddr + 4;
  4086.   }
  4087. }
  4088.  
  4089.  
  4090.  
  4091. /* disassemble (physAddr)
  4092. **
  4093. ** This routine disassembles and prints a single BLITZ instruction.
  4094. ** This routine is passed the addr.  If this address is not a
  4095. ** a legal physical address in the BLITZ memory, it prints a message
  4096. ** and returns.
  4097. */
  4098. void disassemble (int physAddr) {
  4099.   int opcode, opcode2, cat, n, index, implAddr, instr, instr2, i1, i2;
  4100.   TableEntry * tableEntry;
  4101.   char c;
  4102.  
  4103.   char * opcodes [] = {
  4104.  
  4105. /* 0 .. 31 */
  4106. "nop", "wait", "debug", "cleari", "seti", "clearp", "setp", "clears",
  4107. "reti", "ret", "debug2", "---", "---", "---", "---", "---",
  4108. "---", "---", "---", "---", "---", "---", "---", "---",
  4109. "---", "---", "---", "---", "---", "---", "---", "---",
  4110.  
  4111. /* 32 .. 63 */
  4112. "ldptbr", "ldptlr", "---", "---", "---", "---", "---", "---",
  4113. "---", "---", "---", "---", "---", "---", "---", "---",
  4114. "---", "---", "---", "---", "---", "---", "---", "---",
  4115. "---", "---", "---", "---", "---", "---", "---", "---",
  4116.  
  4117. /* 64 .. 95 */
  4118. "call", "jmp", "be", "bne", "bl", "ble", "bg", "bge",
  4119. "---", "---", "bvs", "bvc", "bns", "bnc", "bss", "bsc",
  4120. "bis", "bic", "bps", "bpc", "push", "pop", "readu", "writeu",
  4121. "tset", "ftoi", "itof", "fcmp", "fsqrt", "fneg", "fabs", "---",
  4122.  
  4123. /* 96 .. 127 */
  4124. "add", "sub", "mul", "div", "sll", "srl", "sra", "or",
  4125. "and", "andn", "xor", "load", "loadb", "loadv", "loadbv", "store",
  4126. "storeb", "storev", "storebv", "rem", "fadd", "fsub", "fmul", "fdiv",
  4127. "fload", "fstore", "---", "---", "---", "---", "---", "---",
  4128.  
  4129. /* 128 .. 159 */
  4130. "add", "sub", "mul", "div", "sll", "srl", "sra", "or",
  4131. "and", "andn", "xor", "load", "loadb", "loadv", "loadbv", "store",
  4132. "storeb", "storev", "storebv", "readu", "writeu", "rem", "fload", "fstore",
  4133. "---", "---", "---", "---", "---", "---", "---", "---",
  4134.  
  4135. /* 160 .. 191 */
  4136. "call", "jmp", "be", "bne", "bl", "ble", "bg", "bge",
  4137. "---", "---", "bvs", "bvc", "bns", "bnc", "bss", "bsc",
  4138. "bis", "bic", "bps", "bpc", "---", "---", "---", "---",
  4139. "---", "---", "---", "---", "---", "---", "---", "---",
  4140.  
  4141. /* 192 .. 223 */
  4142. "sethi", "setlo", "ldaddr", "syscall", "---", "---", "---", "---",
  4143. "---", "---", "---", "---", "---", "---", "---", "---",
  4144. "---", "---", "---", "---", "---", "---", "---", "---",
  4145. "---", "---", "---", "---", "---", "---", "---", "---",
  4146.  
  4147. /* 224 .. 255 */
  4148. "---", "---", "---", "---", "---", "---", "---", "---",
  4149. "---", "---", "---", "---", "---", "---", "---", "---",
  4150. "---", "---", "---", "---", "---", "---", "---", "---",
  4151. "---", "---", "---", "---", "---", "---", "---", "---",
  4152.  
  4153. };
  4154.  
  4155.   int  category [] = {
  4156. /* 0 .. 31
  4157. nop, wait, debug, cleari, seti, clearp, setp, clears,
  4158. reti, ret, debug2, xxx, xxx, xxx, xxx, xxx,
  4159. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4160. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4161. */
  4162. 1, 1, 1, 1, 1, 1, 1, 1,
  4163. 1, 1, 1, 0, 0, 0, 0, 0,
  4164. 0, 0, 0, 0, 0, 0, 0, 0,
  4165. 0, 0, 0, 0, 0, 0, 0, 0,
  4166.  
  4167. /* 32 .. 63
  4168. ldptbr, ldptlr, xxx, xxx, xxx, xxx, xxx, xxx,
  4169. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4170. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4171. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4172. */
  4173. 17, 17, 0, 0, 0, 0, 0, 0,
  4174. 0, 0, 0, 0, 0, 0, 0, 0,
  4175. 0, 0, 0, 0, 0, 0, 0, 0,
  4176. 0, 0, 0, 0, 0, 0, 0, 0,
  4177.  
  4178. /* 64 .. 95
  4179. call, jmp, be, bne, bl, ble, bg, bge,
  4180. xxx, xxx, bvs, bvc, bns, bnc, bss, bsc,
  4181. bis, bic, bps, bpc, push, pop, readu, writeu,
  4182. tset, ftoi, itof, fcmp, fsqrt, fneg, fabs, xxx,
  4183. */
  4184. 8, 8, 8, 8, 8, 8, 8, 8,
  4185. 0, 0, 8, 8, 8, 8, 8, 8,
  4186. 8, 8, 8, 8, 10, 11, 15, 16,
  4187. 14, 19, 20, 22, 22, 22, 22, 0,
  4188.  
  4189. /* 96 .. 127
  4190. add, sub, mul, div, sll, srl, sra, or,
  4191. and, andn, xor, load, loadb, loadv, loadbv, store,
  4192. storeb, storev, storebv, rem, fadd, fsub, fmul, fdiv,
  4193. fload, fstore, xxx, xxx, xxx, xxx, xxx, xxx,
  4194. */
  4195. 2, 2, 2, 2, 2, 2, 2, 2,
  4196. 2, 2, 2, 4, 4, 4, 4, 6,
  4197. 6, 6, 6, 2, 21, 21, 21, 21,
  4198. 23, 25, 0, 0, 0, 0, 0, 0,
  4199.  
  4200. /* 128 .. 159
  4201. add, sub, mul, div, sll, srl, sra, or,
  4202. and, andn, xor, load, loadb, loadv, loadbv, store,
  4203. storeb, storev, storebv, readu, writeu, rem, fload, fstore,
  4204. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4205. */
  4206. 3, 3, 3, 3, 3, 3, 3, 3,
  4207. 3, 3, 3, 5, 5, 5, 5, 7,
  4208. 7, 7, 7, 7, 5, 3, 24, 26,
  4209. 0, 0, 0, 0, 0, 0, 0, 0,
  4210.  
  4211. /* 160 .. 191
  4212. call, jmp, be, bne, bl, ble, bg, bge,
  4213. xxx, xxx, bvs, bvc, bns, bnc, bss, bsc,
  4214. bis, bic, bps, bpc, xxx, xxx, xxx, xxx,
  4215. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4216. */
  4217. 9, 9, 9, 9, 9, 9, 9, 9,
  4218. 0, 0, 9, 9, 9, 9, 9, 9,
  4219. 9, 9, 9, 9, 0, 0, 0, 0,
  4220. 0, 0, 0, 0, 0, 0, 0, 0,
  4221.  
  4222. /* 192 .. 223
  4223. sethi, setlo, ldaddr, syscall, xxx, xxx, xxx, xxx,
  4224. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4225. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4226. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4227. */
  4228. 12, 12, 18, 13, 0, 0, 0, 0,
  4229. 0, 0, 0, 0, 0, 0, 0, 0,
  4230. 0, 0, 0, 0, 0, 0, 0, 0,
  4231. 0, 0, 0, 0, 0, 0, 0, 0,
  4232.  
  4233. /* 224 .. 255
  4234. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4235. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4236. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4237. xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  4238. */
  4239. 0, 0, 0, 0, 0, 0, 0, 0,
  4240. 0, 0, 0, 0, 0, 0, 0, 0,
  4241. 0, 0, 0, 0, 0, 0, 0, 0,
  4242. 0, 0, 0, 0, 0, 0, 0, 0,
  4243.  
  4244. };
  4245.  
  4246.   /* Check the address to make sure it is legal. */
  4247.   if (!physicalAddressOk (physAddr) || !isAligned (physAddr)) {
  4248.     printf ("Disassemble: Bad address.\n");
  4249.     return;
  4250.   }
  4251.  
  4252.   /* Fetch the instruction. */
  4253.   implAddr = ((int) memory) + physAddr;
  4254.   instr = * (int *) implAddr;
  4255.  
  4256.   /* Print out the label(s) if any. */
  4257.   index = findLabel (physAddr);
  4258.   while (1) {
  4259.     if (index == -1) break;
  4260.     if (index >= numberOfLabels) break;
  4261.     tableEntry = valueIndex [index++];
  4262.     if (tableEntry->value != physAddr) break;
  4263.     printf ("                   %s:\n", tableEntry->string);
  4264.   }
  4265.   printf ("%06X: %08X       ", physAddr, * (int *) implAddr);
  4266.  
  4267.   opcode = (instr >> 24) & 0x000000ff;
  4268.   printStringInWidth (opcodes[opcode], 8);
  4269.  
  4270.   cat = category[opcode];
  4271.   switch (cat) {
  4272.     case 0:
  4273.       printf ("\t\t\t! Not an instruction\n");
  4274.       break;
  4275.     case 1:
  4276.       printf ("\n");
  4277.       break;
  4278.     case 2:
  4279.       printRa (instr);
  4280.       printf (",");
  4281.       printRb (instr);
  4282.       printf (",");
  4283.       printRc (instr);
  4284.       printf ("\n");
  4285.       break;
  4286.     case 3:
  4287.       printRa (instr);
  4288.       printf (",");
  4289.       printData16 (instr);
  4290.       printf (",");
  4291.       printRc (instr);
  4292.       printComment (instr & 0x0000ffff);
  4293.       break;
  4294.     case 4:
  4295.       printf ("[");
  4296.       printRa (instr);
  4297.       printf ("+");
  4298.       printRb (instr);
  4299.       printf ("],");
  4300.       printRc (instr);
  4301.       printf ("\n");
  4302.       break;
  4303.     case 5:
  4304.       printf ("[");
  4305.       printRa (instr);
  4306.       printf ("+");
  4307.       printData16 (instr);
  4308.       printf ("],");
  4309.       printRc (instr);
  4310.       printComment2 (instr & 0x0000ffff);
  4311.       break;
  4312.     case 6:
  4313.       printRc (instr);
  4314.       printf (",[");
  4315.       printRa (instr);
  4316.       printf ("+");
  4317.       printRb (instr);
  4318.       printf ("]");
  4319.       printf ("\n");
  4320.       break;
  4321.     case 7:
  4322.       printRc (instr);
  4323.       printf (",[");
  4324.       printRa (instr);
  4325.       printf ("+");
  4326.       printData16 (instr);
  4327.       printf ("]");
  4328.       printComment2 (instr & 0x0000ffff);
  4329.       break;
  4330.     case 8:
  4331.       printRa (instr);
  4332.       printf ("+");
  4333.       printRc (instr);
  4334.       printf ("\n");
  4335.       break;
  4336.     case 9:
  4337.       printData24 (instr);
  4338.       n = instr << 8;
  4339.       if (n<0) {
  4340.         n = instr | 0xff000000;
  4341.       } else {
  4342.         n = instr & 0x00ffffff;
  4343.       }
  4344.       index = findLabel (n+physAddr);
  4345.       if (index != -1) {
  4346.         printf ("\t\t! targetAddr = %s", valueIndex[index]->string);
  4347.       } else {
  4348.         printf ("\t\t! targetAddr = 0x%06X ", n+physAddr);
  4349.       }
  4350.       printf ("\n");
  4351.       break;
  4352.     case 10:
  4353.       printRc (instr);
  4354.       printf (",[--");
  4355.       printRa (instr);
  4356.       printf ("]");
  4357.       printf ("\n");
  4358.       break;
  4359.     case 11:
  4360.       printf ("[");
  4361.       printRa (instr);
  4362.       printf ("++],");
  4363.       printRc (instr);
  4364.       printf ("\n");
  4365.       break;
  4366.     case 12:      /* sethi, setlo */
  4367.       printData16 (instr);
  4368.       printf (",");
  4369.       printRc (instr);
  4370.       /* Fetch the next instruction. */
  4371.       if (physicalAddressOk (physAddr+4)) {
  4372.         implAddr = ((int) memory) + physAddr + 4;
  4373.         instr2 = * (int *) implAddr;
  4374.         opcode2 = (instr2 >> 24) & 0x000000ff;
  4375.       } else {
  4376.         opcode2 = 0;
  4377.       }
  4378.       /* If this instruction is a sethi and the next is a setlo, then... */
  4379.       if ((opcode == 192) && (opcode2 == 193)) {   /* SETHI == 192, SETLO=193 */
  4380.         i1 = instr & 0x0000ffff;
  4381.         i2 = instr2 & 0x0000ffff;
  4382.         printf ("\t! 0x%04X%04X = %d", i1, i2, (i1<< 16)|i2);
  4383.         index = findLabel ((i1<< 16)|i2);
  4384.         if (index != -1) {
  4385.           printf (" (%s)", valueIndex[index]->string);
  4386.         }
  4387.       }
  4388.       printf ("\n");
  4389.       break;
  4390.     case 13:
  4391.       printRc (instr);
  4392.       printf ("+");
  4393.       printData16 (instr);
  4394.       printComment2 (instr & 0x0000ffff);
  4395.       break;
  4396.     case 14:
  4397.       printf ("[");
  4398.       printRa (instr);
  4399.       printf ("],");
  4400.       printRc (instr);
  4401.       printf ("\n");
  4402.       break;
  4403.     case 15:
  4404.       printRc (instr);
  4405.       printf (",");
  4406.       printRa (instr);
  4407.       printf ("\n");
  4408.       break;
  4409.     case 16:
  4410.       printRa (instr);
  4411.       printf (",");
  4412.       printRc (instr);
  4413.       printf ("\n");
  4414.       break;
  4415.     case 17:
  4416.       printRc (instr);
  4417.       printf ("\n");
  4418.       break;
  4419.     case 18:
  4420.       printData16 (instr);
  4421.       printf (",");
  4422.       printRc (instr);
  4423.       n = instr << 16;
  4424.       if (n<0) {
  4425.         n = instr | 0xffff0000;
  4426.       } else {
  4427.         n = instr & 0x0000ffff;
  4428.       }
  4429.       index = findLabel (n+physAddr);
  4430.       if (index != -1) {
  4431.         printf ("\t! targetAddr = %s", valueIndex[index]->string);
  4432.       } else {
  4433.         printf ("\t! targetAddr = 0x%06X ", n+physAddr);
  4434.       }
  4435.       printf ("\n");
  4436.       break;
  4437.     case 19:
  4438.       printFRa (instr);
  4439.       printf (",");
  4440.       printRc (instr);
  4441.       printf ("\n");
  4442.       break;
  4443.     case 20:
  4444.       printRa (instr);
  4445.       printf (",");
  4446.       printFRc (instr);
  4447.       printf ("\n");
  4448.       break;
  4449.     case 21:
  4450.       printFRa (instr);
  4451.       printf (",");
  4452.       printFRb (instr);
  4453.       printf (",");
  4454.       printFRc (instr);
  4455.       printf ("\n");
  4456.       break;
  4457.     case 22:
  4458.       printFRa (instr);
  4459.       printf (",");
  4460.       printFRc (instr);
  4461.       printf ("\n");
  4462.       break;
  4463.     case 23:
  4464.       printf ("[");
  4465.       printRa (instr);
  4466.       printf ("+");
  4467.       printRb (instr);
  4468.       printf ("],");
  4469.       printFRc (instr);
  4470.       printf ("\n");
  4471.       break;
  4472.     case 24:
  4473.       printf ("[");
  4474.       printRa (instr);
  4475.       printf ("+");
  4476.       printData16 (instr);
  4477.       printf ("],");
  4478.       printFRc (instr);
  4479.       printComment2 (instr & 0x0000ffff);
  4480.       break;
  4481.     case 25:
  4482.       printFRc (instr);
  4483.       printf (",[");
  4484.       printRa (instr);
  4485.       printf ("+");
  4486.       printRb (instr);
  4487.       printf ("]");
  4488.       printf ("\n");
  4489.       break;
  4490.     case 26:
  4491.       printFRc (instr);
  4492.       printf (",[");
  4493.       printRa (instr);
  4494.       printf ("+");
  4495.       printData16 (instr);
  4496.       printf ("]");
  4497.       printComment2 (instr & 0x0000ffff);
  4498.       break;
  4499.     default:
  4500.       fatalError ("PROGRAM LOGIC ERROR: within disassemble");
  4501.   }
  4502. }
  4503.  
  4504.  
  4505.  
  4506. /* printRa (instr)
  4507. ** printRb (instr)
  4508. ** printRc (instr)
  4509. ** printFRa (instr)
  4510. ** printFRb (instr)
  4511. ** printFRc (instr)
  4512. ** printData16 (instr)
  4513. ** printData24 (instr)
  4514. **
  4515. ** These routines print the selected field from the instruction.
  4516. */
  4517. void printRa (int instr) {
  4518.   printf ("r%d", (instr >> 16) & 0x0000000f);
  4519. }
  4520.  
  4521. void printRb (int instr) {
  4522.   printf ("r%d", (instr >> 12) & 0x0000000f);
  4523. }
  4524.  
  4525. void printRc (int instr) {
  4526.   printf ("r%d", (instr >> 20) & 0x0000000f);
  4527. }
  4528.  
  4529. void printFRa (int instr) {
  4530.   printf ("f%d", (instr >> 16) & 0x0000000f);
  4531. }
  4532.  
  4533. void printFRb (int instr) {
  4534.   printf ("f%d", (instr >> 12) & 0x0000000f);
  4535. }
  4536.  
  4537. void printFRc (int instr) {
  4538.   printf ("f%d", (instr >> 20) & 0x0000000f);
  4539. }
  4540.  
  4541. void printData16 (int instr) {
  4542.   printf ("0x%04X", instr & 0x0000ffff);
  4543. }
  4544.  
  4545. void printData24 (int instr) {
  4546.   printf ("0x%06X", instr & 0x00ffffff);
  4547. }
  4548.  
  4549.  
  4550.  
  4551. /* printComment (i)
  4552. **
  4553. ** This routine prints a number in the form
  4554. **       ! decimal = 32767  ".."  (label)
  4555. ** There is a leading tab printed and the output is followed by a newline.
  4556. */
  4557. void printComment (int i) {
  4558.   char c;
  4559.   int index;
  4560.  
  4561.   /* Sign extend the 16 bit number in i. */
  4562.   if ((i << 16) < 0) {
  4563.     i = i | 0xffff0000;
  4564.   } else {
  4565.     i = i & 0x0000ffff;
  4566.   }
  4567.  
  4568.   if (i != 0) {
  4569.     printf ("\t! decimal: %d, ascii: \"", i);
  4570.     c = (i >> 8) & 0x000000ff;
  4571.     if ((c>=' ') && (c <= '~')) {
  4572.       putchar (c);
  4573.     } else {
  4574.       putchar ('.');
  4575.     }
  4576.     c = i & 0x000000ff;
  4577.     if ((c>=' ') && (c <= '~')) {
  4578.       putchar (c);
  4579.     } else {
  4580.       putchar ('.');
  4581.     }
  4582.     printf ("\"  ");
  4583.     index = findLabel (i);
  4584.     if (index != -1) {
  4585.       printf ("(%s)", valueIndex [index]->string);
  4586.     }
  4587.   }
  4588.   printf ("\n");
  4589. }
  4590.  
  4591.  
  4592.  
  4593. /* printComment2 (i)
  4594. **
  4595. ** This routine prints a number in the form
  4596. **       ! decimal = -2147483648  (label)
  4597. ** There is a leading tab printed and the output is followed by a newline.
  4598. */
  4599. void printComment2 (int i) {
  4600.   char c;
  4601.   int index;
  4602.  
  4603.   /* Sign extend the 16 bit number in i. */
  4604.   if ((i << 16) < 0) {
  4605.     i = i | 0xffff0000;
  4606.   } else {
  4607.     i = i & 0x0000ffff;
  4608.   }
  4609.  
  4610.   /* Print the number. */
  4611.   printf ("\t! decimal: %d", i);
  4612.  
  4613.   /* If there is a label with that value, print it too. */
  4614.   index = findLabel (i);
  4615.   if (index != -1) {
  4616.     printf ("  (%s)", valueIndex [index]->string);
  4617.   }
  4618.   printf ("\n");
  4619. }
  4620.  
  4621.  
  4622.  
  4623. /* printAboutToExecute ()
  4624. **
  4625. ** This routine disassembles and prints the next instruction, which
  4626. ** is about to be executed.  It will not cause any exceptions, but will
  4627. ** notify the user if there would be problems.
  4628. */
  4629. void printAboutToExecute () {
  4630.   int physAddr;
  4631.   /* Call translate with doReading=1, wantPrinting=0, and doUpdates=0. */
  4632.   physAddr = translate (pc, 1, 0, 0);
  4633.   if (translateCausedException) {
  4634.     printf ("*****  WARNING: A PAGE_INVALID_EXCEPTION, ADDRESS_EXCEPTION, or ALIGNMENT_EXCEPTION will occur during the next instruction fetch  *****\n");
  4635.     return;
  4636.   }
  4637.   printf ("The next instruction to execute will be:\n");
  4638.   disassemble (physAddr);
  4639. }
  4640.  
  4641.  
  4642.  
  4643. /* commandStepN ()
  4644. **
  4645. ** Begin BLITZ execution, by repeatedly calling singleStep().
  4646. */
  4647. void commandStepN () {
  4648.   int count;
  4649.   printf ("Enter the number of instructions to execute: ");
  4650.   count = readDecimalInt ();
  4651.   commandGo (count);
  4652. }
  4653.  
  4654.  
  4655.  
  4656. /* commandGo (count)
  4657. **
  4658. ** Execute count BLITZ instructions, by calling singleStep() that
  4659. ** many times.  Count may be MAX, which will achieve infinite execution.
  4660. */
  4661. void commandGo (int count) {
  4662.   int i;
  4663.   printf ("Beginning execution...\n");
  4664.   wantPrintingInSingleStep = 0;
  4665.   executionHalted = 0;
  4666.   turnOnTerminal ();
  4667.   for (i=0; i<count; i++) {
  4668.     if (executionHalted) {
  4669.       break;
  4670.     }
  4671.     if (controlCPressed) {
  4672.       controlCPressed = 0;
  4673.       break;
  4674.     }
  4675.     singleStep ();
  4676.   }
  4677.   turnOffTerminal ();
  4678.   printf ("Done!  ");
  4679.   printAboutToExecute ();
  4680. }
  4681.  
  4682.  
  4683.  
  4684. /* commandStepHigh ()
  4685. **
  4686. ** Execute several instructions, by calling singleStep(), until we detect that
  4687. ** r10 has changed.  This signals the beginning of the next high-level
  4688. ** instruction.
  4689. */
  4690. void commandStepHigh () {
  4691.   int oldR10;
  4692.   // printf ("STEP HIGH...\n");
  4693.   wantPrintingInSingleStep = 1;
  4694.   executionHalted = 0;
  4695.   turnOnTerminal ();
  4696.   if (statusS) {
  4697.     oldR10 = systemRegisters [10];
  4698.   } else {
  4699.     oldR10 = userRegisters [10];
  4700.   }
  4701.   while (1) {
  4702.     if (executionHalted) {
  4703.       break;
  4704.     }
  4705.     if (controlCPressed) {
  4706.       controlCPressed = 0;
  4707.       break;
  4708.     }
  4709.  
  4710.     singleStep ();
  4711.     if (statusS) {
  4712.       if (oldR10 != systemRegisters [10]) break;
  4713.     } else {
  4714.       if (oldR10 != userRegisters [10]) break;
  4715.     }
  4716.   }
  4717.   turnOffTerminal ();
  4718.   printKPLStmtCode ();
  4719. }
  4720.  
  4721.  
  4722.  
  4723. /* commandStepHigh2 ()
  4724. **
  4725. ** Execute several instructions, by calling singleStep(), until we detect that
  4726. ** r10 has been set to "FU", "ME", or "RE".  This indicates that we are
  4727. ** entering or leaving some KPL function/method.
  4728. */
  4729. void commandStepHigh2 () {
  4730.   int newR10, oldR10;
  4731.   // printf ("STEP HIGH 2...\n");
  4732.   wantPrintingInSingleStep = 1;
  4733.   executionHalted = 0;
  4734.   turnOnTerminal ();
  4735.   while (1) {
  4736.     if (executionHalted) {
  4737.       break;
  4738.     }
  4739.     if (controlCPressed) {
  4740.       controlCPressed = 0;
  4741.       break;
  4742.     }
  4743.  
  4744.     if (statusS) {
  4745.       oldR10 = systemRegisters [10];
  4746.     } else {
  4747.       oldR10 = userRegisters [10];
  4748.     }
  4749.     singleStep ();
  4750.     if (statusS) {
  4751.       newR10 = systemRegisters [10];
  4752.     } else {
  4753.       newR10 = userRegisters [10];
  4754.     }
  4755.     if ((newR10 != oldR10) &&
  4756.         (newR10 == '\0\0FU' || newR10 == '\0\0ME' || newR10 == '\0\0RE')) {
  4757.       break;
  4758.     }
  4759.   }
  4760.   turnOffTerminal ();
  4761.   printKPLStmtCode ();
  4762. }
  4763.  
  4764.  
  4765.  
  4766. /* commandStep ()
  4767. **
  4768. ** Execute a single BLITZ instruction and print the next instruction to
  4769. ** be executed.
  4770. */
  4771. void commandStep () {
  4772.  
  4773.   wantPrintingInSingleStep = 1;
  4774.   turnOnTerminal ();
  4775.   singleStep ();
  4776.   turnOffTerminal ();
  4777.  
  4778.   /* Print the next instruction. */
  4779.   printf ("Done!  ");
  4780.   printAboutToExecute ();
  4781.  
  4782.   /*****
  4783.   if (getNextInterrupt ()) {
  4784.     printf ("Done!\n");
  4785.     // Don't print next instruction, since it will be pre-emted.
  4786.   } else {
  4787.     printf ("Done!  ");
  4788.     printAboutToExecute ();
  4789.   }
  4790.   *****/
  4791. }
  4792.  
  4793.  
  4794.  
  4795. /* singleStep ()
  4796. **
  4797. ** This routine will execute the next BLITZ instruction and return.
  4798. */
  4799. void singleStep () {
  4800.   int instr, opcode, x, y, z, thisInterrupt, sp, oldStatusReg, i, overflow;
  4801.   double d1, d2, d3;
  4802.   int physAddr, physAddr2, word, saveP, regNumber, regA, regC;
  4803.   int * p;
  4804.  
  4805.   // printf ("_");
  4806.  
  4807.   /* Increment the current time by 1 cycle.  This will overflow after
  4808.      perhaps 5 to 45 minutes of CPU-bound execution time, depending on the
  4809.      host speed. */
  4810.   if (++currentTime >= MAX) {
  4811.     fatalError ("Implementation Restriction: Current time overflow");
  4812.   }
  4813.  
  4814.   /* Check to see if we need to process an event. */
  4815.   i = 0;
  4816.   while (currentTime >= timeOfNextEvent) {
  4817.     if (currentTime >= timeOfNextTimerEvent) {
  4818.       // printf ("t");
  4819.       doTimerEvent ();
  4820.     }
  4821.     if (currentTime >= timeOfNextDiskEvent) {
  4822.       doDiskEvent ();
  4823.     }
  4824.     if (currentTime >= timeOfNextSerialInEvent) {
  4825.       // printf ("i");
  4826.       doSerialInEvent (0);
  4827.     }
  4828.     if (currentTime >= timeOfNextSerialOutEvent) {
  4829.       // printf ("o");
  4830.       doSerialOutEvent ();
  4831.     }
  4832.     updateTimeOfNextEvent ();
  4833.     if (++i > 100) {
  4834.       fatalError ("PROGRAM LOGIC ERROR: Too many events");
  4835.     }
  4836.   }
  4837.  
  4838.  
  4839.   /* Check for and process any and all interrupts that have been signaled.
  4840.      Each iteration of this loop looks at the next interrupt.  The call
  4841.      to getNextInterrupt will ignore maskable interrupts if interrupts
  4842.      are currently disabled (i.e., if statusI=0).  */
  4843.   if (thisInterrupt = getNextInterrupt ()) {
  4844.  
  4845.     // printf (".");
  4846.  
  4847.     if (wantPrintingInSingleStep) {
  4848.       if (interruptsSignaled & POWER_ON_RESET)
  4849.         printf ("*****  POWER_ON_RESET interrupt  *****\n");
  4850.       if (interruptsSignaled & TIMER_INTERRUPT)
  4851.         printf ("*****  TIMER_INTERRUPT interrupt  *****\n");
  4852.       if (interruptsSignaled & DISK_INTERRUPT)
  4853.         printf ("*****  DISK_INTERRUPT interrupt  *****\n");
  4854.       if (interruptsSignaled & SERIAL_INTERRUPT)
  4855.         printf ("*****  SERIAL_INTERRUPT interrupt  *****\n");
  4856.       if (interruptsSignaled & HARDWARE_FAULT)
  4857.         printf ("*****  HARDWARE_FAULT interrupt  *****\n");
  4858.       if (interruptsSignaled & ILLEGAL_INSTRUCTION)
  4859.         printf ("*****  ILLEGAL_INSTRUCTION interrupt  *****\n");
  4860.       if (interruptsSignaled & ARITHMETIC_EXCEPTION)
  4861.         printf ("*****  ARITHMETIC_EXCEPTION_EXCEPTION interrupt  *****\n");
  4862.       if (interruptsSignaled & ADDRESS_EXCEPTION)
  4863.         printf ("*****  ADDRESS_EXCEPTION interrupt  *****\n");
  4864.       if (interruptsSignaled & PAGE_INVALID_EXCEPTION)
  4865.         printf ("*****  PAGE_INVALID_EXCEPTION interrupt  *****\n");
  4866.       if (interruptsSignaled & PAGE_READONLY_EXCEPTION)
  4867.         printf ("*****  PAGE_READONLY_EXCEPTION interrupt  *****\n");
  4868.       if (interruptsSignaled & PRIVILEGED_INSTRUCTION)
  4869.         printf ("*****  PRIVILEGED_INSTRUCTION interrupt  *****\n");
  4870.       if (interruptsSignaled & ALIGNMENT_EXCEPTION)
  4871.         printf ("*****  ALIGNMENT_EXCEPTION interrupt  *****\n");
  4872.       if (interruptsSignaled & EXCEPTION_DURING_INTERRUPT)
  4873.         printf ("*****  EXCEPTION_DURING_INTERRUPT interrupt  *****\n");
  4874.       if (interruptsSignaled & SYSCALL_TRAP)
  4875.         printf ("*****  SYSCALL_TRAP interrupt  *****\n");
  4876.       printf ("Processing an interrupt and jumping into interrupt vector.\n");
  4877.     }
  4878.  
  4879.     /* Cancel this interrupt. */
  4880.     interruptsSignaled &= ~thisInterrupt;
  4881.  
  4882.     /* Save the old Status Register and change to System Mode, Paging
  4883.        Disabled, and Interrupts Disabled. */
  4884.     oldStatusReg = buildStatusWord ();
  4885.     statusI = 0;   
  4886.     statusS = 1;   
  4887.     statusP = 0;   
  4888.  
  4889.     /* For POWER_ON_RESET and HARDWARE_FAULT, cancel all other interrupts. */
  4890.     if ((thisInterrupt == POWER_ON_RESET) ||
  4891.         (thisInterrupt == HARDWARE_FAULT)) {
  4892.       interruptsSignaled = 0;
  4893.       pageInvalidOffendingAddress = 0;
  4894.       pageReadonlyOffendingAddress = 0;
  4895.       systemTrapNumber = 0;
  4896.  
  4897.     /* For all other interrupts, push exception info onto the stack. */
  4898.     } else {
  4899.  
  4900.       /* Check for any problems that might arise with the stack. */
  4901.       sp = systemRegisters [15];
  4902.       if (!physicalAddressOk (sp-4) || !physicalAddressOk (sp-12)
  4903.                || inMemoryMappedArea (sp-4) || inMemoryMappedArea (sp-12)
  4904.                || !isAligned (sp)) {
  4905.  
  4906.         /* Turn this into an EXCEPTION_DURING_INTERRUPT and cancel all
  4907.            other pending interrupts. */
  4908.         if (wantPrintingInSingleStep) {
  4909.           printf ("*****  An EXCEPTION_DURING_INTERRUPT interrupt has occurred  *****\n");
  4910.         }
  4911.         thisInterrupt = EXCEPTION_DURING_INTERRUPT;
  4912.         interruptsSignaled = 0;
  4913.   
  4914.       } else {
  4915.   
  4916.         /* Push the Exception info word onto the stack. */
  4917.         if (thisInterrupt == SYSCALL_TRAP) {
  4918.           putPhysicalWord (sp-4, systemTrapNumber);
  4919.           systemTrapNumber = 0;
  4920.         } else if (thisInterrupt == PAGE_INVALID_EXCEPTION) {
  4921.           putPhysicalWord (sp-4, pageInvalidOffendingAddress);
  4922.           pageInvalidOffendingAddress = 0;
  4923.         } else if (thisInterrupt == PAGE_READONLY_EXCEPTION) {
  4924.           putPhysicalWord (sp-4, pageReadonlyOffendingAddress);
  4925.           pageReadonlyOffendingAddress = 0;
  4926.         } else {
  4927.           putPhysicalWord (sp-4, 0);
  4928.         }
  4929.         /* Push the status register and the PC onto the stack. */
  4930.         putPhysicalWord (sp-8, oldStatusReg);
  4931.         putPhysicalWord (sp-12, pc);
  4932.         systemRegisters [15] = sp-12;
  4933.       }
  4934.     }
  4935.  
  4936.     /* Next, set the pc to the address in the low-memory interrupt vector. */
  4937.     pc = getVectorNumber (thisInterrupt);
  4938.  
  4939.     /* This is enough work for one machine cycle. */
  4940.     return;
  4941.  
  4942.   }
  4943.  
  4944.   /* Fetch the next instruction. */
  4945.   /*   Call translate with reading=TRUE, wantPrinting=FALSE, doUpdates=TRUE */
  4946.   i = translate (pc, 1, 0, 1);
  4947.   if (translateCausedException) {
  4948.     if (wantPrintingInSingleStep) {
  4949.       printf ("An exception has occurred during instruction fetch!\n");
  4950.     }
  4951.     return;
  4952.   }
  4953.   instr = getPhysicalWord (i);
  4954.  
  4955.   /* Print the instruction. */
  4956.   // printf ("Executing this instruction:\n");
  4957.   // printAboutToExecute ();
  4958.  
  4959.   /* Switch on the op-code. */
  4960.   opcode = (instr >> 24) & 0x000000ff;
  4961.   switch (opcode) {
  4962.  
  4963.     /***  add      Ra,Rb,Rc  ***/
  4964.     case 96:
  4965.       x = getRa (instr);
  4966.       y = getRb (instr);
  4967.       z = x + y;
  4968.       if ((x<0) && (y<0)) {
  4969.         overflow = (z>=0);
  4970.       } else if ((x>0) && (y>0)) {
  4971.         overflow = (z<=0);
  4972.       } else {
  4973.         overflow = 0;
  4974.       }
  4975.       setSR (z, overflow);
  4976.       putRc (instr, z);
  4977.       pc += 4;
  4978.       break;
  4979.  
  4980.     /***  add      Ra,data16,Rc  ***/
  4981.     case 128:
  4982.       x = getRa (instr);
  4983.       y = getData16 (instr);
  4984.       z = x + y;
  4985.       if ((x<0) && (y<0)) {
  4986.         overflow = (z>=0);
  4987.       } else if ((x>0) && (y>0)) {
  4988.         overflow = (z<=0);
  4989.       } else {
  4990.         overflow = 0;
  4991.       }
  4992.       setSR (z, overflow);
  4993.       putRc (instr, z);
  4994.       pc += 4;
  4995.       break;
  4996.  
  4997.     /***  sub      Ra,Rb,Rc  ***/
  4998.     case 97:
  4999.       x = getRa (instr);
  5000.       y = getRb (instr);
  5001.       z = x - y;
  5002.       if ((x>=0) && (y<0)) {
  5003.         overflow = (z<=0);
  5004.       } else if ((x<0) && (y>0)) {
  5005.         overflow = (z>=0);
  5006.       } else {
  5007.         overflow = 0;
  5008.       }
  5009.       setSR (z, overflow);
  5010.       putRc (instr, z);
  5011.       pc += 4;
  5012.       break;
  5013.  
  5014.     /***  sub      Ra,data16,Rc  ***/
  5015.     case 129:
  5016.       x = getRa (instr);
  5017.       y = getData16 (instr);
  5018.       z = x - y;
  5019.       if ((x>=0) && (y<0)) {
  5020.         overflow = (z<=0);
  5021.       } else if ((x<0) && (y>0)) {
  5022.         overflow = (z>=0);
  5023.       } else {
  5024.         overflow = 0;
  5025.       }
  5026.       setSR (z, overflow);
  5027.       putRc (instr, z);
  5028.       pc += 4;
  5029.       break;
  5030.  
  5031.     /***  mul      Ra,Rb,Rc  ***/
  5032.     case 98:
  5033.       x = getRa (instr);
  5034.       y = getRb (instr);
  5035.       d1 = ((double) x) * ((double) y);
  5036.       z = x * y;
  5037.       if (d1 != (double) z) {
  5038.         setSR (z, 1);
  5039.       } else {
  5040.         setSR (z, 0);
  5041.       }
  5042.       putRc (instr, z);
  5043.       pc += 4;
  5044.       break;
  5045.  
  5046.     /***  mul      Ra,data16,Rc  ***/
  5047.     case 130:
  5048.       x = getRa (instr);
  5049.       y = getData16 (instr);
  5050.       d1 = ((double) x) * ((double) y);
  5051.       z = x * y;
  5052.       if (d1 != (double) z) {
  5053.         setSR (z, 1);
  5054.       } else {
  5055.         setSR (z, 0);
  5056.       }
  5057.       putRc (instr, z);
  5058.       pc += 4;
  5059.       break;
  5060.  
  5061.     /***  div      Ra,Rb,Rc  ***/
  5062.     case 99:
  5063.       x = getRa (instr);
  5064.       y = getRb (instr);
  5065.       if (y == 0) {
  5066.         interruptsSignaled |= ARITHMETIC_EXCEPTION;
  5067.         break;
  5068.       }
  5069.       if ((x == MIN) && (y == -1)) {
  5070.         setSR (MIN, 1);
  5071.         putRc (instr, MIN);
  5072.         pc += 4;
  5073.         break;
  5074.       }
  5075.       divide (x, y);
  5076.       setSR (q, 0);
  5077.       putRc (instr, q);
  5078.       pc += 4;
  5079.       break;
  5080.  
  5081.     /***  div      Ra,data16,Rc  ***/
  5082.     case 131:
  5083.       x = getRa (instr);
  5084.       y = getData16 (instr);
  5085.       if (y == 0) {
  5086.         interruptsSignaled |= ARITHMETIC_EXCEPTION;
  5087.         break;
  5088.       }
  5089.       if ((x == MIN) && (y == -1)) {
  5090.         setSR (MIN, 1);
  5091.         putRc (instr, MIN);
  5092.         pc += 4;
  5093.         break;
  5094.       }
  5095.       divide (x, y);
  5096.       setSR (q, 0);
  5097.       putRc (instr, q);
  5098.       pc += 4;
  5099.       break;
  5100.  
  5101.     /***  sll      Ra,Rb,Rc  ***/
  5102.     case 100:
  5103.       x = getRa (instr);
  5104.       y = getRb (instr);
  5105.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5106.       z = x << y;
  5107.       setSR (z, 0);
  5108.       putRc (instr, z);
  5109.       pc += 4;
  5110.       break;
  5111.  
  5112.     /***  sll      Ra,data16,Rc  ***/
  5113.     case 132:
  5114.       x = getRa (instr);
  5115.       y = getData16 (instr);
  5116.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5117.       z = x << y;
  5118.       setSR (z, 0);
  5119.       putRc (instr, z);
  5120.       pc += 4;
  5121.       break;
  5122.  
  5123.     /***  srl      Ra,Rb,Rc  ***/
  5124.     case 101:
  5125.       x = getRa (instr);
  5126.       y = getRb (instr);
  5127.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5128.       z = (signed int) (((unsigned int) x) >> y);
  5129.       setSR (z, 0);
  5130.       putRc (instr, z);
  5131.       pc += 4;
  5132.       break;
  5133.  
  5134.     /***  srl      Ra,data16,Rc  ***/
  5135.     case 133:
  5136.       x = getRa (instr);
  5137.       y = getData16 (instr);
  5138.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5139.       z = (signed int) (((unsigned int) x) >> y);
  5140.       setSR (z, 0);
  5141.       putRc (instr, z);
  5142.       pc += 4;
  5143.       break;
  5144.  
  5145.     /***  sra      Ra,Rb,Rc  ***/
  5146.     case 102:
  5147.       x = getRa (instr);
  5148.       y = getRb (instr);
  5149.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5150.       z = x >> y;
  5151.       setSR (z, 0);
  5152.       putRc (instr, z);
  5153.       pc += 4;
  5154.       break;
  5155.  
  5156.     /***  sra      Ra,data16,Rc  ***/
  5157.     case 134:
  5158.       x = getRa (instr);
  5159.       y = getData16 (instr);
  5160.       y &= 0x0000001f;   /* Shift value must be 0..31 */
  5161.       z = x >> y;
  5162.       setSR (z, 0);
  5163.       putRc (instr, z);
  5164.       pc += 4;
  5165.       break;
  5166.  
  5167.     /***  or       Ra,Rb,Rc  ***/
  5168.     case 103:
  5169.       x = getRa (instr);
  5170.       y = getRb (instr);
  5171.       z = x | y;
  5172.       setSR (z, 0);
  5173.       putRc (instr, z);
  5174.       pc += 4;
  5175.       break;
  5176.  
  5177.     /***  or       Ra,data16,Rc  ***/
  5178.     case 135:
  5179.       x = getRa (instr);
  5180.       y = getData16 (instr);
  5181.       z = x | y;
  5182.       setSR (z, 0);
  5183.       putRc (instr, z);
  5184.       pc += 4;
  5185.       break;
  5186.  
  5187.     /***  and      Ra,Rb,Rc  ***/
  5188.     case 104:
  5189.       x = getRa (instr);
  5190.       y = getRb (instr);
  5191.       z = x & y;
  5192.       setSR (z, 0);
  5193.       putRc (instr, z);
  5194.       pc += 4;
  5195.       break;
  5196.  
  5197.     /***  and      Ra,data16,Rc  ***/
  5198.     case 136:
  5199.       x = getRa (instr);
  5200.       y = getData16 (instr);
  5201.       z = x & y;
  5202.       setSR (z, 0);
  5203.       putRc (instr, z);
  5204.       pc += 4;
  5205.       break;
  5206.  
  5207.     /***  andn     Ra,Rb,Rc  ***/
  5208.     case 105:
  5209.       x = getRa (instr);
  5210.       y = getRb (instr);
  5211.       z = x & ~y;
  5212.       setSR (z, 0);
  5213.       putRc (instr, z);
  5214.       pc += 4;
  5215.       break;
  5216.  
  5217.     /***  andn     Ra,data16,Rc  ***/
  5218.     case 137:
  5219.       x = getRa (instr);
  5220.       y = getData16 (instr);
  5221.       z = x & ~y;
  5222.       setSR (z, 0);
  5223.       putRc (instr, z);
  5224.       pc += 4;
  5225.       break;
  5226.  
  5227.     /***  xor      Ra,Rb,Rc  ***/
  5228.     case 106:
  5229.       x = getRa (instr);
  5230.       y = getRb (instr);
  5231.       z = x ^ y;
  5232.       setSR (z, 0);
  5233.       putRc (instr, z);
  5234.       pc += 4;
  5235.       break;
  5236.  
  5237.     /***  xor      Ra,data16,Rc  ***/
  5238.     case 138:
  5239.       x = getRa (instr);
  5240.       y = getData16 (instr);
  5241.       z = x ^ y;
  5242.       setSR (z, 0);
  5243.       putRc (instr, z);
  5244.       pc += 4;
  5245.       break;
  5246.  
  5247.     /***  rem      Ra,Rb,Rc  ***/
  5248.     case 115:
  5249.       x = getRa (instr);
  5250.       y = getRb (instr);
  5251.       if (y == 0) {
  5252.         interruptsSignaled |= ARITHMETIC_EXCEPTION;
  5253.         break;
  5254.       }
  5255.       if ((x == MIN) && (y == -1)) {
  5256.         setSR (0, 1);
  5257.         putRc (instr, 0);
  5258.         pc += 4;
  5259.         break;
  5260.       }
  5261.       divide (x, y);
  5262.       setSR (r, 0);
  5263.       putRc (instr, r);
  5264.       pc += 4;
  5265.       break;
  5266.  
  5267.     /***  rem      Ra,data16,Rc  ***/
  5268.     case 149:
  5269.       x = getRa (instr);
  5270.       y = getData16 (instr);
  5271.       if (y == 0) {
  5272.         interruptsSignaled |= ARITHMETIC_EXCEPTION;
  5273.         break;
  5274.       }
  5275.       if ((x == MIN) && (y == -1)) {
  5276.         setSR (0, 1);
  5277.         putRc (instr, 0);
  5278.         pc += 4;
  5279.         break;
  5280.       }
  5281.       divide (x, y);
  5282.       setSR (r, 0);
  5283.       putRc (instr, r);
  5284.       pc += 4;
  5285.       break;
  5286.  
  5287.     /***  load     [Ra+Rb],Rc  ***/
  5288.     case 107:
  5289.       x = getRa (instr);
  5290.       y = getRb (instr);
  5291.       z = x + y;
  5292.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5293.       physAddr = translate (z, 1, 0, 1);
  5294.       if (translateCausedException) {
  5295.         break;
  5296.       }
  5297.       putRc (instr, getPhysicalWord (physAddr));
  5298.       pc += 4;
  5299.       break;
  5300.  
  5301.     /***  load     [Ra+data16],Rc  ***/
  5302.     case 139:
  5303.       x = getRa (instr);
  5304.       y = getData16 (instr);
  5305.       z = x + y;
  5306.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5307.       physAddr = translate (z, 1, 0, 1);
  5308.       if (translateCausedException) {
  5309.         break;
  5310.       }
  5311.       putRc (instr, getPhysicalWord (physAddr));
  5312.       pc += 4;
  5313.       break;
  5314.  
  5315.     /***  loadb    [Ra+Rb],Rc  ***/
  5316.     case 108:
  5317.       x = getRa (instr);
  5318.       y = getRb (instr);
  5319.       z = x + y;
  5320.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5321.       physAddr = translate (z&0xfffffffc, 1, 0, 1);
  5322.       if (translateCausedException) {
  5323.         break;
  5324.       }
  5325.       word = getPhysicalWord (physAddr);
  5326.       /* Isolate the byte in the word and shift to lower-order 8 bits. */
  5327.       word = word >> (24 - ((z & 0x00000003) << 3));
  5328.       word &= 0x000000ff;
  5329.       putRc (instr, word);
  5330.       pc += 4;
  5331.       break;
  5332.  
  5333.     /***  loadb    [Ra+data16],Rc  ***/
  5334.     case 140:
  5335.       x = getRa (instr);
  5336.       y = getData16 (instr);
  5337.       z = x + y;
  5338.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5339.       physAddr = translate (z&0xfffffffc, 1, 0, 1);
  5340.       if (translateCausedException) {
  5341.         break;
  5342.       }
  5343.       word = getPhysicalWord (physAddr);
  5344.       /* Isolate the byte in the word and shift to lower-order 8 bits. */
  5345.       word = word >> (24 - ((z & 0x00000003) << 3));
  5346.       word &= 0x000000ff;
  5347.       putRc (instr, word);
  5348.       pc += 4;
  5349.       break;
  5350.  
  5351.     /***  loadv    [Ra+Rb],Rc  ***/
  5352.     case 109:
  5353.       if (!statusS) {
  5354.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5355.         break;
  5356.       }
  5357.       x = getRa (instr);
  5358.       y = getRb (instr);
  5359.       z = x + y;
  5360.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5361.       saveP = statusP;
  5362.       statusP = 1;
  5363.       physAddr = translate (z, 1, 0, 1);
  5364.       statusP = saveP;
  5365.       if (translateCausedException) {
  5366.         break;
  5367.       }
  5368.       putRc (instr, getPhysicalWord (physAddr));
  5369.       pc += 4;
  5370.       break;
  5371.  
  5372.     /***  loadv    [Ra+data16],Rc  ***/
  5373.     case 141:
  5374.       if (!statusS) {
  5375.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5376.         break;
  5377.       }
  5378.       x = getRa (instr);
  5379.       y = getData16 (instr);
  5380.       z = x + y;
  5381.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5382.       saveP = statusP;
  5383.       statusP = 1;
  5384.       physAddr = translate (z, 1, 0, 1);
  5385.       statusP = saveP;
  5386.       if (translateCausedException) {
  5387.         break;
  5388.       }
  5389.       putRc (instr, getPhysicalWord (physAddr));
  5390.       pc += 4;
  5391.       break;
  5392.  
  5393.     /***  loadbv   [Ra+Rb],Rc  ***/
  5394.     case 110:
  5395.       if (!statusS) {
  5396.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5397.         break;
  5398.       }
  5399.       x = getRa (instr);
  5400.       y = getRb (instr);
  5401.       z = x + y;
  5402.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5403.       saveP = statusP;
  5404.       statusP = 1;
  5405.       physAddr = translate (z&0xfffffffc, 1, 0, 1);
  5406.       statusP = saveP;
  5407.       if (translateCausedException) {
  5408.         break;
  5409.       }
  5410.       word = getPhysicalWord (physAddr);
  5411.       /* Isolate the byte in the word and shift to lower-order 8 bits. */
  5412.       word = word >> (24 - ((z & 0x00000003) << 3));
  5413.       word &= 0x000000ff;
  5414.       putRc (instr, word);
  5415.       pc += 4;
  5416.       break;
  5417.  
  5418.     /***  loadbv   [Ra+data16],Rc  ***/
  5419.     case 142:
  5420.       if (!statusS) {
  5421.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5422.         break;
  5423.       }
  5424.       x = getRa (instr);
  5425.       y = getData16 (instr);
  5426.       z = x + y;
  5427.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  5428.       saveP = statusP;
  5429.       statusP = 1;
  5430.       physAddr = translate (z&0xfffffffc, 1, 0, 1);
  5431.       statusP = saveP;
  5432.       if (translateCausedException) {
  5433.         break;
  5434.       }
  5435.       word = getPhysicalWord (physAddr);
  5436.       /* Isolate the byte in the word and shift to lower-order 8 bits. */
  5437.       word = word >> (24 - ((z & 0x00000003) << 3));
  5438.       word &= 0x000000ff;
  5439.       putRc (instr, word);
  5440.       pc += 4;
  5441.       break;
  5442.  
  5443.     /***  store    Rc,[Ra+Rb]  ***/
  5444.     case 111:
  5445.       x = getRa (instr);
  5446.       y = getRb (instr);
  5447.       z = x + y;
  5448.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5449.       physAddr = translate (z, 0, 0, 1);
  5450.       if (translateCausedException) {
  5451.         break;
  5452.       }
  5453.       putPhysicalWord (physAddr, getRc (instr));
  5454.       pc += 4;
  5455.       break;
  5456.  
  5457.     /***  store    Rc,[Ra+data16]  ***/
  5458.     case 143:
  5459.       x = getRa (instr);
  5460.       y = getData16 (instr);
  5461.       z = x + y;
  5462.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5463.       physAddr = translate (z, 0, 0, 1);
  5464.       if (translateCausedException) {
  5465.         break;
  5466.       }
  5467.       putPhysicalWord (physAddr, getRc (instr));
  5468.       pc += 4;
  5469.       break;
  5470.  
  5471.     /***  storeb   Rc,[Ra+Rb]  ***/
  5472.     case 112:
  5473.       x = getRa (instr);
  5474.       y = getRb (instr);
  5475.       z = x + y;
  5476.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5477.       physAddr = translate (z&0xfffffffc, 0, 0, 1);
  5478.       if (translateCausedException) {
  5479.         break;
  5480.       }
  5481.       word = getPhysicalWordAndLock (physAddr);
  5482.       /* Get the low-order byte from register C; then shift it to proper
  5483.          place in the word; then "or" it into the word. */
  5484.       i = getRc (instr);
  5485.       if (z%4 == 0) {
  5486.         word = (word & 0x00ffffff) | ((i & 0x000000ff) << 24);
  5487.       } else if (z%4 == 1) {
  5488.         word = (word & 0xff00ffff) | ((i & 0x000000ff) << 16);
  5489.       } else if (z%4 == 2) {
  5490.         word = (word & 0xffff00ff) | ((i & 0x000000ff) << 8);
  5491.       } else if (z%4 == 3) {
  5492.         word = (word & 0xffffff00) | (i & 0x000000ff);
  5493.       }
  5494.       putPhysicalWordAndRelease (physAddr, word);
  5495.       pc += 4;
  5496.       break;
  5497.  
  5498.     /***  storeb   Rc,[Ra+data16]  ***/
  5499.     case 144:
  5500.       x = getRa (instr);
  5501.       y = getData16 (instr);
  5502.       z = x + y;
  5503.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5504.       physAddr = translate (z&0xfffffffc, 0, 0, 1);
  5505.       if (translateCausedException) {
  5506.         break;
  5507.       }
  5508.       word = getPhysicalWordAndLock (physAddr);
  5509.       /* Get the low-order byte from register C; then shift it to proper
  5510.          place in the word; then "or" it into the word. */
  5511.       i = getRc (instr);
  5512.       if (z%4 == 0) {
  5513.         word = (word & 0x00ffffff) | ((i & 0x000000ff) << 24);
  5514.       } else if (z%4 == 1) {
  5515.         word = (word & 0xff00ffff) | ((i & 0x000000ff) << 16);
  5516.       } else if (z%4 == 2) {
  5517.         word = (word & 0xffff00ff) | ((i & 0x000000ff) << 8);
  5518.       } else if (z%4 == 3) {
  5519.         word = (word & 0xffffff00) | (i & 0x000000ff);
  5520.       }
  5521.       putPhysicalWordAndRelease (physAddr, word);
  5522.       pc += 4;
  5523.       break;
  5524.  
  5525.     /***  storev   Rc,[Ra+Rb]  ***/
  5526.     case 113:
  5527.       if (!statusS) {
  5528.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5529.         break;
  5530.       }
  5531.       x = getRa (instr);
  5532.       y = getRb (instr);
  5533.       z = x + y;
  5534.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5535.       saveP = statusP;
  5536.       statusP = 1;
  5537.       physAddr = translate (z, 0, 0, 1);
  5538.       statusP = saveP;
  5539.       if (translateCausedException) {
  5540.         break;
  5541.       }
  5542.       putPhysicalWord (physAddr, getRc (instr));
  5543.       pc += 4;
  5544.       pc += 4;
  5545.       break;
  5546.  
  5547.     /***  storev   Rc,[Ra+data16]  ***/
  5548.     case 145:
  5549.       if (!statusS) {
  5550.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5551.         break;
  5552.       }
  5553.       x = getRa (instr);
  5554.       y = getData16 (instr);
  5555.       z = x + y;
  5556.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5557.       saveP = statusP;
  5558.       statusP = 1;
  5559.       physAddr = translate (z, 0, 0, 1);
  5560.       statusP = saveP;
  5561.       if (translateCausedException) {
  5562.         break;
  5563.       }
  5564.       putPhysicalWord (physAddr, getRc (instr));
  5565.       pc += 4;
  5566.       break;
  5567.  
  5568.     /***  storebv  Rc,[Ra+Rb]  ***/
  5569.     case 114:
  5570.       if (!statusS) {
  5571.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5572.         break;
  5573.       }
  5574.       x = getRa (instr);
  5575.       y = getRb (instr);
  5576.       z = x + y;
  5577.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5578.       saveP = statusP;
  5579.       statusP = 1;
  5580.       physAddr = translate (z&0xfffffffc, 0, 0, 1);
  5581.       statusP = saveP;
  5582.       if (translateCausedException) {
  5583.         break;
  5584.       }
  5585.       word = getPhysicalWordAndLock (physAddr);
  5586.       /* Get the low-order byte from register C; then shift it to proper
  5587.          place in the word; then "or" it into the word. */
  5588.       i = getRc (instr);
  5589.       if (z%4 == 0) {
  5590.         word = (word & 0x00ffffff) | ((i & 0x000000ff) << 24);
  5591.       } else if (z%4 == 1) {
  5592.         word = (word & 0xff00ffff) | ((i & 0x000000ff) << 16);
  5593.       } else if (z%4 == 2) {
  5594.         word = (word & 0xffff00ff) | ((i & 0x000000ff) << 8);
  5595.       } else if (z%4 == 3) {
  5596.         word = (word & 0xffffff00) | (i & 0x000000ff);
  5597.       }
  5598.       putPhysicalWordAndRelease (physAddr, word);
  5599.       pc += 4;
  5600.       break;
  5601.  
  5602.     /***  storebv  Rc,[Ra+data16]  ***/
  5603.     case 146:
  5604.       if (!statusS) {
  5605.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5606.         break;
  5607.       }
  5608.       x = getRa (instr);
  5609.       y = getData16 (instr);
  5610.       z = x + y;
  5611.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  5612.       saveP = statusP;
  5613.       statusP = 1;
  5614.       physAddr = translate (z&0xfffffffc, 0, 0, 1);
  5615.       statusP = saveP;
  5616.       if (translateCausedException) {
  5617.         break;
  5618.       }
  5619.       word = getPhysicalWordAndLock (physAddr);
  5620.       /* Get the low-order byte from register C; then shift it to proper
  5621.          place in the word; then "or" it into the word. */
  5622.       i = getRc (instr);
  5623.       if (z%4 == 0) {
  5624.         word = (word & 0x00ffffff) | ((i & 0x000000ff) << 24);
  5625.       } else if (z%4 == 1) {
  5626.         word = (word & 0xff00ffff) | ((i & 0x000000ff) << 16);
  5627.       } else if (z%4 == 2) {
  5628.         word = (word & 0xffff00ff) | ((i & 0x000000ff) << 8);
  5629.       } else if (z%4 == 3) {
  5630.         word = (word & 0xffffff00) | (i & 0x000000ff);
  5631.       }
  5632.       putPhysicalWordAndRelease (physAddr, word);
  5633.       pc += 4;
  5634.       break;
  5635.  
  5636.     /***  call     Ra+Rc  ***/
  5637.     case 64:
  5638.       x = getRa (instr);
  5639.       y = getRc (instr);
  5640.       z = x + y;
  5641.       if (z % 4 != 0) {
  5642.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  5643.         break;
  5644.       }
  5645.       pushOntoStack (15, pc+4);
  5646.       if (translateCausedException) {
  5647.         break;
  5648.       }
  5649.       pc = z;
  5650.       break;
  5651.  
  5652.     /***  call     data24  ***/
  5653.     case 160:
  5654.       z = getData24 (instr);
  5655.       if (z % 4 != 0) {
  5656.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  5657.         break; 
  5658.       }
  5659.       pushOntoStack (15, pc+4);
  5660.       if (translateCausedException) {
  5661.         break;
  5662.       }
  5663.       pc += z;
  5664.       break;
  5665.  
  5666.     /***  jmp      Ra+Rc  ***/
  5667.     case 65:
  5668.       x = getRa (instr);
  5669.       y = getRc (instr);
  5670.       z = x + y;
  5671.       if (z % 4 != 0) {
  5672.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  5673.         break;
  5674.       }
  5675.       pc = z;
  5676.       break;
  5677.  
  5678.     /***  jmp      data24  ***/
  5679.     case 161:
  5680.       z = getData24 (instr);
  5681.       if (z % 4 != 0) {
  5682.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  5683.         break;
  5684.       }
  5685.       pc += z;
  5686.       break;
  5687.  
  5688.     /***  be       Ra+Rc  ***/
  5689.     case 66:
  5690.       jumpIfTrueRaRb (statusZ, instr);
  5691.       break;
  5692.  
  5693.     /***  be       data24  ***/
  5694.     case 162:
  5695.       jumpIfTrueData24 (statusZ, instr);
  5696.       break;
  5697.  
  5698.     /***  bne      Ra+Rc  ***/
  5699.     case 67:
  5700.       jumpIfTrueRaRb (!statusZ, instr);
  5701.       break;
  5702.  
  5703.     /***  bne      data24  ***/
  5704.     case 163:
  5705.       jumpIfTrueData24 (!statusZ, instr);
  5706.       break;
  5707.  
  5708.     /***  bl       Ra+Rc  ***/
  5709.     case 68:
  5710.       jumpIfTrueRaRb ((statusN ^ statusV), instr);
  5711.       break;
  5712.  
  5713.     /***  bl       data24  ***/
  5714.     case 164:
  5715.       jumpIfTrueData24 ((statusN ^ statusV), instr);
  5716.       break;
  5717.  
  5718.     /***  ble      Ra+Rc  ***/
  5719.     case 69:
  5720.       jumpIfTrueRaRb ((statusZ | (statusN ^ statusV)), instr);
  5721.       break;
  5722.  
  5723.     /***  ble      data24  ***/
  5724.     case 165:
  5725.       jumpIfTrueData24 ((statusZ | (statusN ^ statusV)), instr);
  5726.       break;
  5727.  
  5728.     /***  bg       Ra+Rc  ***/
  5729.     case 70:
  5730.       jumpIfTrueRaRb (!(statusZ | (statusN ^ statusV)), instr);
  5731.       break;
  5732.  
  5733.     /***  bg       data24  ***/
  5734.     case 166:
  5735.       jumpIfTrueData24 (!(statusZ | (statusN ^ statusV)), instr);
  5736.       break;
  5737.  
  5738.     /***  bge      Ra+Rc  ***/
  5739.     case 71:
  5740.       jumpIfTrueRaRb (!(statusN ^ statusV), instr);
  5741.       break;
  5742.  
  5743.     /***  bge      data24  ***/
  5744.     case 167:
  5745.       jumpIfTrueData24 (!(statusN ^ statusV), instr);
  5746.       break;
  5747.  
  5748. /***
  5749.     case 72:
  5750.     case 73:
  5751.     case 168:
  5752.     case 169:
  5753. ***/
  5754.  
  5755.     /***  bvs      Ra+Rc  ***/
  5756.     case 74:
  5757.       jumpIfTrueRaRb (statusV, instr);
  5758.       break;
  5759.  
  5760.     /***  bvs      data24  ***/
  5761.     case 170:
  5762.       jumpIfTrueData24 (statusV, instr);
  5763.       break;
  5764.  
  5765.     /***  bvc      Ra+Rc  ***/
  5766.     case 75:
  5767.       jumpIfTrueRaRb (!statusV, instr);
  5768.       break;
  5769.  
  5770.     /***  bvc      data24  ***/
  5771.     case 171:
  5772.       jumpIfTrueData24 (!statusV, instr);
  5773.       break;
  5774.  
  5775.     /***  bns      Ra+Rc  ***/
  5776.     case 76:
  5777.       jumpIfTrueRaRb (statusN, instr);
  5778.       break;
  5779.  
  5780.     /***  bns      data24  ***/
  5781.     case 172:
  5782.       jumpIfTrueData24 (statusN, instr);
  5783.       break;
  5784.  
  5785.     /***  bnc      Ra+Rc  ***/
  5786.     case 77:
  5787.       jumpIfTrueRaRb (!statusN, instr);
  5788.       break;
  5789.  
  5790.     /***  bnc      data24  ***/
  5791.     case 173:
  5792.       jumpIfTrueData24 (!statusN, instr);
  5793.       break;
  5794.  
  5795.     /***  bss      Ra+Rc  ***/
  5796.     case 78:
  5797.       jumpIfTrueRaRb (statusS, instr);
  5798.       break;
  5799.  
  5800.     /***  bss      data24  ***/
  5801.     case 174:
  5802.       jumpIfTrueData24 (statusS, instr);
  5803.       break;
  5804.  
  5805.     /***  bsc      Ra+Rc  ***/
  5806.     case 79:
  5807.       jumpIfTrueRaRb (!statusS, instr);
  5808.       break;
  5809.  
  5810.     /***  bsc      data24  ***/
  5811.     case 175:
  5812.       jumpIfTrueData24 (!statusS, instr);
  5813.       break;
  5814.  
  5815.     /***  bis      Ra+Rc  ***/
  5816.     case 80:
  5817.       jumpIfTrueRaRb (statusI, instr);
  5818.       break;
  5819.  
  5820.     /***  bis      data24  ***/
  5821.     case 176:
  5822.       jumpIfTrueData24 (statusI, instr);
  5823.       break;
  5824.  
  5825.     /***  bic      Ra+Rc  ***/
  5826.     case 81:
  5827.       jumpIfTrueRaRb (!statusI, instr);
  5828.       break;
  5829.  
  5830.     /***  bic      data24  ***/
  5831.     case 177:
  5832.       jumpIfTrueData24 (!statusI, instr);
  5833.       break;
  5834.  
  5835.     /***  bps      Ra+Rc  ***/
  5836.     case 82:
  5837.       jumpIfTrueRaRb (statusP, instr);
  5838.       break;
  5839.  
  5840.     /***  bps      data24  ***/
  5841.     case 178:
  5842.       jumpIfTrueData24 (statusP, instr);
  5843.       break;
  5844.  
  5845.     /***  bpc      Ra+Rc  ***/
  5846.     case 83:
  5847.       jumpIfTrueRaRb (!statusP, instr);
  5848.       break;
  5849.  
  5850.     /***  bpc      data24  ***/
  5851.     case 179:
  5852.       jumpIfTrueData24 (!statusP, instr);
  5853.       break;
  5854.  
  5855.     /***  push     Rc,[--Ra]  ***/
  5856.     case 84:
  5857.       regNumber = (instr >> 16) & 0x0000000f;
  5858.       z = getRc (instr);
  5859.       pushOntoStack (regNumber, z);
  5860.       if (translateCausedException) {
  5861.         break;
  5862.       }
  5863.       pc += 4;
  5864.       break;
  5865.  
  5866.     /***  pop      [Ra++],Rc  ***/
  5867.     case 85:
  5868.       regNumber = (instr >> 16) & 0x0000000f;
  5869.       z = popFromStack (regNumber);
  5870.       if (translateCausedException) {
  5871.         break;
  5872.       }
  5873.       putRc (instr, z);
  5874.       pc += 4;
  5875.       break;
  5876.  
  5877.     /***  sethi    data16,Rc  ***/
  5878.     case 192:
  5879.       z = getData16 (instr);
  5880.       regNumber = (instr >> 20) & 0x0000000f;
  5881.       if (regNumber != 0) {
  5882.         if (statusS) {
  5883.           systemRegisters [regNumber] =
  5884.                (systemRegisters [regNumber] & 0x0000ffff) | (z << 16);
  5885.         } else {
  5886.           userRegisters [regNumber] =
  5887.                (userRegisters [regNumber] & 0x0000ffff) | (z << 16);
  5888.         }
  5889.       }
  5890.       pc += 4;
  5891.       break;
  5892.  
  5893.     /***  setlo    data16,Rc  ***/
  5894.     case 193:
  5895.       z = getData16 (instr);
  5896.       regNumber = (instr >> 20) & 0x0000000f;
  5897.       if (regNumber != 0) {
  5898.         if (statusS) {
  5899.           systemRegisters [regNumber] =
  5900.                (systemRegisters [regNumber] & 0xffff0000) | (z & 0x0000ffff);
  5901.         } else {
  5902.           userRegisters [regNumber] =
  5903.                (userRegisters [regNumber] & 0xffff0000) | (z & 0x0000ffff);
  5904.         }
  5905.       }
  5906.       pc += 4;
  5907.       break;
  5908.  
  5909.     /***  ldaddr   data16,Rc  ***/
  5910.     case 194:
  5911.       x = getData16 (instr);
  5912.       y = pc + x;
  5913.       putRc (instr, y);
  5914.       pc += 4;
  5915.       break;
  5916.  
  5917.     /***  syscall  Rc+data16  ***/
  5918.     case 195:
  5919.       x = getRc (instr);
  5920.       y = getData16 (instr);
  5921.       interruptsSignaled |= SYSCALL_TRAP;
  5922.       systemTrapNumber = x+y;
  5923.       pc += 4;
  5924.       break;
  5925.  
  5926.     /***  nop  ***/
  5927.     case 0:
  5928.       printf ("WARNING: Executing a NOP instruction at address 0x%08X - Suspending execution!\r\n", pc);
  5929.       controlCPressed = 1;
  5930.       pc += 4;
  5931.       break;
  5932.  
  5933.     /***  wait  ***/
  5934.     case 1:
  5935.  
  5936.       // printf ("h");
  5937.       if (!statusS) {
  5938.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  5939.         break;
  5940.       }
  5941.  
  5942.       /* Enable interrupts. */
  5943.       statusI = 1;
  5944.  
  5945.       /* Compute the time of the next event; we will ignore timer events... */
  5946.       i = timeOfNextDiskEvent;
  5947.  
  5948.       if (timeOfNextSerialOutEvent < i) {
  5949.         i = timeOfNextSerialOutEvent;
  5950.       }
  5951.  
  5952.       /* If there is something in the type-ahead buffer... */
  5953.       if (typeAheadBufferCount > 0) {
  5954.         doSerialInEvent (1);
  5955.         if (timeOfNextSerialInEvent < i) {
  5956.           i = timeOfNextSerialInEvent;
  5957.         }
  5958.  
  5959.       /* Else, if serial input comes from a file... */
  5960.       } else if (termInputFile != stdin) {
  5961.         /* Then get more input from the file, if any... */
  5962.         if (! feof (termInputFile)) {
  5963.           doSerialInEvent (1);
  5964.           if (timeOfNextSerialInEvent < i) {
  5965.             i = timeOfNextSerialInEvent;
  5966.           }
  5967.         }
  5968.  
  5969.       /* Else input comes from stdin... */
  5970.       } else {
  5971.         /* See if there is a character available on the input... */
  5972.         doSerialInEvent (0);
  5973.         if (termInCharAvail && timeOfNextSerialInEvent < i) {
  5974.           i = timeOfNextSerialInEvent;
  5975.         }
  5976.       }
  5977.  
  5978.       /* If we still haven't found anything to do
  5979.          and there are no pending interrupts
  5980.          and input is coming from the terminal
  5981.          and the user has asked us to wait instead of terminate...  */
  5982.       if ((i == MAX) &&
  5983.           (getNextInterrupt () == 0) &&
  5984.           (termInputFile == stdin) &&
  5985.           (commandOptionWait)) {
  5986.  
  5987.         /* We are about to wait on user input.  Print a message so the
  5988.            user will know we are waiting (unless we're in raw mode)...  */
  5989.         if (! terminalWantRawProcessing) {
  5990.           fprintf (stderr, "\n\r*****  Execution suspended on 'wait' instruction; waiting for additional user input  *****\n\r");
  5991.         }
  5992.  
  5993.         /* Wait for some input from stdin... */
  5994.         doSerialInEvent (1);
  5995.         if (timeOfNextSerialInEvent < i) {
  5996.           i = timeOfNextSerialInEvent;
  5997.         }
  5998.       }
  5999.  
  6000.       /* If we now have an interrupt that will be processed on the next cycle... */
  6001.       if (getNextInterrupt ()) {
  6002.         /* Do nothing thing; continue execution */
  6003.  
  6004.       /* Else if we have a disk or serial event in the future... */
  6005.       } else if (i != MAX) {
  6006.  
  6007.         /* Move currentTime up to the time of the next event. */
  6008.         timeSpentAsleep += (timeOfNextEvent-1) - currentTime;
  6009.         currentTime = timeOfNextEvent-1;
  6010.  
  6011.       /* Else halt execution. */
  6012.       } else {
  6013.      
  6014.         fprintf (stderr, "\n\r*****  A 'wait' instruction was executed and no more interrupts are scheduled... halting emulation!  *****\n\r\n\r");
  6015.         executionHalted = 1;
  6016.       }
  6017.  
  6018.       /* Increment PC; executing go after a wait will resume execution. */
  6019.       pc += 4;
  6020.       break;
  6021.  
  6022.     /***  debug  ***/
  6023.     case 2:
  6024.       /* Stop instruction emulation and print a message.  Advance the
  6025.          PC so that we can easily resume execution. */
  6026.       controlCPressed = 1;
  6027.       turnOffTerminal ();
  6028.       fprintf (stderr, "\n\r****  A 'debug' instruction was encountered  *****\n\r");
  6029.       turnOnTerminal ();
  6030.       pc += 4;
  6031.       break;
  6032.  
  6033.     /***  debug2  ***/
  6034.     case 10:
  6035.       /* Perform a special function.  The function code is in r1. */
  6036.       if (statusS) {
  6037.         x = systemRegisters [1];
  6038.       } else {
  6039.         x = userRegisters [1];
  6040.       }
  6041.       /* Get the value of register r2 (string ptr, integer, or boolean). */
  6042.       if (statusS) {
  6043.         y = systemRegisters [2];
  6044.       } else {
  6045.         y = userRegisters [2];
  6046.       }
  6047.  
  6048.       /* Function = "printInt" */
  6049.       if (x == 1) {
  6050.         printf ("%d", y);
  6051.  
  6052.       /* Function = "printString" */
  6053.       } else if (x == 2) {
  6054.         /* z = string length */
  6055.         if (statusS) {
  6056.           z = systemRegisters [3];
  6057.         } else {
  6058.           z = userRegisters [3];
  6059.         }
  6060.         if ((z < 0) | (z > 100000)) {
  6061.           controlCPressed = 1;
  6062.           fprintf (stderr, "\n\r****  An error occurred during a 'debug2' instruction - invalid string length in print  *****\n\r");
  6063.           z = -1;
  6064.         }
  6065.         while (z > 0) {
  6066.           z--;
  6067.           /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6068.           physAddr = translate (y&0xfffffffc, 1, 0, 1);
  6069.           if (translateCausedException) {
  6070.             controlCPressed = 1;
  6071.             fprintf (stderr, "\n\r****  An error occurred during a 'debug2' instruction - address exception in print  *****\n\r");
  6072.             break;
  6073.           }
  6074.           word = getPhysicalWord (physAddr);
  6075.           /* Isolate the byte in the word and shift to lower-order 8 bits. */
  6076.           word = word >> (24 - ((y & 0x00000003) << 3));
  6077.           x = word & 0x000000ff;
  6078.           if ((x >= 32) && (x < 127)) {
  6079.             printf ("%c", x);
  6080.           } else if (x == '\t') {
  6081.             printf ("\t");
  6082.           } else if (x == '\n') {
  6083.             printf ("\r\n");
  6084.           } else {
  6085.             printf ("\\x%02X", x);
  6086.           }
  6087.           y++;
  6088.         }
  6089.  
  6090.       /* Function = "printChar" */
  6091.       } else if (x == 3) {
  6092.         if ((y >= 32) && (y < 127)) {
  6093.           printf ("%c", y);
  6094.         } else if (y == '\t') {
  6095.           printf ("\t");
  6096.         } else if (y == '\n') {
  6097.           printf ("\r\n");
  6098.         } else {
  6099.           printf ("\\x%02X", y);
  6100.         }
  6101.  
  6102.       /* Function = "printDouble" */
  6103.       } else if (x == 4) {
  6104.         printDoubleVal (floatRegisters[0]);
  6105.  
  6106.       /* Function = "printBool" */
  6107.       } else if (x == 5) {
  6108.         if (y == 0) {
  6109.           printf ("FALSE");
  6110.         } else if (y == 1) {
  6111.           printf ("TRUE");
  6112.         } else {
  6113.           controlCPressed = 1;
  6114.           fprintf (stderr, "\n\r****  An error occurred during a 'debug2' instruction - invalid boolean value in printBool  *****\n\r");
  6115.         }
  6116.  
  6117.       /* Function = "printHex" */
  6118.       } else if (x == 6) {
  6119.         printf ("0x");
  6120.         putlong (y);
  6121.  
  6122.       /* Function = ERROR */
  6123.       } else {
  6124.         controlCPressed = 1;
  6125.         fprintf (stderr, "\n\r****  An error occurred during a 'debug2' instruction - invalid function code  *****\n\r");
  6126.       }
  6127.  
  6128.       fflush (stdout);
  6129.       pc += 4;
  6130.       break;
  6131.  
  6132.     /***  cleari  ***/
  6133.     case 3:
  6134.       if (!statusS) {
  6135.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6136.         break;
  6137.       }
  6138.       statusI = 0;
  6139.       pc += 4;
  6140.       break;
  6141.  
  6142.     /***  seti  ***/
  6143.     case 4:
  6144.       if (!statusS) {
  6145.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6146.         break;
  6147.       }
  6148.       statusI = 1;
  6149.       pc += 4;
  6150.       break;
  6151.  
  6152.     /***  clearp  ***/
  6153.     case 5:
  6154.       if (!statusS) {
  6155.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6156.         break;
  6157.       }
  6158.       statusP = 0;
  6159.       pc += 4;
  6160.       break;
  6161.  
  6162.     /***  setp  ***/
  6163.     case 6:
  6164.       if (!statusS) {
  6165.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6166.         break;
  6167.       }
  6168.       statusP = 1;
  6169.       pc += 4;
  6170.       break;
  6171.  
  6172.     /***  clears  ***/
  6173.     case 7:
  6174.       if (!statusS) {
  6175.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6176.         break;
  6177.       }
  6178.       statusS = 0;
  6179.       pc += 4;
  6180.       break;
  6181.  
  6182.     /***  reti  ***/
  6183.     case 8:
  6184.       if (!statusS) {
  6185.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6186.         break;
  6187.       }
  6188.       x = popFromStack (15);
  6189.       if (translateCausedException) {
  6190.         break;
  6191.       }
  6192.       y = popFromStack (15);
  6193.       if (translateCausedException) {
  6194.         break;
  6195.       }
  6196.       z = popFromStack (15);
  6197.       if (translateCausedException) {
  6198.         break;
  6199.       }
  6200.       setStatusFromWord (y);
  6201.       pc = x;
  6202.       break;
  6203.  
  6204.     /***  ret  ***/
  6205.     case 9:
  6206.       z = popFromStack (15);
  6207.       if (translateCausedException) {
  6208.         break;
  6209.       }
  6210.       pc = z;
  6211.       break;
  6212.  
  6213.     /***  tset     [Ra],Rc  ***/
  6214.     case 88:
  6215.       x = getRa (instr);
  6216.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6217.       physAddr = translate (x, 0, 0, 1);
  6218.       if (translateCausedException) {
  6219.         break;
  6220.       }
  6221.       putRc (instr, getPhysicalWordAndLock (physAddr));
  6222.       putPhysicalWordAndRelease (physAddr, 0x00000001);
  6223.       pc += 4;
  6224.       break;
  6225.  
  6226.     /***  readu    Rc,Ra  ***/
  6227.     case 86:
  6228.       if (!statusS) {
  6229.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6230.         break;
  6231.       }
  6232.       regC = (instr >> 20) & 0x0000000f;
  6233.       regA = (instr >> 16) & 0x0000000f;
  6234.       pc += 4;
  6235.       if (regA == 0) break;
  6236.       systemRegisters [regA] = userRegisters [regC];
  6237.       break;
  6238.  
  6239.     /***  readu    Rc,[Ra+data16]  ***/
  6240.     case 147:
  6241.       if (!statusS) {
  6242.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6243.         break;
  6244.       }
  6245.       x = getRa (instr);
  6246.       y = getData16 (instr);
  6247.       z = x + y;
  6248.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6249.       physAddr = translate (z, 0, 0, 1);
  6250.       if (translateCausedException) {
  6251.         break;
  6252.       }
  6253.       regC = (instr >> 20) & 0x0000000f;
  6254.       putPhysicalWord (physAddr, userRegisters [regC]);
  6255.       pc += 4;
  6256.       break;
  6257.  
  6258.     /***  writeu   Ra,Rc  ***/
  6259.     case 87:
  6260.       if (!statusS) {
  6261.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6262.         break;
  6263.       }
  6264.       regC = (instr >> 20) & 0x0000000f;
  6265.       regA = (instr >> 16) & 0x0000000f;
  6266.       pc += 4;
  6267.       if (regC == 0) break;
  6268.       userRegisters [regC] = systemRegisters [regA];
  6269.       break;
  6270.  
  6271.     /***  writeu   [Ra+data16],Rc  ***/
  6272.     case 148:
  6273.       if (!statusS) {
  6274.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6275.         break;
  6276.       }
  6277.       x = getRa (instr);
  6278.       y = getData16 (instr);
  6279.       z = x + y;
  6280.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6281.       physAddr = translate (z, 1, 0, 1);
  6282.       if (translateCausedException) {
  6283.         break;
  6284.       }
  6285.       regC = (instr >> 20) & 0x0000000f;
  6286.       pc += 4;
  6287.       if (regC == 0) break;
  6288.       userRegisters [regC] = getPhysicalWord (physAddr);
  6289.       break;
  6290.  
  6291.     /***  ldptbr   Rc  ***/
  6292.     case 32:
  6293.       if (!statusS) {
  6294.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6295.         break;
  6296.       }
  6297.       x = getRc (instr);
  6298.       if (x % 4 != 0) {
  6299.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  6300.         break;
  6301.       }
  6302.       ptbr = x;
  6303.       pc += 4;
  6304.       break;
  6305.  
  6306.     /***  ldptlr   Rc  ***/
  6307.     case 33:
  6308.       if (!statusS) {
  6309.         interruptsSignaled |= PRIVILEGED_INSTRUCTION;
  6310.         break;
  6311.       }
  6312.       x = getRc (instr);
  6313.       if (x % 4 != 0) {
  6314.         interruptsSignaled |= ALIGNMENT_EXCEPTION;
  6315.         break;
  6316.       }
  6317.       ptlr = x;
  6318.       pc += 4;
  6319.       break;
  6320.  
  6321.     /***  ftoi      FRa,Rc  ***/
  6322.     case 89:
  6323.       d1 = getFRa (instr);
  6324.       i = d1;
  6325.       putRc (instr, i);
  6326.       pc += 4;
  6327.       break;
  6328.  
  6329.     /***  itof      Ra,FRc  ***/
  6330.     case 90:
  6331.       i = getRa (instr);
  6332.       d1 = i;
  6333.       putFRc (instr, d1);
  6334.       pc += 4;
  6335.       break;
  6336.  
  6337.     /***  fadd      FRa,FRb,FRc  ***/
  6338.     case 116:
  6339.       d1 = getFRa (instr);
  6340.       d2 = getFRb (instr);
  6341.       d3 = d1 + d2;
  6342.       putFRc (instr, d3);
  6343.       pc += 4;
  6344.       break;
  6345.  
  6346.     /***  fsub      FRa,FRb,FRc  ***/
  6347.     case 117:
  6348.       d1 = getFRa (instr);
  6349.       d2 = getFRb (instr);
  6350.       d3 = d1 - d2;
  6351.       putFRc (instr, d3);
  6352.       pc += 4;
  6353.       break;
  6354.  
  6355.     /***  fmul      FRa,FRb,FRc  ***/
  6356.     case 118:
  6357.       d1 = getFRa (instr);
  6358.       d2 = getFRb (instr);
  6359.       d3 = d1 * d2;
  6360.       putFRc (instr, d3);
  6361.       pc += 4;
  6362.       break;
  6363.  
  6364.     /***  fdiv      FRa,FRb,FRc  ***/
  6365.     case 119:
  6366.       d1 = getFRa (instr);
  6367.       d2 = getFRb (instr);
  6368.       d3 = d1 / d2;
  6369.       putFRc (instr, d3);
  6370.       pc += 4;
  6371.       break;
  6372.  
  6373.     /***  fcmp      FRa,FRc  ***/
  6374.     case 91:
  6375.       d1 = getFRa (instr);
  6376.       d2 = getFRc (instr);
  6377.       statusZ = statusN = statusV = 0;
  6378.       if (d1 == d2) {
  6379.         statusZ = 1;
  6380.       }
  6381.       if (d1 < d2) {
  6382.         statusN = 1;
  6383.       }
  6384.       if (isnan(d1)) {
  6385.         statusV = 1;
  6386.       }
  6387.       if (isnan(d2)) {
  6388.         statusV = 1;
  6389.       }
  6390.       pc += 4;
  6391.       break;
  6392.  
  6393.     /***  fsqrt      FRa,FRc  ***/
  6394.     case 92:
  6395.       d1 = getFRa (instr);
  6396.       d3 = sqrt (d1);
  6397.       putFRc (instr, d3);
  6398.       pc += 4;
  6399.       break;
  6400.  
  6401.     /***  fneg      FRa,FRc  ***/
  6402.     case 93:
  6403.       d1 = getFRa (instr);
  6404.       d3 = -d1;
  6405.       putFRc (instr, d3);
  6406.       pc += 4;
  6407.       break;
  6408.  
  6409.     /***  fabs      FRa,FRc  ***/
  6410.     case 94:
  6411.       d1 = getFRa (instr);
  6412.       d3 = fabs (d1);
  6413.       putFRc (instr, d3);
  6414.       pc += 4;
  6415.       break;
  6416.  
  6417.     /***  fload      [Ra+Rb],FRc  ***/
  6418.     case 120:
  6419.       x = getRa (instr);
  6420.       y = getRb (instr);
  6421.       z = x + y;
  6422.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6423.       physAddr = translate (z, 1, 0, 1);
  6424.       if (translateCausedException) {
  6425.         break;
  6426.       }
  6427.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6428.       physAddr2 = translate (z+4, 1, 0, 1);
  6429.       if (translateCausedException) {
  6430.         break;
  6431.       }
  6432.       p = (int *) (& d3);
  6433.       *p = getPhysicalWord (physAddr);
  6434.       *(p+1) = getPhysicalWord (physAddr2);
  6435.       putFRc (instr, d3);
  6436.       pc += 4;
  6437.       break;
  6438.  
  6439.     /***  fload      [Ra+data16],FRc  ***/
  6440.     case 150:
  6441.       x = getRa (instr);
  6442.       y = getData16 (instr);
  6443.       z = x + y;
  6444.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6445.       physAddr = translate (z, 1, 0, 1);
  6446.       if (translateCausedException) {
  6447.         break;
  6448.       }
  6449.       /* Call translate with reading=true, wantPrinting=0, doUpdates=1 */
  6450.       physAddr2 = translate (z+4, 1, 0, 1);
  6451.       if (translateCausedException) {
  6452.         break;
  6453.       }
  6454.       p = (int *) (& d3);
  6455.       *p = getPhysicalWord (physAddr);
  6456.       *(p+1) = getPhysicalWord (physAddr2);
  6457.       putFRc (instr, d3);
  6458.       pc += 4;
  6459.       break;
  6460.  
  6461.     /***  fstore      FRc,[Ra+Rb]  ***/
  6462.     case 121:
  6463.       x = getRa (instr);
  6464.       y = getRb (instr);
  6465.       z = x + y;
  6466.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6467.       physAddr = translate (z, 0, 0, 1);
  6468.       if (translateCausedException) {
  6469.         break;
  6470.       }
  6471.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6472.       physAddr2 = translate (z+4, 0, 0, 1);
  6473.       if (translateCausedException) {
  6474.         break;
  6475.       }
  6476.       p = (int *) (& d3);
  6477.       d3 = getFRc (instr);
  6478.       putPhysicalWord (physAddr, *p);
  6479.       putPhysicalWord (physAddr2, *(p+1));
  6480.       pc += 4;
  6481.       break;
  6482.  
  6483.     /***  fstore      FRc,[Ra+data16]  ***/
  6484.     case 151:
  6485.       x = getRa (instr);
  6486.       y = getData16 (instr);
  6487.       z = x + y;
  6488.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6489.       physAddr = translate (z, 0, 0, 1);
  6490.       if (translateCausedException) {
  6491.         break;
  6492.       }
  6493.       /* Call translate with reading=false, wantPrinting=0, doUpdates=1 */
  6494.       physAddr2 = translate (z+4, 0, 0, 1);
  6495.       if (translateCausedException) {
  6496.         break;
  6497.       }
  6498.       p = (int *) (& d3);
  6499.       d3 = getFRc (instr);
  6500.       putPhysicalWord (physAddr, *p);
  6501.       putPhysicalWord (physAddr2, *(p+1));
  6502.       pc += 4;
  6503.       break;
  6504.  
  6505.     /***  illegal instruction  ***/
  6506.     default:
  6507.       interruptsSignaled |= ILLEGAL_INSTRUCTION;
  6508.       break;
  6509.   }
  6510. }
  6511.  
  6512.  
  6513.  
  6514. /* getRa (instr)
  6515. ** getRb (instr)
  6516. ** getRc (instr)
  6517. ** putRc (instr, value)
  6518. ** getData16 (instr)
  6519. ** getData24 (instr)
  6520. **
  6521. ** These routine get the value of (put a value to) the indicated register.
  6522. ** The current SystemMode bit will be checked and the data will be
  6523. ** moved from/to either the System or User registers as appropriate.
  6524. ** The "getData16" and "getData24" routines return the literal values
  6525. ** from the instruction after sign-extending the value to 32 bits.
  6526. */
  6527. int getRa (int instr) {
  6528.   int reg = (instr >> 16) & 0x0000000f;
  6529.   if (statusS) {
  6530.     return systemRegisters [reg];
  6531.   } else {
  6532.     return userRegisters [reg];
  6533.   }
  6534. }
  6535.  
  6536. int getRb (int instr) {
  6537.   int reg = (instr >> 12) & 0x0000000f;
  6538.   if (statusS) {
  6539.     return systemRegisters [reg];
  6540.   } else {
  6541.     return userRegisters [reg];
  6542.   }
  6543. }
  6544.  
  6545. int getRc (int instr) {
  6546.   int reg = (instr >> 20) & 0x0000000f;
  6547.   if (statusS) {
  6548.     return systemRegisters [reg];
  6549.   } else {
  6550.     return userRegisters [reg];
  6551.   }
  6552. }
  6553.  
  6554. void putRc (int instr, int value) {
  6555.   int reg = (instr >> 20) & 0x0000000f;
  6556.   if (reg == 0) return;
  6557.   if (statusS) {
  6558.     systemRegisters [reg] = value;
  6559.   } else {
  6560.     userRegisters [reg] = value;
  6561.   }
  6562. }
  6563.  
  6564. int getData16 (int instr) {
  6565.   int i = instr << 16;
  6566.   if (i < 0) {
  6567.     return (instr | 0xffff0000);
  6568.   } else {
  6569.     return (instr & 0x0000ffff);
  6570.   }
  6571. }
  6572.  
  6573. int getData24 (int instr) {
  6574.   int i = instr << 8;
  6575.   if (i < 0) {
  6576.     return (instr | 0xff000000);
  6577.   } else {
  6578.     return (instr & 0x00ffffff);
  6579.   }
  6580.   return instr & 0x00ffffff;
  6581. }
  6582.  
  6583.  
  6584.  
  6585. /* getFRa (instr)
  6586. ** getFRb (instr)
  6587. ** getFRc (instr)
  6588. ** putFRc (instr, value)
  6589. **
  6590. ** These routines get the value of (put a value to) the indicated register.
  6591. */
  6592. double getFRa (int instr) {
  6593.   int reg = (instr >> 16) & 0x0000000f;
  6594.   return floatRegisters [reg];
  6595. }
  6596.  
  6597. double getFRb (int instr) {
  6598.   int reg = (instr >> 12) & 0x0000000f;
  6599.   return floatRegisters [reg];
  6600. }
  6601.  
  6602. double getFRc (int instr) {
  6603.   int reg = (instr >> 20) & 0x0000000f;
  6604.   return floatRegisters [reg];
  6605. }
  6606.  
  6607. void putFRc (int instr, double value) {
  6608.   int reg = (instr >> 20) & 0x0000000f;
  6609.   floatRegisters [reg] = value;
  6610. }
  6611.  
  6612.  
  6613.  
  6614. /* buildStatusWord ()
  6615. **
  6616. ** This routine builds and returns a 32-bit word reflecting the status
  6617. ** bits, which are kept in individual variables by this program.
  6618. */
  6619. int buildStatusWord () {
  6620.   int word = 0;
  6621.   if (statusN) {
  6622.     word |= 0x00000001;
  6623.   }
  6624.   if (statusV) {
  6625.     word |= 0x00000002;
  6626.   }
  6627.   if (statusZ) {
  6628.     word |= 0x00000004;
  6629.   }
  6630.   if (statusP) {
  6631.     word |= 0x00000008;
  6632.   }
  6633.   if (statusS) {
  6634.     word |= 0x00000010;
  6635.   }
  6636.   if (statusI) {
  6637.     word |= 0x00000020;
  6638.   }
  6639.   return word;
  6640. }
  6641.  
  6642.  
  6643.  
  6644. /* setStatusFromWord (word)
  6645. **
  6646. ** This routine is passed a 32-bit word reflecting the status register.
  6647. ** It sets the individual status variables used by this program to
  6648. ** record the current status bits.
  6649. */
  6650. void setStatusFromWord (int word) {
  6651.   statusI = 0;
  6652.   statusS = 0;
  6653.   statusP = 0;
  6654.   statusZ = 0;
  6655.   statusV = 0;
  6656.   statusN = 0;
  6657.   if (word & 0x00000020) {
  6658.   }
  6659.   if (word & 0x00000020) {
  6660.     statusI = 1;
  6661.   }
  6662.   if (word & 0x00000010) {
  6663.     statusS = 1;
  6664.   }
  6665.   if (word & 0x00000008) {
  6666.     statusP = 1;
  6667.   }
  6668.   if (word & 0x00000004) {
  6669.     statusZ = 1;
  6670.   }
  6671.   if (word & 0x00000002) {
  6672.     statusV = 1;
  6673.   }
  6674.   if (word & 0x00000001) {
  6675.     statusN = 1;
  6676.   }
  6677.   /* ignore all other bits in the word */
  6678. }
  6679.  
  6680.  
  6681.  
  6682. /* setSR (value, overflow)
  6683. **
  6684. ** This routine sets the Z, V, and N bits of the status word.
  6685. ** The Zero (Z) and Negative (N) bits will be set according to the
  6686. ** "value".  The values of the overflow bit will be passed
  6687. ** in as an argument.
  6688. */
  6689. void setSR (int value, int overflow) {
  6690.   statusZ = (value == 0);
  6691.   statusV = overflow;
  6692.   statusN = (value < 0);
  6693. }
  6694.  
  6695.  
  6696.  
  6697. /* getNextInterrupt ()
  6698. **
  6699. ** This routine returns the type of the interrupt that is being
  6700. ** signalled.  It looks at the "interruptsSignaled" variable and finds
  6701. ** an interrupt to return by finding a bit that is set.  This routine
  6702. ** determines the order in which several simultaneous interrupts are
  6703. ** processed.  The first one returned will be processed first.  However,
  6704. ** on the next instruction cycle, the next interrupt will be chosen and
  6705. ** will be processed.  Thus, the first interrupt will be interrupted on
  6706. ** its first instruction and will not be serviced until all other
  6707. ** interrupts are serviced.
  6708. **
  6709. ** Thus, interrupts are actually processed in the reverse of whatever order
  6710. ** they are returned from this routine.
  6711. **
  6712. ** This routine also checks the "interrupts enabled" bit in the status
  6713. ** register.  If a signalled bit is maskable but interrupts are disabled,
  6714. ** this routine just ignores it.
  6715. **
  6716. ** Note that we return the exceptions and SYSCALL trap first, before TIMER,
  6717. ** DISK, and SERIAL interrupts.  The reason is that these last three exceptions
  6718. ** may perform a context switch.  It would be disastrous to have an exception
  6719. ** in one thread, process a TIMER Interrupt, do a context switch, then service
  6720. ** the exception or SYSCALL trap.  This would attribute the exception or trap
  6721. ** to the incorrect thread.
  6722. */
  6723. int getNextInterrupt () {
  6724.   if (interruptsSignaled & POWER_ON_RESET) {
  6725.     return POWER_ON_RESET;
  6726.   } else if (interruptsSignaled & HARDWARE_FAULT) {
  6727.     return HARDWARE_FAULT;
  6728.   } else if (interruptsSignaled & ILLEGAL_INSTRUCTION) {
  6729.     return ILLEGAL_INSTRUCTION;
  6730.   } else if ((interruptsSignaled & ARITHMETIC_EXCEPTION) && statusI) {
  6731.     return ARITHMETIC_EXCEPTION;
  6732.   } else if (interruptsSignaled & ADDRESS_EXCEPTION) {
  6733.     return ADDRESS_EXCEPTION;
  6734.   } else if (interruptsSignaled & PAGE_INVALID_EXCEPTION) {
  6735.     return PAGE_INVALID_EXCEPTION;
  6736.   } else if (interruptsSignaled & PAGE_READONLY_EXCEPTION) {
  6737.     return PAGE_READONLY_EXCEPTION;
  6738.   } else if (interruptsSignaled & PRIVILEGED_INSTRUCTION) {
  6739.     return PRIVILEGED_INSTRUCTION;
  6740.   } else if (interruptsSignaled & ALIGNMENT_EXCEPTION) {
  6741.     return ALIGNMENT_EXCEPTION;
  6742.   } else if (interruptsSignaled & EXCEPTION_DURING_INTERRUPT) {
  6743.     return EXCEPTION_DURING_INTERRUPT;
  6744.   } else if ((interruptsSignaled & SYSCALL_TRAP) && statusI) {
  6745.     return SYSCALL_TRAP;
  6746.   } else if ((interruptsSignaled & TIMER_INTERRUPT) && statusI) {
  6747.     return TIMER_INTERRUPT;
  6748.   } else if ((interruptsSignaled & DISK_INTERRUPT) && statusI) {
  6749.     return DISK_INTERRUPT;
  6750.   } else if ((interruptsSignaled & SERIAL_INTERRUPT) && statusI) {
  6751.     return SERIAL_INTERRUPT;
  6752.   } else {
  6753.     return 0;
  6754.   }
  6755. }
  6756.  
  6757.  
  6758.  
  6759. /* getVectorNumber (interruptType)
  6760. **
  6761. ** This routine returns the interrupt vector number for the
  6762. ** given interrupt type.
  6763. **
  6764. **     address description                 maskable
  6765. **     ======= =========================== ========
  6766. **      0000   Power On Reset                 No
  6767. **      0004   Timer Interrupt               Yes
  6768. **      0008   Disk Interrupt                Yes
  6769. **      000C   Serial Interrupt              Yes
  6770. **      0010   Hardware Fault                 No
  6771. **      0014   Illegal Instruction            No
  6772. **      0018   Arithmetic Exception          Yes
  6773. **      001C   Address Exception              No
  6774. **      0020   Page Invalid Exception         No
  6775. **      0024   Page Readonly Exception        No
  6776. **      0028   Privileged Instruction         No
  6777. **      002C   Alignment Exception            No
  6778. **      0030   Exception During Interrupt     No
  6779. **      0034   Syscall Trap                  Yes
  6780. */
  6781. int getVectorNumber (int interruptType) {
  6782.   if (interruptType == POWER_ON_RESET) {
  6783.     return 0x00000000;
  6784.   } else if (interruptType == TIMER_INTERRUPT) {
  6785.     return 0x00000004;
  6786.   } else if (interruptType == DISK_INTERRUPT) {
  6787.     return 0x00000008;
  6788.   } else if (interruptType == SERIAL_INTERRUPT) {
  6789.     return 0x0000000C;
  6790.   } else if (interruptType == HARDWARE_FAULT) {
  6791.     return 0x00000010;
  6792.   } else if (interruptType == ILLEGAL_INSTRUCTION) {
  6793.     return 0x00000014;
  6794.   } else if (interruptType == ARITHMETIC_EXCEPTION) {
  6795.     return 0x00000018;
  6796.   } else if (interruptType == ADDRESS_EXCEPTION) {
  6797.     return 0x0000001C;
  6798.   } else if (interruptType == PAGE_INVALID_EXCEPTION) {
  6799.     return 0x00000020;
  6800.   } else if (interruptType == PAGE_READONLY_EXCEPTION) {
  6801.     return 0x00000024;
  6802.   } else if (interruptType == PRIVILEGED_INSTRUCTION) {
  6803.     return 0x00000028;
  6804.   } else if (interruptType == ALIGNMENT_EXCEPTION) {
  6805.     return 0x0000002C;
  6806.   } else if (interruptType == EXCEPTION_DURING_INTERRUPT) {
  6807.     return 0x00000030;
  6808.   } else if (interruptType == SYSCALL_TRAP) {
  6809.     return 0x00000034;
  6810.   } else {
  6811.     fatalError ("PROGRAM LOGIC ERROR: Unknown exception vector");
  6812.   }
  6813. }
  6814.  
  6815.  
  6816.  
  6817.  
  6818.  
  6819. /**************************************************************************
  6820. **
  6821. ** MEMORY SUB-SYSTEM
  6822. **
  6823. ** These routines deal with access to the physical memory of the BLITZ
  6824. ** machine.
  6825. **
  6826. ** We make the distinction between "implementation memory", which is the
  6827. ** memory used by the program you are currently reading (i.e., the memory
  6828. ** addressed by direct "C" pointers, such as the "memory" variable, and
  6829. ** "BLITZ memory", which is the emulated memory.  We make a further
  6830. ** distinction between the "Physical memory", which is the total emulated
  6831. ** memory of the BLITZ machine, and "Virtual memory" (i.e., "logical
  6832. ** memory"), which is the memory of BLITZ user-level processes, before the
  6833. ** addresses have gone through page table translation.
  6834. **
  6835. ** The BLITZ machine is designed to support multi-processing, i.e., to
  6836. ** support multiple CPUs operating on a single shared physical memory
  6837. ** unit.  To this end, the CPU may lock portions of memory during critical
  6838. ** operations.  Examples of critical operations include: (1) the reading and
  6839. ** subsequent writing of a page table entry, and (2) the reading and
  6840. ** subsequent writing during the "tset" instruction.
  6841. **
  6842. ** The granularity of memory locks is not specified at this time.
  6843. ** It may be the case that each word has its own lock, or perhaps each lock
  6844. ** covers an entire page, or perhaps there is only a single lock covering all
  6845. ** of the physical memory.
  6846. **
  6847. ** In this implementation, we assume that individual words are locked.
  6848. ** Furthermore, we assume that, since this is a single processor implementation,
  6849. ** that only one lock will be held at a time.  Thus, locking is modelled with a
  6850. ** single variable (called "currentMemoryLock") which contains the address of
  6851. ** the word that is locked, or -1 if no word is currently locked.
  6852. ** 
  6853. ** Locking is somewhat unnecessary to the goal of this emulator, since only
  6854. ** a single CPU is emulated, yet it is included in order to model a
  6855. ** multiprocessor implementation more faithfully.  Toward this end, locks are
  6856. ** set and released at the correct times and we do some consistency checking
  6857. ** to make sure we don't (for example) try to release a lock that is not held,
  6858. ** but beyond that, there is no blocking, waiting, or scheduling associated
  6859. ** with locks.
  6860. **
  6861. ** The operations that a CPU or I/O device may issue to the memory unit are:
  6862. **
  6863. **   getPhysicalWord (physAddr)  --> int
  6864. **   getPhysicalWordAndLock (physAddr)  --> int
  6865. **   putPhysicalWord (physAddr, value)
  6866. **   putPhysicalWordAndRelease (physAddr, value)
  6867. **   releaseMemoryLock (physAddr)
  6868. **
  6869. ** In addition, there are a couple of support routines:
  6870. **
  6871. **   physicalAddressOk (physAddr)  -->  bool
  6872. **   isAligned (addr)  --> bool
  6873. **
  6874. ** All I/O is memory-mapped.  Occasionally, reads and writes to certain
  6875. ** addresses should be directed not to the memory, but to various devices.
  6876. ** Routines that support this are:
  6877. **
  6878. **   inMemoryMappedArea (physAddr)  --> bool
  6879. **   ... etc...
  6880. **
  6881. ** The CPU performs page-table translation.  All the details of the
  6882. ** page table translation are encapsulated into this routine.
  6883. **
  6884. **   translate (addr, reading, wantPrinting, doUpdates)  --> physAddr
  6885. **
  6886. ** A typical use is to first call translate to produce a physical address,
  6887. ** then check to see if an exception has occurred, then to either abort if
  6888. ** we had an exception or to call a routine (such as getPhysicalWord) to
  6889. ** fetch or store a word from/to memory.
  6890. **
  6891. **************************************************************************/
  6892.  
  6893.  
  6894.  
  6895.  
  6896. /* physicalAddressOk (addr)
  6897. **
  6898. ** This routine is passed a physical memory address.  It returns TRUE
  6899. ** if this is a legal physical memory address, i.e., if no "Address
  6900. ** Exception" should be thrown.  The address may be in the memory mapped
  6901. ** area; this is still considered OK.
  6902. */
  6903. int physicalAddressOk (int addr) {
  6904.   return ((0 <= addr ) && (addr < MEMORY_SIZE));
  6905. }
  6906.  
  6907.  
  6908.  
  6909. /* isAligned (addr)
  6910. **
  6911. ** This function returns TRUE if this address is word aligned.
  6912. */
  6913. int isAligned (int addr) {
  6914.   return addr%4 == 0;
  6915. }
  6916.  
  6917.  
  6918.  
  6919. /* getPhysicalWord (physAddr)
  6920. **
  6921. ** This routine is passed a physical memory address.  It returns the
  6922. ** word stored at that address.  The address is assumed to be OK, i.e.,
  6923. ** both aligned and within physical memory.  Therefore, no exceptions
  6924. ** are possible.  If the address is in the memory-mapped region, it calls
  6925. ** the I/O subsystem.
  6926. */
  6927. int getPhysicalWord (int physAddr) {
  6928.   int implAddr;
  6929.   if (!physicalAddressOk (physAddr)) {
  6930.     fatalError ("PROGRAM LOGIC ERROR: Invalid address in getPhysicalWord");
  6931.   }
  6932.   if (physAddr % 4 != 0) {
  6933.     fatalError ("PROGRAM LOGIC ERROR: Unaligned address in getPhysicalWord");
  6934.   }
  6935.   checkDiskBufferError (physAddr);
  6936.   if (inMemoryMappedArea (physAddr)) {
  6937.     return getMemoryMappedWord (physAddr);
  6938.   } else {
  6939.     implAddr = ((int) memory) + physAddr;
  6940.     return * (int *) implAddr;
  6941.   }
  6942. }
  6943.  
  6944.  
  6945.  
  6946. /* getPhysicalWordAndLock (physAddr)
  6947. **
  6948. ** Acquire a lock on this word and then get the word from memory.
  6949. */
  6950. int getPhysicalWordAndLock (int physAddr) {
  6951.   if (currentMemoryLock != -1) {
  6952.     fatalError ("PROGRAM LOGIC ERROR: In getPhysicalWordAndLock - lock is not clear");
  6953.   }
  6954.   currentMemoryLock = physAddr;
  6955.   return getPhysicalWord (physAddr);
  6956. }
  6957.  
  6958.  
  6959.  
  6960. /* putPhysicalWord (physAddr, value)
  6961. **
  6962. ** This routine is passed a physical memory address.  It stores the word
  6963. ** "value" at that address.  The address is assumed to be OK, i.e.,
  6964. ** both aligned and within physical memory.  Therefore, no exceptions
  6965. ** are possible.  If the address is in the memory-mapped region, it calls
  6966. ** the I/O subsystem.
  6967. */
  6968. void putPhysicalWord (int physAddr, int value) {
  6969.   int implAddr;
  6970.   if (!physicalAddressOk (physAddr)) {
  6971.     fatalError ("PROGRAM LOGIC ERROR: Invalid address in putPhysicalWord");
  6972.   }
  6973.   if (physAddr % 4 != 0) {
  6974.     fatalError ("PROGRAM LOGIC ERROR: Unaligned address in putPhysicalWord");
  6975.   }
  6976.   checkDiskBufferError (physAddr);
  6977.   if (inMemoryMappedArea (physAddr)) {
  6978.     putMemoryMappedWord (physAddr, value);
  6979.   } else {
  6980.     implAddr = ((int) memory) + physAddr;
  6981.     * (int *) implAddr = value;
  6982.   }
  6983. }
  6984.  
  6985.  
  6986.  
  6987. /* putPhysicalWordAndRelease (physAddr, value)
  6988. **
  6989. ** This routine writes a word to memory and then releases the lock.
  6990. */
  6991. void putPhysicalWordAndRelease (int physAddr, int value) {
  6992.   if (currentMemoryLock != physAddr) {
  6993.     fatalError ("PROGRAM LOGIC ERROR: In putPhysicalWordAndRelease - lock is not held for this address");
  6994.   }
  6995.   currentMemoryLock = -1;
  6996.   putPhysicalWord (physAddr, value);
  6997. }
  6998.  
  6999.  
  7000.  
  7001. /* releaseMemoryLock (physAddr)
  7002. **
  7003. ** This routine releases the lock on this memory location.
  7004. */
  7005. void releaseMemoryLock (int physAddr) {
  7006.   if (currentMemoryLock != physAddr) {
  7007.     fatalError ("PROGRAM LOGIC ERROR: In releaseMemoryLock - Lock not held on this address");
  7008.   }
  7009.   currentMemoryLock = -1;
  7010. }
  7011.  
  7012.  
  7013.  
  7014. /* inMemoryMappedArea (addr)
  7015. **
  7016. ** This routine is passed a physical address.  It returns true if
  7017. ** this address is the range of memory-mapped bytes.
  7018. */
  7019. int inMemoryMappedArea (int addr) {
  7020.   return (addr >= MEMORY_MAPPED_AREA_LOW) && (addr <= MEMORY_MAPPED_AREA_HIGH);
  7021. }
  7022.  
  7023.  
  7024.  
  7025. /* translate (virtAddr, reading, wantPrinting, doUpdates) --> physAddr
  7026. **
  7027. ** This routine is passed a logical address "virtAddr", which should be
  7028. ** word-aligned.
  7029. **
  7030. ** If paging is turned on, it will go through the page tables, compute the
  7031. ** physical address and return it.  If paging is off, it will return the
  7032. ** address, as is.  This routine will check for all exceptions that would
  7033. ** arise if memory were accessed using this address.  This routine will not
  7034. ** actually read or write the target memory word.
  7035. **
  7036. ** If "reading" is true, it indicates that the coming memory operation
  7037. ** will be a read, otherwise we intend to write to the address.  This is
  7038. ** needed since the page may be marked read-only.
  7039. **
  7040. ** If "wantPrinting" is TRUE, this routine will print out a trace of
  7041. ** how this logical address is processed, and which exception would
  7042. ** be signalled, if any.
  7043. **
  7044. ** If "doUpdates" is TRUE, this routine will update the page table
  7045. ** entry and will signal an interrupt (if one should occur).  If "doUpdates"
  7046. ** is FALSE, the page table entry will be unchanged and no exception will
  7047. ** be signalled.
  7048. **
  7049. ** This routine has the side-effect of setting the variable
  7050. ** "translateCausedException" to TRUE iff an exception should be
  7051. ** generated by this translation.  This variable is set regardless of
  7052. ** "doUpdates".
  7053. */
  7054. int translate (int virtAddr, int reading, int wantPrinting, int doUpdates) {
  7055.   int tableIndex, tableEntryAddr, tableEntry, frameNumber, offset, physAddr;
  7056.  
  7057.   translateCausedException = 0;
  7058.   if (wantPrinting) {
  7059.     printf ("*****  PAGE TRANSLATION BEGINNING  *****\n");
  7060.     printf ("   Logical address             = 0x%08X\n", virtAddr);
  7061.   }
  7062.  
  7063.   /* Check for an alignment exception.  If found, signal it and return. */
  7064.   if (!isAligned (virtAddr)) {
  7065.     if (wantPrinting) {
  7066.       printf ("   This address is not divisible by 4: ALIGNMENT_EXCEPTION\n");
  7067.     }
  7068.     translateCausedException = 1;
  7069.     if (doUpdates) {
  7070.       interruptsSignaled |= ALIGNMENT_EXCEPTION;
  7071.     }
  7072.     return 0;
  7073.   }
  7074.  
  7075.   /* If paging is turned off... */
  7076.   if (!statusP) {
  7077.     if (wantPrinting) {
  7078.       printf ("   Status[P] = 0, Paging is turned off\n");
  7079.       printf ("   Physical address            = 0x%08X\n", virtAddr);
  7080.     }
  7081.     /* Check for an address exception.  If found, signal it and return. */
  7082.     if (!physicalAddressOk (virtAddr)) {
  7083.       if (wantPrinting) {
  7084.         printf ("   Bad physical address: ADDRESS_EXCEPTION\n");
  7085.       }
  7086.       translateCausedException = 1;
  7087.       if (doUpdates) {
  7088.         interruptsSignaled |= ADDRESS_EXCEPTION;
  7089.       }
  7090.       return 0;
  7091.     }
  7092.     /* Return the virtual address as the physical address. */
  7093.     return virtAddr;
  7094.  
  7095.   /* If paging is turned on... */
  7096.   } else {
  7097.     tableIndex = virtAddr & 0x00ffe000;
  7098.     offset = virtAddr & 0x00001fff;
  7099.     if (wantPrinting) {
  7100.       printf ("     Page Number               = 0x%08X\n", tableIndex);
  7101.       printf ("     Offset into page          = 0x%08X\n", offset);
  7102.       printf ("   Status[P] = 1, Paging is turned on\n");
  7103.     }
  7104.  
  7105.     /* Check for an address exception.  If found, signal it and return. */
  7106.     if (virtAddr & 0xff000000) {
  7107.       if (wantPrinting) {
  7108.         printf ("   Logical address out of range: ADDRESS_EXCEPTION\n");
  7109.       }
  7110.       translateCausedException = 1;
  7111.       if (doUpdates) {
  7112.         interruptsSignaled |= ADDRESS_EXCEPTION;
  7113.       }
  7114.       return 0;
  7115.     }
  7116.  
  7117.     /* Determine which page table entry we will be accessing. */
  7118.     tableIndex = tableIndex >> 11;
  7119.     tableEntryAddr = ptbr + tableIndex;
  7120.     if (wantPrinting) {
  7121.       printf ("   Page Table:\n");
  7122.       printf ("            base               = 0x%08X\n", ptbr);
  7123.       printf ("            length             = 0x%08X\n", ptlr);
  7124.       printf ("            addr of last entry = 0x%08X\n", ptbr + ptlr - 4);
  7125.       printf ("   Page number (shifted)       = 0x%08X\n", tableIndex);
  7126.       printf ("   Address of page table entry = 0x%08X\n", tableEntryAddr);
  7127.     }
  7128.  
  7129.     /* Check for a PAGE_INVALID exception.  If found, signal it and return. */
  7130.     if (tableIndex >= ptlr) {
  7131.       if (wantPrinting) {
  7132.         printf ("   This entry is not within the page table bound: PAGE_INVALID_EXCEPTION\n");
  7133.       }
  7134.       translateCausedException = 1;
  7135.       if (doUpdates) {
  7136.         interruptsSignaled |= PAGE_INVALID_EXCEPTION;
  7137.         pageInvalidOffendingAddress = virtAddr;
  7138.       }
  7139.       return 0;
  7140.     }
  7141.  
  7142.     /* Check for an address exception.  If found, signal it and return. */
  7143.     if (!physicalAddressOk (tableEntryAddr)) {
  7144.       if (wantPrinting) {
  7145.         printf ("   This page table entry is not within physical memory: ADDRESS_EXCEPTION\n");
  7146.       }
  7147.       translateCausedException = 1;
  7148.       if (doUpdates) {
  7149.         interruptsSignaled |= ADDRESS_EXCEPTION;
  7150.       }
  7151.       return 0;
  7152.     }
  7153.  
  7154.     /* Get the page table entry. */
  7155.        /* (tableEntryAddr must be aligned since ptbr is aligned.) */
  7156.     tableEntry = getPhysicalWordAndLock (tableEntryAddr);
  7157.     frameNumber = tableEntry & 0xffffe000;
  7158.     if (wantPrinting) {
  7159.       printf ("   Page table entry            = 0x%08X\n", tableEntry);
  7160.       printf ("       Frame number = 0x%08X\n", frameNumber);
  7161.       if (tableEntry & 0x00000001) {
  7162.         printf ("       V=1 (Page is valid)\n");
  7163.       } else {
  7164.         printf ("       V=0 (Page not valid)\n");
  7165.       }
  7166.       if (tableEntry & 0x00000002) {
  7167.         printf ("       W=1 (Page is writable)\n");
  7168.       } else {
  7169.         printf ("       W=0 (Page not writable)\n");
  7170.       }
  7171.       if (tableEntry & 0x00000004) {
  7172.         printf ("       R=1 (Page has been referenced)\n");
  7173.       } else {
  7174.         printf ("       R=0 (Page has not been referenced)\n");
  7175.       }
  7176.       if (tableEntry & 0x00000008) {
  7177.         printf ("       D=1 (Page is dirty)\n");
  7178.       } else {
  7179.         printf ("       D=0 (Page not dirty)\n");
  7180.       }
  7181.     }
  7182.  
  7183.     /* Check for a PAGE_INVALID exception.  If found, signal it and return. */
  7184.     if (!(tableEntry & 0x00000001)) {   /* if V bit is clear... */
  7185.       if (wantPrinting) {
  7186.         printf ("   Valid bit is clear: PAGE_INVALID_EXCEPTION\n");
  7187.       }
  7188.       translateCausedException = 1;
  7189.       if (doUpdates) {
  7190.         interruptsSignaled |= PAGE_INVALID_EXCEPTION;
  7191.         pageInvalidOffendingAddress = virtAddr;
  7192.       }
  7193.       releaseMemoryLock (tableEntryAddr);
  7194.       return 0;
  7195.     }
  7196.  
  7197.     /* If we will be writing to memory...*/
  7198.     if (!reading) {
  7199.  
  7200.       /* Check for a PAGE_READONLY exception.  If found, signal and return. */
  7201.       if (!(tableEntry & 0x00000002)) {   /* if W bit is clear... */
  7202.         if (wantPrinting) {
  7203.           printf ("   Writable bit is clear: PAGE_READONLY_EXCEPTION\n");
  7204.         }
  7205.         translateCausedException = 1;
  7206.         if (doUpdates) {
  7207.           interruptsSignaled |= PAGE_READONLY_EXCEPTION;
  7208.           pageReadonlyOffendingAddress = virtAddr;
  7209.         }
  7210.         releaseMemoryLock (tableEntryAddr);
  7211.         return 0;
  7212.       }
  7213.  
  7214.       /* Set the dirty bit */
  7215.       if (wantPrinting) {
  7216.         printf ("   Setting the dirty bit\n");
  7217.       }
  7218.       tableEntry |= 0x00000008;
  7219.     }
  7220.  
  7221.     /* Set the referenced bit */
  7222.     if (wantPrinting) {
  7223.       printf ("   Setting the referenced bit\n");
  7224.     }
  7225.     tableEntry |= 0x00000004;
  7226.  
  7227.     /* Compute the physical address. */
  7228.     physAddr = frameNumber | offset;
  7229.     if (wantPrinting) {
  7230.       printf ("   Physical address            = 0x%08X\n", physAddr);
  7231.     }
  7232.  
  7233.     /* Check for an ADDRESS exception.  If found, signal it and return. */
  7234.     if (!physicalAddressOk (physAddr)) {
  7235.       if (wantPrinting) {
  7236.         printf ("   Bad physical address: ADDRESS_EXCEPTION\n");
  7237.       }
  7238.       translateCausedException = 1;
  7239.       if (doUpdates) {
  7240.         interruptsSignaled |= ADDRESS_EXCEPTION;
  7241.       }
  7242.       releaseMemoryLock (tableEntryAddr);
  7243.       return 0;
  7244.     }
  7245.  
  7246.     /* If we are supposed to update the page table, then update it. */
  7247.     if (doUpdates) {
  7248.       putPhysicalWordAndRelease (tableEntryAddr, tableEntry);
  7249.     } else {
  7250.       releaseMemoryLock (tableEntryAddr);
  7251.     }
  7252.     if (wantPrinting) {
  7253.       printf ("   Modified page table entry   = 0x%08X\n", tableEntry);
  7254.       if (doUpdates) {
  7255.         printf ("     (Page table entry was written back to memory)\n");
  7256.       } else {
  7257.         printf ("     (Page table entry was NOT modified)\n");
  7258.       }
  7259.       printf ("   Translation completed with no exceptions\n");
  7260.     }
  7261.  
  7262.     /* Return the physical address. */
  7263.     return physAddr;
  7264.   }
  7265. }
  7266.  
  7267.  
  7268.  
  7269. /* getMemoryMappedWord (physAddr)  ==> int
  7270. **
  7271. */
  7272. int getMemoryMappedWord (int physAddr) {
  7273.   int x;
  7274.  
  7275.   /* Terminal status word... */
  7276.   if (physAddr == SERIAL_STATUS_WORD_ADDRESS) {
  7277.     x = 0;
  7278.     if (termInCharAvail) {
  7279.       x = x | 0x00000001;
  7280.     }
  7281.     if (termOutputReady) {
  7282.       x = x | 0x00000002;
  7283.     }
  7284.     return x;
  7285.  
  7286.   /* Terminal input buffer... */
  7287.   } else if (physAddr == SERIAL_DATA_WORD_ADDRESS) {
  7288.     termInCharWasUsed = 1;
  7289.     termInCharAvail = 0;
  7290.     return termInChar;
  7291.  
  7292.   /* Disk status word... */
  7293.   } else if (physAddr == DISK_STATUS_WORD_ADDRESS) {
  7294.     return currentDiskStatus;
  7295.  
  7296.   /* DISK_MEMORY_ADDRESS_REGISTER... */
  7297.   } else if (physAddr == DISK_MEMORY_ADDRESS_REGISTER) {
  7298.     return diskMemoryAddressRegister;
  7299.  
  7300.   /* DISK_SECTOR_NUMBER_REGISTER... */
  7301.   } else if (physAddr == DISK_SECTOR_NUMBER_REGISTER) {
  7302.     return diskSectorNumberRegister;
  7303.  
  7304.   /* DISK_SECTOR_COUNT_REGISTER... */
  7305.   } else if (physAddr == DISK_SECTOR_COUNT_REGISTER) {
  7306.     return diskSectorCountRegister;
  7307.  
  7308.   /* All other words in the memory-mapped I/O region... */
  7309.   } else {
  7310.     fprintf (stderr, "\n\rERROR: Attempt to access undefined address in memory-mapped area\n\r");
  7311.     controlCPressed = 1;
  7312.   }
  7313. }
  7314.  
  7315.  
  7316.  
  7317. /* putMemoryMappedWord (physAddr, value)
  7318. **
  7319. */
  7320. void putMemoryMappedWord (int physAddr, int value) {
  7321.   int x;
  7322.  
  7323.   /* Terminal status word... */
  7324.   if (physAddr == SERIAL_STATUS_WORD_ADDRESS) {
  7325.     fprintf (stderr, "\n\rAttempt to write to the SERIAL_STATUS_WORD in the memory-mapped area\n\r");
  7326.     controlCPressed = 1;
  7327.     return;
  7328.  
  7329.   /* Terminal output buffer... */
  7330.   } else if (physAddr == SERIAL_DATA_WORD_ADDRESS) {
  7331.     x = value & 0x000000ff;
  7332.     if (!termOutputReady) {
  7333.       fprintf (stderr, "\n\rERROR: Serial device output overrun; char \"%c\" was lost\n\r",
  7334.                x);
  7335.       controlCPressed = 1;
  7336.       return;
  7337.     }
  7338.     /***  fprintf (termOutputFile, "OUTPUT >>>%c<<<\n\r", x);  ***/
  7339.     fprintf (termOutputFile, "%c", x);
  7340.     fflush (termOutputFile);
  7341.     termOutputReady = 0;
  7342.     timeOfNextSerialOutEvent =
  7343.          randomBetween (
  7344.             currentTime + TERM_OUT_DELAY,
  7345.             currentTime + TERM_OUT_DELAY + TERM_OUT_DELAY_VARIATION);
  7346.     if (timeOfNextSerialOutEvent <= currentTime) {
  7347.       timeOfNextSerialOutEvent = currentTime + 1;
  7348.     }
  7349.     updateTimeOfNextEvent ();
  7350.  
  7351.   /* DISK_COMMAND_WORD_ADDRESS... */
  7352.   } else if (physAddr == DISK_COMMAND_WORD_ADDRESS) {
  7353.     if (currentDiskStatus == DISK_BUSY) {
  7354.       fprintf (stderr, "\n\rERROR: Attempt to write to DISK_COMMAND_WORD while disk is busy!\n\r");
  7355.       controlCPressed = 1;
  7356.       return;
  7357.     } else {
  7358.       performDiskIO (value);
  7359.     }
  7360.  
  7361.   /* DISK_MEMORY_ADDRESS_REGISTER... */
  7362.   } else if (physAddr == DISK_MEMORY_ADDRESS_REGISTER) {
  7363.     if (currentDiskStatus == DISK_BUSY) {
  7364.       fprintf (stderr, "\n\rERROR: Attempt to write to DISK_MEMORY_ADDRESS_REGISTER while disk is busy!\n\r");
  7365.       controlCPressed = 1;
  7366.       return;
  7367.     } else {
  7368.       diskMemoryAddressRegister = value;
  7369.     }
  7370.  
  7371.   /* DISK_SECTOR_NUMBER_REGISTER... */
  7372.   } else if (physAddr == DISK_SECTOR_NUMBER_REGISTER) {
  7373.     if (currentDiskStatus == DISK_BUSY) {
  7374.       fprintf (stderr, "\n\rERROR: Attempt to write to DISK_SECTOR_NUMBER_REGISTER while disk is busy!\n\r");
  7375.       controlCPressed = 1;
  7376.       return;
  7377.     } else {
  7378.       diskSectorNumberRegister = value;
  7379.     }
  7380.  
  7381.   /* DISK_SECTOR_COUNT_REGISTER... */
  7382.   } else if (physAddr == DISK_SECTOR_COUNT_REGISTER) {
  7383.     if (currentDiskStatus == DISK_BUSY) {
  7384.       fprintf (stderr, "\n\rERROR: Attempt to write to DISK_SECTOR_COUNT_REGISTER while disk is busy!\n\r");
  7385.       controlCPressed = 1;
  7386.       return;
  7387.     } else {
  7388.       diskSectorCountRegister = value;
  7389.     }
  7390.  
  7391.   /* All other words in the memory-mapped I/O region... */
  7392.   } else {
  7393.     fprintf (stderr, "\n\rERROR: Attempt to access undefined address in memory-mapped area\n\r");
  7394.     controlCPressed = 1;
  7395.   }
  7396. }
  7397.  
  7398.  
  7399.  
  7400.  
  7401. /**************************************************************************
  7402. **
  7403. ** END OF MEMORY SUB-SYSTEM
  7404. **
  7405. **************************************************************************/
  7406.  
  7407.  
  7408.  
  7409. /* pushOntoStack (reg, value)
  7410. **
  7411. ** This routine is passed a 32-bit value.  It pushes it onto the stack.
  7412. ** It is passed the number of the register to use as the stack top
  7413. ** pointer.  If an exception occurs, it is made pending but no other
  7414. ** changes are made.
  7415. */
  7416. void pushOntoStack (int reg, int value) {
  7417.   int top, physAddr;
  7418.   if (statusS) {
  7419.     top = systemRegisters [reg];
  7420.   } else {
  7421.     top = userRegisters [reg];
  7422.   }
  7423.   top -= 4;
  7424.   /* Call translate with reading=false, wantPrinting=false, doUpdates=true */
  7425.   physAddr = translate (top, 0, 0, 1);
  7426.   if (translateCausedException) {
  7427.     return;
  7428.   }
  7429.   putPhysicalWord (physAddr, value);
  7430.   if (reg==0) {
  7431.     return;
  7432.   }
  7433.   if (reg==0) {
  7434.     return;
  7435.   }
  7436.   if (statusS) {
  7437.     systemRegisters [reg] = top;
  7438.   } else {
  7439.     userRegisters [reg] = top;
  7440.   }
  7441. }
  7442.  
  7443.  
  7444.  
  7445. /* popFromStack (reg)
  7446. **
  7447. ** This routine pops a word from the stack and returns it.  It is passed
  7448. ** the number of the register to use as the stack top pointer.  If an
  7449. ** exception occurs, it is made pending and zero is returned, but no other
  7450. ** changes are made.
  7451. */
  7452. int popFromStack (int reg) {
  7453.   int top, physAddr, value;
  7454.   if (statusS) {
  7455.     top = systemRegisters [reg];
  7456.   } else {
  7457.     top = userRegisters [reg];
  7458.   }
  7459.   /* Call translate with reading=true, wantPrinting=false, doUpdates=true */
  7460.   physAddr = translate (top, 1, 0, 1);
  7461.   if (translateCausedException) {
  7462.     return 0;
  7463.   }
  7464.   value = getPhysicalWord (physAddr);
  7465.   if (reg==0) {
  7466.     return value;
  7467.   }
  7468.   top += 4;
  7469.   if (statusS) {
  7470.     systemRegisters [reg] = top;
  7471.   } else {
  7472.     userRegisters [reg] = top;
  7473.   }
  7474.   return value;
  7475. }
  7476.  
  7477.  
  7478.  
  7479. /* commandShowStack ()
  7480. **
  7481. ** This routine prints out the KPL calling stack.
  7482. */
  7483. void commandShowStack () {
  7484.   int i = 0;
  7485.   printf ("   Function/Method            Frame Addr   Execution at...\n");
  7486.   printf ("   ========================   ==========   =====================\n");
  7487.   while (1) {
  7488.     if (!printFrame (i, 0)) break;
  7489.     i++;
  7490.     if (i % 50 == 0) {
  7491.       printf ("Want more (y/n)? ");
  7492.       if (readYesNo () != 1) return;
  7493.     }
  7494.   }
  7495. }
  7496.  
  7497.  
  7498.  
  7499. /* commandFrame ()
  7500. **
  7501. ** This routine prints out the current frame in the calling stack in
  7502. ** the format:
  7503. **   foo    testPack.c, line 123
  7504. */
  7505. void commandFrame () {
  7506.   printf ("=====  Frame number %d (where StackTop = 0)  =====\n",
  7507.           currentFrame);
  7508.   if (!printFrame (currentFrame, 1)) {
  7509.     printf ("Resetting current frame to top of stack!\n");
  7510.     currentFrame = 0;
  7511.   }
  7512. }
  7513.  
  7514.  
  7515.  
  7516. /* commandStackUp ()
  7517. **
  7518. ** This routine moves up one frame (toward the stack top) and prints
  7519. ** the frame.
  7520. */
  7521. void commandStackUp () {
  7522.   currentFrame--;
  7523.   if (currentFrame < 0) {
  7524.     printf ("Already at top of stack!\n");
  7525.     currentFrame = 0;
  7526.   }
  7527.   printf ("=====  Frame number %d (where StackTop = 0)  =====\n",
  7528.           currentFrame);
  7529.   if (!printFrame (currentFrame, 1)) {
  7530.     printf ("Resetting current frame to top of stack!\n");
  7531.     currentFrame = 0;
  7532.   }
  7533. }
  7534.  
  7535.  
  7536.  
  7537. /* commandStackDown ()
  7538. **
  7539. ** This routine moves down one frame (deeper into the stack) and prints
  7540. ** the frame.
  7541. */
  7542. void commandStackDown () {
  7543.   currentFrame++;
  7544.   printf ("=====  Frame number %d (where StackTop = 0)  =====\n",
  7545.           currentFrame);
  7546.   if (!printFrame (currentFrame, 1)) {
  7547.     printf ("Resetting current frame to top of stack!\n");
  7548.     currentFrame = 0;
  7549.   }
  7550. }
  7551.  
  7552.  
  7553.  
  7554. /* printFrame (frameNumber, longPrint)  -->  bool
  7555. **
  7556. ** This routine prints out frame number "frameNumber" in the calling stack.
  7557. ** Frame 0 is on the stack top.  If everything is ok, we return TRUE; if
  7558. ** problems (including end of stack) we return FALSE.
  7559. **
  7560. ** If longPrint is FALSE, we print one line; if TRUE, we print the full frame.
  7561. */
  7562. int printFrame (int frameNumber, int longPrint) {
  7563.   int r13, fp, sp, physAddr, addrOfRoutineDescriptor,
  7564.       filenamePtr, ptrToFunName, lineNum, oldFp, p, i, j, vdAddr, ptrToVarName,
  7565.       offset, offset2, code, totalParmSize, frameSize, index, sizeInBytes;
  7566.   TableEntry * tableEntry;
  7567.   int * ptr;
  7568.   double d; 
  7569.  
  7570.   // Get "r13" and "r14/fp"...
  7571.   if (statusS) {
  7572.     r13 = systemRegisters [13];
  7573.     fp = systemRegisters [14];
  7574.     sp = systemRegisters [15];
  7575.   } else {
  7576.     r13 = userRegisters [13];
  7577.     fp = userRegisters [14];
  7578.     sp = userRegisters [15];
  7579.   }
  7580.   lineNum = r13;
  7581.   oldFp = sp;
  7582.  
  7583.   while (frameNumber > 0) {
  7584.     frameNumber--;
  7585.  
  7586.     // Get "lineNum" from this frame...
  7587.     physAddr = translate (fp-4, 1, 0, 0);  // reading=1, wantPrinting=0, doUpdates=0
  7588.     if (translateCausedException) {
  7589.       printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7590.       return 0;
  7591.     }
  7592.     lineNum = getPhysicalWord (physAddr);
  7593.  
  7594.     // Get new frame pointer "fp" from this frame...
  7595.     physAddr = translate (fp, 1, 0, 0);  // reading=1, wantPrinting=0, doUpdates=0
  7596.     if (translateCausedException) {
  7597.       printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7598.       return 0;
  7599.     }
  7600.  
  7601.     oldFp = fp;
  7602.     fp = getPhysicalWord (physAddr);
  7603.  
  7604.     if (fp != 0 && fp <= oldFp) {
  7605.       printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", oldFp);
  7606.       return 0;
  7607.     }
  7608.   }
  7609.  
  7610.   if (fp == 0) {
  7611.     printf ("Bottom of activation frame stack!\n");
  7612.     return 0;
  7613.   }
  7614.  
  7615.   // printf ("frame pointer = ");
  7616.   // printNumberNL (fp);
  7617.  
  7618.   // Get ptr to routine descriptor
  7619.   physAddr = translate (fp-8, 1, 0, 0);  // reading=1, wantPrinting=0, doUpdates=0
  7620.   if (translateCausedException) {
  7621.     printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7622.     return 0;
  7623.   }
  7624.   addrOfRoutineDescriptor = getPhysicalWord (physAddr);
  7625.   // printf ("addrOfRoutineDescriptor = ");
  7626.   // printNumberNL (addrOfRoutineDescriptor);
  7627.  
  7628.   // Get ptr to filename...
  7629.   physAddr = translate (addrOfRoutineDescriptor, 1, 0, 0);
  7630.   if (translateCausedException) {
  7631.     printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7632.     return 0;
  7633.   }
  7634.   filenamePtr = getPhysicalWord (physAddr);
  7635.   // printf ("filenamePtr = ");
  7636.   // printNumberNL (filenamePtr);
  7637.  
  7638.   // Get ptr to function name...
  7639.   physAddr = translate (addrOfRoutineDescriptor+4, 1, 0, 0);
  7640.   if (translateCausedException) {
  7641.     printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7642.     return 0;
  7643.   }
  7644.   ptrToFunName = getPhysicalWord (physAddr);
  7645.   // printf ("ptrToFunName = ");
  7646.   // printNumberNL (ptrToFunName);
  7647.  
  7648.   // Get totalParmSize...
  7649.   physAddr = translate (addrOfRoutineDescriptor+8, 1, 0, 0);
  7650.   if (translateCausedException) {
  7651.     printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7652.     return 0;
  7653.   }
  7654.   totalParmSize = getPhysicalWord (physAddr);
  7655.  
  7656.   // Get frameSize...
  7657.   physAddr = translate (addrOfRoutineDescriptor+12, 1, 0, 0);
  7658.   if (translateCausedException) {
  7659.     printf ("Invalid activation frame stack!  The frame pointer is 0x%08X.\n", fp);
  7660.     return 0;
  7661.   }
  7662.   frameSize = getPhysicalWord (physAddr);
  7663.  
  7664.   if (longPrint == 0) {
  7665.  
  7666.     // Print the function name...
  7667.     printf ("   ");
  7668.     if (!printAsciiDataInWidth (ptrToFunName, 27)) return 0;
  7669.     printf (" ");
  7670.  
  7671.     // Print the frame address...
  7672.     putlong (fp);
  7673.     printf ("    ");
  7674.  
  7675.     // Print the Filename...
  7676.     if (!printAsciiDataInWidth (filenamePtr,0)) return 0;
  7677.  
  7678.     // Print the line number...
  7679.     printf (", line %d\n", lineNum);
  7680.  
  7681.     return 1;
  7682.   }
  7683.  
  7684.   // Perform the long printout of the frame...
  7685.  
  7686.   // Print the function name...
  7687.   printf ("Function Name:    ");
  7688.   printAsciiDataInWidth (ptrToFunName, 0);
  7689.   printf ("\n");
  7690.  
  7691.   // Print the Filename...
  7692.   printf ("Filename:         ");
  7693.   printAsciiDataInWidth (filenamePtr, 0);
  7694.   printf ("\n");
  7695.  
  7696.   // Print the line number...
  7697.   printf ("Execution now at: line %d\n", lineNum);
  7698.  
  7699.   // Print the frame address...
  7700.   printf ("Frame Addr:       ");
  7701.   putlong (fp);
  7702.   printf ("\n");
  7703.   printf ("frameSize:        %d\n", frameSize);
  7704.   printf ("totalParmSize:    %d\n", totalParmSize);
  7705.  
  7706.   printf ("                         ==========\n");
  7707.   if (oldFp != sp) {
  7708.     oldFp = oldFp+8;
  7709.   }
  7710.   for (p = oldFp; p <= fp+totalParmSize+4; p = p+4) {
  7711.     if (p == fp) {
  7712.       printf ("     fp:");
  7713.     } else if (p == fp-4) {
  7714.       printf ("    r13:");
  7715.     } else if (p == fp-8) {
  7716.       printf ("R.D.ptr:");
  7717.     } else if (p == fp+4) {
  7718.       printf ("RetAddr:");
  7719.     } else if (p == fp+8) {
  7720.       printf ("   Args:");
  7721.     } else if (p == sp) {
  7722.       printf ("   sp-->");
  7723.     } else {
  7724.       printf ("        ");
  7725.     }
  7726.     printf ("%4d   %08X:  ", p-fp, p);
  7727.     physAddr = translate (p, 1, 0, 0);
  7728.     if (translateCausedException) {
  7729.       printf ("*****  MEMORY EXCEPTION  *****\n");
  7730.     } else {
  7731.       i = getPhysicalWord (physAddr);
  7732.       printf ("%08X\n", i);
  7733.     }
  7734.     if (p == fp+4) {
  7735.       printf ("                         ==========\n");
  7736.     }
  7737.   }
  7738.  
  7739.  
  7740.   printf ("\nPARAMETERS AND LOCAL VARIABLES WITHIN THIS FRAME:\n");
  7741.   printf ("=================================================\n");
  7742.  
  7743.   // In a loop, print each var descriptor...
  7744.   vdAddr = addrOfRoutineDescriptor + 16;
  7745.   while (1) {
  7746.  
  7747.     // Get ptr to variable name...
  7748.     physAddr = translate (vdAddr, 1, 0, 0);
  7749.     if (translateCausedException) {
  7750.       printf ("Problems in variable descriptor information in memory (addr = 0x%08X - address exception when accessing ptr to var name)!\n",
  7751.               vdAddr);
  7752.       break;
  7753.     }
  7754.     ptrToVarName = getPhysicalWord (physAddr);
  7755.  
  7756.     // If the pointer is zero, we are done...
  7757.     if (ptrToVarName == 0) break;
  7758.  
  7759.     // Get offset...
  7760.     physAddr = translate (vdAddr+4, 1, 0, 0);
  7761.     if (translateCausedException) {
  7762.       printf ("Problems in variable descriptor information in memory (addr = 0x%08X - address exception when accessing offset)!\n",
  7763.               vdAddr+4);
  7764.       break;
  7765.     }
  7766.     offset = getPhysicalWord (physAddr);
  7767.  
  7768.     // Get sizeInBytes...
  7769.     physAddr = translate (vdAddr+8, 1, 0, 0);
  7770.     if (translateCausedException) {
  7771.       printf ("Problems in variable descriptor information in memory (addr = 0x%08X - bad sizeInBytes)!\n",
  7772.               vdAddr+8);
  7773.       break;
  7774.     }
  7775.     sizeInBytes = getPhysicalWord (physAddr);
  7776.  
  7777.     // Get the type code (e.g., 'D', 'I', etc.)
  7778.     physAddr = translate (ptrToVarName, 1, 0, 0);
  7779.     if (translateCausedException) {
  7780.       printf ("Problems in variable descriptor information in memory (addr = 0x%08X - address exception when accessing type code)!\n",
  7781.               ptrToVarName);
  7782.       break;
  7783.     }
  7784.     code = getPhysicalWord (physAddr);
  7785.     code = (code >> 24) & 0x000000ff;
  7786.  
  7787.     ptrToVarName++;
  7788.  
  7789.     // Print the variable name...
  7790.     printf ("  ");
  7791.     printAsciiDataInWidth (ptrToVarName, 0);
  7792.     if (code == 'I') {
  7793.       printf (": int\n");
  7794.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7795.       physAddr = translate (fp+offset, 1, 0, 0);
  7796.       if (translateCausedException) {
  7797.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7798.       } else {
  7799.         i = getPhysicalWord (physAddr);
  7800.         printf ("%08X    value = %d\n", i, i);
  7801.       }
  7802.     } else if (code == '?') {    // This would be for temporaries...
  7803.       printf ("\n");
  7804.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7805.       physAddr = translate (fp+offset, 1, 0, 0);
  7806.       if (translateCausedException) {
  7807.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7808.       } else {
  7809.         i = getPhysicalWord (physAddr);
  7810.         printf ("%08X\n", i);
  7811.         for (j = 4; j< sizeInBytes; j=j+4) {
  7812.           physAddr = translate (fp+offset+j, 1, 0, 0);
  7813.           if (translateCausedException) {
  7814.             printf ("*****  MEMORY EXCEPTION  *****\n");
  7815.           } else {
  7816.             i = getPhysicalWord (physAddr);
  7817.             printf ("        %4d   %08X:  %08X\n", offset+j, fp+offset+j, i);
  7818.           }
  7819.         }
  7820.       }
  7821.     } else if (code == 'D') {
  7822.       printf (": double\n");
  7823.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7824.       physAddr = translate (fp+offset, 1, 0, 0);
  7825.       if (translateCausedException) {
  7826.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7827.       } else {
  7828.         i = getPhysicalWord (physAddr);
  7829.         ptr = (int *) (& d);
  7830.         *ptr = i;
  7831.         ptr++;
  7832.         physAddr = translate (fp+offset+4, 1, 0, 0);
  7833.         if (translateCausedException) {
  7834.           printf ("*****  MEMORY EXCEPTION  *****\n");
  7835.         } else {
  7836.           j = getPhysicalWord (physAddr);
  7837.           *ptr = j;
  7838.           printf ("%08X    value = ", i);
  7839.           if (isnan(d)) {
  7840.             printf ("Not-a-Number\n");
  7841.           } else if (d == POSITIVE_INFINITY) {
  7842.             printf ("Positive-Infinity\n");
  7843.           } else if (d == NEGATIVE_INFINITY) {
  7844.             printf ("Negative-Infinity\n");
  7845.           } else if (isNegZero (d)) {
  7846.             printf ("Negative-Zero\n");
  7847.           } else {
  7848.             printf ("%.15g\n", d);        // This precision is a little low, to look nice
  7849.           }
  7850.           printf ("        %4d   %08X:  %08X\n", offset+4, fp+offset+4, j);
  7851.         }
  7852.       }
  7853.     } else if ((code == 'C') || (code == 'B')) {
  7854.       if (code == 'C') {
  7855.         printf (": char\n");
  7856.       } else {
  7857.         printf (": bool\n");
  7858.       }
  7859.       // printf ("offset = 0x%08X  %d\n", offset, offset);
  7860.       divide (offset, 4);
  7861.       offset2 = q * 4;
  7862.       // printf ("offset2 = 0x%08X  %d\n", offset2, offset2);
  7863.       printf ("        %4d   %08X:  ", offset, fp+offset2);
  7864.       physAddr = translate (fp+offset2, 1, 0, 0);
  7865.       if (translateCausedException) {
  7866.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7867.       } else {
  7868.         i = getPhysicalWord (physAddr);
  7869.         if (r == 0) {
  7870.           i = (i >> 24) & 0x000000ff;
  7871.           printf ("%02X------", i);
  7872.         } else if (r == 1) {
  7873.           i = (i >> 16) & 0x000000ff;
  7874.           printf ("--%02X----", i);
  7875.         } else if (r == 2) {
  7876.           i = (i >> 8) & 0x000000ff;
  7877.           printf ("----%02X--", i);
  7878.         } else if (r == 3) {
  7879.           i = (i >> 0) & 0x000000ff;
  7880.           printf ("------%02X", i);
  7881.         }
  7882.         if (code == 'C') {
  7883.           printf ("    value = '");
  7884.           fancyPrintChar (i);
  7885.           printf ("'\n");
  7886.         } else {
  7887.           if (i == 0) {
  7888.             printf ("    value = FALSE\n");
  7889.           } else if (i == 1) {
  7890.             printf ("    value = TRUE\n");
  7891.           } else {
  7892.             printf ("    value = *****  ERROR IN BOOLEAN VALUE  *****\n");
  7893.           }
  7894.         }
  7895.       }
  7896.     } else if (code == 'P') {
  7897.       printf (": ptr\n");
  7898.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7899.       physAddr = translate (fp+offset, 1, 0, 0);
  7900.       if (translateCausedException) {
  7901.         printf ("*****  MEMORY EXCEPTION  *****");
  7902.       } else {
  7903.         i = getPhysicalWord (physAddr);
  7904.         printf ("%08X    --> ", i);
  7905.         index = findLabel (i);
  7906.         if ((index != -1) && (i != 0)) {
  7907.           tableEntry = valueIndex [index];
  7908.           printf ("(%s) ", tableEntry->string);
  7909.         }
  7910.         if (i == 0) {
  7911.           printf ("NULL");
  7912.         } else {
  7913.           divide (i, 4);
  7914.           j = q * 4;
  7915.           printf ("%08X:  ", j);
  7916.           physAddr = translate (j, 1, 0, 0);
  7917.           if (translateCausedException) {
  7918.             printf ("*****  MEMORY EXCEPTION  *****");
  7919.           } else {
  7920.             i = getPhysicalWord (physAddr);
  7921.             if (r == 0) {
  7922.               printf ("%08X", i);
  7923.             } else if (r == 1) {
  7924.               printf ("--%06X", i & 0x00ffffff);
  7925.             } else if (r == 2) {
  7926.               printf ("----%04X", i & 0x0000ffff);
  7927.             } else {
  7928.               printf ("------%02X", i & 0x000000ff);
  7929.             }
  7930.           }
  7931.         }
  7932.       }
  7933.       printf ("\n");
  7934.     } else if (code == 'R') {
  7935.       printf (": record\n");
  7936.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7937.       physAddr = translate (fp+offset, 1, 0, 0);
  7938.       if (translateCausedException) {
  7939.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7940.       } else {
  7941.         i = getPhysicalWord (physAddr);
  7942.         printf ("%08X\n", i);
  7943.         for (j = 4; j< sizeInBytes; j=j+4) {
  7944.           physAddr = translate (fp+offset+j, 1, 0, 0);
  7945.           if (translateCausedException) {
  7946.             printf ("*****  MEMORY EXCEPTION  *****\n");
  7947.           } else {
  7948.             i = getPhysicalWord (physAddr);
  7949.             printf ("        %4d   %08X:  %08X\n", offset+j, fp+offset+j, i);
  7950.           }
  7951.         }
  7952.       }
  7953.     } else if (code == 'O') {
  7954.       printf (": object\n");
  7955.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7956.       physAddr = translate (fp+offset, 1, 0, 0);
  7957.       if (translateCausedException) {
  7958.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7959.       } else {
  7960.         i = getPhysicalWord (physAddr);
  7961.         printf ("%08X    (Dispatch Table is at 0x%08X)\n", i, i);
  7962.         for (j = 4; j< sizeInBytes; j=j+4) {
  7963.           physAddr = translate (fp+offset+j, 1, 0, 0);
  7964.           if (translateCausedException) {
  7965.             printf ("*****  MEMORY EXCEPTION  *****\n");
  7966.           } else {
  7967.             i = getPhysicalWord (physAddr);
  7968.             printf ("        %4d   %08X:  %08X\n", offset+j, fp+offset+j, i);
  7969.           }
  7970.         }
  7971.       }
  7972.     } else if (code == 'A') {
  7973.       printf (": array\n");
  7974.       printf ("        %4d   %08X:  ", offset, fp+offset);
  7975.       physAddr = translate (fp+offset, 1, 0, 0);
  7976.       if (translateCausedException) {
  7977.         printf ("*****  MEMORY EXCEPTION  *****\n");
  7978.       } else {
  7979.         i = getPhysicalWord (physAddr);
  7980.         printf ("%08X    (Number of elts = %d)\n", i, i);
  7981.         for (j = 4; j< sizeInBytes; j=j+4) {
  7982.           physAddr = translate (fp+offset+j, 1, 0, 0);
  7983.           if (translateCausedException) {
  7984.             printf ("*****  MEMORY EXCEPTION  *****\n");
  7985.           } else {
  7986.             i = getPhysicalWord (physAddr);
  7987.             printf ("        %4d   %08X:  %08X\n", offset+j, fp+offset+j, i);
  7988.           }
  7989.         }
  7990.       }
  7991.     } else {
  7992.       printf ("Problems in variable descriptor information in memory (addr = 0x%08X - address exception when accessing data type code)!\n",
  7993.               ptrToVarName);
  7994.       break;
  7995.     }
  7996.  
  7997.     // Increment to next var descriptor...
  7998.     vdAddr = vdAddr + 12;
  7999.     
  8000.   }
  8001.   printf ("=================================================\n");
  8002.  
  8003.   return 1;
  8004.  
  8005. }
  8006.  
  8007.  
  8008.  
  8009.  
  8010. /* printAsciiDataInWidth (ptr, width) --> bool
  8011. **
  8012. ** This routine is passed a pointer to a Null-terminated string of characters
  8013. ** in the BLITZ memory.  It attempts to print it.  The ptr could be anything, so
  8014. ** this routine checks for all conceivable errors.
  8015. **
  8016. ** If everything seemed ok, then return TRUE.  If problems, return FALSE.
  8017. **
  8018. ** If the string is shorter than 'width' characters, it will be padded to that
  8019. ** length with blanks.
  8020. */
  8021. int printAsciiDataInWidth (int ptr, int width) {
  8022.   int physAddr, word, i;
  8023.  
  8024.   while (1) {
  8025.     physAddr = translate (ptr & 0xfffffffc, 1, 0, 0);
  8026.                           // reading=1, wantPrinting=0, doUpdates=0
  8027.     if (translateCausedException) {
  8028.       printf ("\n*****  Problem with stack frame: A debugging string is in error  *****\n");
  8029.       return 0;
  8030.     }
  8031.     word = getPhysicalWord (physAddr);
  8032.     /* Isolate the byte in the word and shift to lower-order 8 bits. */
  8033.     word = word >> (24 - ((ptr & 0x00000003) << 3));
  8034.     word &= 0x000000ff;
  8035.     if (word == 0) {
  8036.       for (i = width; i>0; i--) {
  8037.         printf (" ");
  8038.       }
  8039.       return 1;
  8040.     }
  8041.     if (word >= ' ' && word < 0x7f) {
  8042.       printf ("%c", word);
  8043.       width--;
  8044.     } else {
  8045.       printf ("\n*****  Problem with stack frame: A debugging string is in error  *****\n");
  8046.       return 0;
  8047.     }
  8048.     ptr++;
  8049.   }
  8050. }
  8051.  
  8052.  
  8053.  
  8054. /* commandHex ()
  8055. **
  8056. ** This routine asks for a hex number.  It prints it out in hex, decimal,
  8057. ** and ascii.
  8058. */
  8059. void commandHex () {
  8060.   int value;
  8061.   /* Read in a value. */
  8062.   printf ("Enter a value in hex: ");
  8063.   value = readHexInt ();
  8064.  
  8065.   printHexDecimalAscii (value);
  8066. }
  8067.  
  8068.  
  8069.  
  8070. /* commandDecimal ()
  8071. **
  8072. ** This routine asks for a decimal number.  It prints it out in hex, decimal,
  8073. ** and ascii.
  8074. */
  8075. void commandDecimal () {
  8076.   int value;
  8077.   /* Read in a value. */
  8078.   printf ("Enter a value in decimal: ");
  8079.   value = readDecimalInt ();
  8080.  
  8081.   printHexDecimalAscii (value);
  8082. }
  8083.  
  8084.  
  8085.  
  8086. /* commandAscii ()
  8087. **
  8088. ** This routine asks for a character.  It prints it out in hex, decimal,
  8089. ** and ascii.
  8090. */
  8091. void commandAscii () {
  8092.   int value;
  8093.   /* Read in a value. */
  8094.   printf ("Enter a single character followed by a newline/return: ");
  8095.   fflush (stdout);
  8096.   fgets (inputBuffer, sizeof(inputBuffer), stdin);
  8097.   /* Overwrite the \n with \0 to remove it. */
  8098.   inputBuffer [strlen (inputBuffer)-1] = '\0';
  8099.   if (strlen (inputBuffer) != 1) {
  8100.     printf ("You entered %d characters - Aborted\n", strlen (inputBuffer));
  8101.     return;
  8102.   }
  8103.   printHexDecimalAscii (inputBuffer[0]);
  8104. }
  8105.  
  8106.  
  8107.  
  8108. /* printHexDecimalAscii (i)
  8109. **
  8110. ** This routine prints a number in the form
  8111. **       hex: 0x1234abcd   decimal: 395441741   ascii: "..a."
  8112. ** followed by a newline.
  8113. */
  8114. void printHexDecimalAscii (int i) {
  8115.   char str [100];
  8116.   char c;
  8117.   printf ("     hex: 0x");
  8118.   putlong (i);
  8119.   printf ("     decimal: %d", i);
  8120.   printf ("     ascii: \"");
  8121.   c = (i >> 24) & 0x000000ff;
  8122.   if ((c>=' ') && (c <= '~')) {
  8123.     putchar (c);
  8124.   } else {
  8125.     putchar ('.');
  8126.   }
  8127.   c = (i >> 16) & 0x000000ff;
  8128.   if ((c>=' ') && (c <= '~')) {
  8129.     putchar (c);
  8130.   } else {
  8131.     putchar ('.');
  8132.   }
  8133.   c = (i >> 8) & 0x000000ff;
  8134.   if ((c>=' ') && (c <= '~')) {
  8135.     putchar (c);
  8136.   } else {
  8137.     putchar ('.');
  8138.   }
  8139.   c = i & 0x000000ff;
  8140.   if ((c>=' ') && (c <= '~')) {
  8141.     putchar (c);
  8142.   } else {
  8143.     putchar ('.');
  8144.   }
  8145.   printf ("\"\n");
  8146. }
  8147.  
  8148.  
  8149.  
  8150. /* jumpIfTrueRaRb (cond, instr)
  8151. **
  8152. ** This routine is used in the implementation of the conditional jumping
  8153. ** instructions.  If the condition is true, it updates pc to effect the
  8154. ** jump.  Otherwise, it increments the pc.
  8155. */
  8156. void jumpIfTrueRaRb (int cond, int instr) {
  8157.   int x, y, z;
  8158.   if (cond) {
  8159.     x = getRa (instr);
  8160.     y = getRc (instr);
  8161.     z = x + y;
  8162.     if (z % 4 != 0) {
  8163.       interruptsSignaled |= ALIGNMENT_EXCEPTION;
  8164.       return;
  8165.     }
  8166.     pc = z;
  8167.   } else {
  8168.     pc += 4;
  8169.   }
  8170. }
  8171.  
  8172.  
  8173.  
  8174. /* jumpIfTrueData24 (cond, instr)
  8175. **
  8176. ** This routine is used in the implementation of the conditional jumping
  8177. ** instructions.  If the condition is true, it updates pc to effect the
  8178. ** jump.  Otherwise, it increments the pc.
  8179. */
  8180. void jumpIfTrueData24 (int cond, int instr) {
  8181.   int z;
  8182.   if (cond) {
  8183.     z = getData24 (instr);
  8184.     if (z % 4 != 0) {
  8185.       interruptsSignaled |= ALIGNMENT_EXCEPTION;
  8186.       return;
  8187.     }
  8188.     pc += z;
  8189.   } else {
  8190.     pc += 4;
  8191.   }
  8192. }
  8193.  
  8194.  
  8195.  
  8196. /* controlC (sig)
  8197. **
  8198. ** This routine is called when the user hits control-C.  It sets
  8199. ** "controlCPressed" to TRUE.  In the fetch-increment-execute loop, this
  8200. ** variable is checked before each instruction and execution of BLITZ
  8201. ** instructions is terminated if it is ever found to be true.  The variable
  8202. ** is also reset to false at that time.
  8203. **
  8204. ** If "controlCPressed" was already TRUE when this routine is called,
  8205. ** then it must be that control-C has just been pressed twice in a row, with
  8206. ** the first press not having been "absorbed".  This could be due to a
  8207. ** problem in the emulator itself; perhaps the emulator is stuck in an
  8208. ** infinite loop.  In this case, this routine will abort the emulator.
  8209. */
  8210. void controlC (int sig) {
  8211.   if (sig != SIGINT) {
  8212.     fatalError ("PROGRAM LOGIC ERROR: Expected SIGINT in signal handler");
  8213.   }
  8214.   signal (SIGINT, controlC);
  8215.   printf ("\n*****  Control-C  *****\n");
  8216.   if (controlCPressed) {
  8217.     turnOffTerminal ();
  8218.     fprintf (stderr, "\nBLITZ Emulator quiting\n");
  8219.     /* raise (SIGSEGV);  Produce a core dump. */
  8220.     errorExit ();
  8221.   } else {
  8222.     controlCPressed = 1;
  8223.   }
  8224. }
  8225.  
  8226.  
  8227.  
  8228. /* randomBetween (lo, high)
  8229. **
  8230. ** This routine returns the next random number between the given numbers,
  8231. ** inclusive.
  8232. */
  8233. int randomBetween (int lo, int high) {
  8234.   int gap = high - lo + 1;
  8235.   int i = genRandom () % gap;
  8236.   return lo + i;
  8237. }
  8238.  
  8239.  
  8240.  
  8241. /*
  8242. ** genRandom ()
  8243. **
  8244. ** This routine returns a random number within the range
  8245. ** 1,2,3,... 2147483646  (i.e., 2**31-2) and updates the random seed.
  8246. ** See "Random Number Generators: Good Ones are Hard to Find", by
  8247. ** Stephen K. Parks and Keith W. Miller, CACM 31:10, October 1988.
  8248. */
  8249. int genRandom () {
  8250.  
  8251. #define randomA 16807
  8252. #define randomM 2147483647
  8253. #define randomQ 127773
  8254. #define randomR 2836
  8255.  
  8256.   int lo,hi,test;
  8257.  
  8258.   hi = randomSeed / randomQ;
  8259.   lo = randomSeed % randomQ;
  8260.   test = (randomA * lo) - (randomR * hi);
  8261.   if (test > 0) {
  8262.     randomSeed = test;
  8263.   } else {
  8264.     randomSeed = test + randomM;
  8265.   }
  8266.   return (randomSeed);      /*  to normalize, use random/m */
  8267.  
  8268.  
  8269.  
  8270. /* doTimerEvent ()
  8271. **
  8272. ** This routine is called when a timer event is due.  It will signal and
  8273. ** interrupt and schedule another timer event in the future.
  8274. */
  8275. void doTimerEvent () {
  8276.  
  8277.   /* Set the timeOfNextTimerEvent. */
  8278.   if (TIME_SLICE <= 0) {
  8279.     timeOfNextTimerEvent = MAX;
  8280.   } else {
  8281.     timeOfNextTimerEvent =
  8282.          randomBetween (currentTime + TIME_SLICE,
  8283.                         currentTime + TIME_SLICE + TIME_SLICE_VARIATION);
  8284.     if (timeOfNextTimerEvent <= currentTime) {
  8285.       timeOfNextTimerEvent = currentTime + 1;
  8286.     }
  8287.     /* Signal a timer interrupt. */
  8288.     interruptsSignaled |= TIMER_INTERRUPT;
  8289.   }
  8290. }
  8291.  
  8292.  
  8293.  
  8294. /* doDiskEvent ()
  8295. **
  8296. ** This routine is called when a disk event is due.  It will:
  8297. **    Set the "currentDiskStatus" to "futureDiskStatus,"
  8298. **    Signal a DISK_INTERRUPT, and
  8299. **    Not schedule any future disk events.
  8300. */
  8301. void doDiskEvent () {
  8302.  
  8303.   /* Signal a disk interrupt. */
  8304.   interruptsSignaled |= DISK_INTERRUPT;
  8305.  
  8306.   /* Change the disk status to WAITING. */
  8307.   currentDiskStatus = futureDiskStatus;
  8308.  
  8309.   /* Do not schedule another disk event. */
  8310.   timeOfNextDiskEvent = MAX;
  8311. }
  8312.  
  8313.  
  8314.  
  8315. /* doSerialInEvent (waitForKeystroke)
  8316. **
  8317. ** This routine is called when a serial input event is due.  We need to check
  8318. ** the input and see if we have a new character on the input.  If so, we
  8319. ** need to signal a serial interrupt.  Normally, we do not wait for the user
  8320. ** to type something, but if "waitForKeystroke" is true, we will wait for
  8321. ** at least one keystroke.
  8322. */
  8323. void doSerialInEvent (int waitForKeystroke) {
  8324.   int ch;
  8325.  
  8326.   /* If the last character was never used, report it. */
  8327.   if (!termInCharWasUsed) {
  8328.     termInCharWasUsed = 1;
  8329.     if ((termInChar >= ' ') && (termInChar < 0x7f)) {
  8330.       fprintf (stderr, "\n\rERROR: The serial input character \"%c\" was not fetched in a timely way and has been lost!\n\r",
  8331.              termInChar);
  8332.     } else {
  8333.       fprintf (stderr, "\n\rERROR: The serial input character 0x%02X was not fetched in a timely way and has been lost!\n\r",
  8334.              termInChar);
  8335.     }
  8336.     // controlCPressed = 1;
  8337.     return;
  8338.   }
  8339.  
  8340.   /* See if we have a new key pressed.  If so, signal an interrupt. */
  8341.   ch = checkForInput (waitForKeystroke);
  8342.   if (ch != 0) {
  8343.     termInChar = ch;
  8344.     termInCharWasUsed = 0;
  8345.     termInCharAvail = 1;
  8346.     interruptsSignaled |= SERIAL_INTERRUPT;
  8347.   }
  8348.  
  8349.   /* Figure out when to check the keyboard next. */
  8350.   if (timeOfNextSerialInEvent != MAX) {
  8351.     timeOfNextSerialInEvent =
  8352.         randomBetween (
  8353.            currentTime + KEYBOARD_WAIT_TIME,
  8354.            currentTime + KEYBOARD_WAIT_TIME + KEYBOARD_WAIT_TIME_VARIATION);
  8355.     if (timeOfNextSerialInEvent <= currentTime) {
  8356.       timeOfNextSerialInEvent = currentTime + 1;
  8357.     }
  8358.   }
  8359.  
  8360. }
  8361.  
  8362.  
  8363.  
  8364. /* doSerialOutEvent ()
  8365. **
  8366. ** This routine is called when a serial outout event is due.  If we are
  8367. ** busy sending a character to the terminal, then at this event, we are
  8368. ** done and the terminal is once again ready.  Set the terminal output
  8369. ** status to "output ready" and signal an interrupt.
  8370. */
  8371. void doSerialOutEvent () {
  8372.   if (!termOutputReady) {
  8373.     termOutputReady = 1;
  8374.     interruptsSignaled |= SERIAL_INTERRUPT;
  8375.   }
  8376.   timeOfNextSerialOutEvent = MAX;
  8377. }
  8378.  
  8379.  
  8380.  
  8381. /* updateTimeOfNextEvent ()
  8382. **
  8383. ** This routine sets "timeOfNextEvent".  It looks at the times of all of
  8384. ** the next scheduled events and uses the minimum of all of these.
  8385. */
  8386. void updateTimeOfNextEvent () {
  8387.   timeOfNextEvent = MAX;
  8388.   if (timeOfNextEvent > timeOfNextTimerEvent) {
  8389.     timeOfNextEvent = timeOfNextTimerEvent;
  8390.   }
  8391.   if (timeOfNextEvent > timeOfNextDiskEvent) {
  8392.     timeOfNextEvent = timeOfNextDiskEvent;
  8393.   }
  8394.   if (timeOfNextEvent > timeOfNextSerialInEvent) {
  8395.     timeOfNextEvent = timeOfNextSerialInEvent;
  8396.   }
  8397.   if (timeOfNextEvent > timeOfNextSerialOutEvent) {
  8398.     timeOfNextEvent = timeOfNextSerialOutEvent;
  8399.   }
  8400. }
  8401.  
  8402.  
  8403.  
  8404. /* divide (a, b)
  8405. **
  8406. ** This routine is passed two integers ("a" and "b").  It divides a by b
  8407. ** to get a quotient ("q") and remainder ("r"), such that
  8408. **
  8409. **       a = b*q + r
  8410. **
  8411. ** Furthermore, the remainder follows the mathematical definition of the
  8412. ** "modulo" operator, namely that the remainder will have the same sign
  8413. ** as b and that
  8414. **
  8415. **       0 <= abs(r) < abs(b)
  8416. **
  8417. ** Another way to look at this is that the quotient is the real quotient,
  8418. ** rounded down to the nearest integer.
  8419. **
  8420. ** For example:
  8421. **
  8422. **       a   b     q   r     a =  b *  q +  r     a/b   rounded
  8423. **      ==  ==    ==  ==    =================    ====   =======
  8424. **       7   3     2   1     7 =  3 *  2 +  1     2.3      2
  8425. **      -7   3    -3   2    -7 =  3 * -3 +  2    -2.3     -3
  8426. **       7  -3    -3  -2     7 = -3 * -3 + -2    -2.3     -3
  8427. **      -7  -3     2  -1    -7 = -3 *  2 + -1     2.3      2
  8428. **
  8429. ** This routine modifies global variables "q" and "r".  If b=0 it
  8430. ** sets q and r to zero and returns immediately.
  8431. **
  8432. ** With this definition of "q" and "r", overflow can and will occur in only
  8433. ** one situation.  Assuming that we are using 32-bit signed integers, the
  8434. ** following inputs cause a problem...
  8435. **      a = -2147483648
  8436. **      b = -1
  8437. ** The mathematically correct answer is...
  8438. **      q = +2147483648
  8439. **      r = 0
  8440. ** Unfortunately, this value of q is not representable.  The underlying
  8441. ** implementation of the C operators / and % will normally fail, and will
  8442. ** quietly return the wrong answer...
  8443. **      q = -2147483648
  8444. **      r = 0
  8445. ** This routine will simply return these incorrect values.
  8446. **
  8447. ** The C language does not define the / and % operators precisely, but
  8448. ** only requires that a = b*q + r be true.  This routine is designed to
  8449. ** return consistent, "correct" answers, regardless of the underlying
  8450. ** implementation of / and %.
  8451. **
  8452. ** Typical variations in integer division are...
  8453. **
  8454. ** (1) "r" is always non-negative.  0 <= r < abs(b)
  8455. **     "q" will be negative when either a or b (but not both) are negative.
  8456. **         a   b     q   r     a =  b *  q +  r
  8457. **        ==  ==    ==  ==    =================
  8458. **         7   3     2   1     7 =  3 *  2 +  1
  8459. **        -7   3    -3   2    -7 =  3 * -3 +  2
  8460. **         7  -3    -2   1     7 = -3 * -2 +  1
  8461. **        -7  -3     3   2    -7 = -3 *  3 +  2
  8462. **
  8463. ** (2) Real division, rounded toward zero.
  8464. **     "q" = a/b, rounded toward zero.
  8465. **     "q" will be negative when either a or b (but not both) are negative.
  8466. **     The sign of "r" will be the same as the sign of "a".
  8467. **         a   b     q   r     a =  b *  q +  r     a/b   rounded
  8468. **        ==  ==    ==  ==    =================    ====   =======
  8469. **         7   3     2   1     7 =  3 *  2 +  1     2.3      2
  8470. **        -7   3    -2  -1    -7 =  3 * -2 + -1    -2.3     -2
  8471. **         7  -3    -2   1     7 = -3 * -2 +  1    -2.3     -2
  8472. **        -7  -3     2  -1    -7 = -3 *  2 + -1     2.3      2
  8473. **
  8474. ** (3) Real division, rounded toward negative infinity.
  8475. **     "q" = a/b, rounded toward negative infinity.
  8476. **     This results in "r" being the mathematically correct "modulo".
  8477. **     "q" will be negative when either a or b (but not both) are negative.
  8478. **     "r" will be negative whenever "b" is negative.
  8479. **
  8480. ** This routine implements option number (3).  It works assuming that
  8481. ** the underlying C implementation uses options (1), (2), or (3).
  8482. **
  8483. ** Overflow cannot occur in this routine, assuming 2's complement
  8484. ** representation of integers.
  8485. */
  8486. void divide (int a, int b) {
  8487.   if (b==0) {
  8488.     q = r = 0;
  8489.     return;
  8490.   }
  8491.   q = a/b;
  8492.   r = a%b;
  8493.   if (b>0) {
  8494.     if (r<0) {
  8495.       q--;        /* Overflow iff q=MIN; but then b=1 and r=0... can't be. */
  8496.       r = r + b;  /* r is neg, b is pos; cannot overflow. */
  8497.     }
  8498.   } else {
  8499.     if (r>0) {
  8500.       q--;        /* Overflow iff q=MIN; but then b=1 and r=0... can't be. */
  8501.       r = r + b;  /* r is pos, b is neg; cannot overflow. */
  8502.     }
  8503.   }
  8504. }
  8505.  
  8506.  
  8507.  
  8508. /* turnOnTerminal ()
  8509. **
  8510. ** This routine is called before BLITZ instruction execution begins.
  8511. ** Terminal input may come from "stdin", which is normally used by
  8512. ** the emulator itself.  If input is coming from stdin, this routine
  8513. ** sets up the terminal by turning off buffering and echoing, so that
  8514. ** it will behave like an "ideal BLITZ terminal".  If input is coming
  8515. ** from a file, then this routine does nothing.
  8516. **
  8517. ** NOTE: We assume that the Emulator is running under Unix and that the
  8518. ** terminal is normally running with "stty -raw echo".
  8519. */
  8520. void turnOnTerminal () {
  8521.   if (termInputFile == stdin) {
  8522.     clearerr (stdin);  /* clear previous control-D/EOFs */
  8523.     if (terminalWantRawProcessing) {
  8524.       terminalInRawMode = 1;
  8525.       system ("stty raw -echo");
  8526.     }
  8527.   }
  8528. }
  8529.  
  8530.  
  8531.  
  8532. /* turnOffTerminal ()
  8533. **
  8534. ** This routine is called when execution of BLITZ instructions is complete.
  8535. ** If the terminal was in raw mode, it restores it so that it will
  8536. ** behave normally.
  8537. */
  8538. void turnOffTerminal () {
  8539.  
  8540.   if (terminalInRawMode) {
  8541.     /* Change back to cooked mode */
  8542.     terminalInRawMode = 0;
  8543.     system ("stty -raw echo");
  8544.   }
  8545.   /* Clear any pending characters... */
  8546.   fseek (stdin, 0l, SEEK_SET);
  8547.   clearerr (stdin);  /* clear previous control-D/EOFs */
  8548. }
  8549.  
  8550.  
  8551.  
  8552. /* checkForInput (waitForKeystroke) -> char
  8553. **
  8554. ** This routine checks to see if a character has appeared on the input.
  8555. ** If so, it returns the character.  If "waitForKeystroke" is true, this
  8556. ** routine will wait for a keystroke; otherwise it will return 0 without
  8557. ** waiting.  
  8558. **
  8559. ** If the input is coming from stdin, this routine checks to see if the
  8560. ** input character happens to be control-C; if so, it is processed
  8561. ** immediately (by setting a flag) and zero is returned.
  8562. **
  8563. ** If we have characters buffered in the type-ahead buffer, then these
  8564. ** are used before getting characters from stdin.  The characters may also
  8565. ** be coming from a file besides stdin.
  8566. */
  8567. char checkForInput (int waitForKeystroke) {
  8568.   int i, j;
  8569.   char ch, other;
  8570. #define TERM_BUFF_SIZE 1
  8571.   char terminalBuffer [TERM_BUFF_SIZE];
  8572.  
  8573.   /* Print the current typeAheadBuffer... */
  8574.   //  printf ("  typeAheadBuffer = ");
  8575.   //  printTypeAheadBuffer ();
  8576.  
  8577.   /* See if input comes from stdin and we have something in the type-ahead
  8578.      buffer... */
  8579.   if (typeAheadBufferCount > 0) {
  8580.     ch = typeAheadBuffer [typeAheadBufferOut++];
  8581.     if (typeAheadBufferOut >= TYPE_AHEAD_BUFFER_SIZE) {
  8582.       typeAheadBufferOut = 0;
  8583.     }
  8584.     typeAheadBufferCount--;
  8585.     return ch;
  8586.   }
  8587.  
  8588.   /* Return immediately if input=stdin & we don't want to wait & no char is avail. */
  8589.   if (termInputFile == stdin) {
  8590.     if (!waitForKeystroke)  {
  8591.       if (!characterAvailableOnStdin ()) {
  8592.         // printf ("  returning(stdin,noWait,nothingReady) \"\\0\"...\n");
  8593.         return 0;
  8594.       }
  8595.     }
  8596.   }
  8597.  
  8598.   if (feof (termInputFile)) {
  8599.     if (termInputFile == stdin) {
  8600.       printf ("\n\r*****  EOF on input ignored: Use Control-C to halt execution  *****\n\r");
  8601.       fseek (stdin, 0l, SEEK_SET);
  8602.       return 0;
  8603.     } else {
  8604.       if (waitForKeystroke) {
  8605.         printf ("\n\r*****  EOF encountered on input  *****\n\r");
  8606.         controlCPressed = 1;
  8607.         return 0;
  8608.       } else {
  8609.         /* No further input is available... */
  8610.         timeOfNextSerialInEvent = MAX;
  8611.         return 0;
  8612.       }
  8613.     }
  8614.   }
  8615.  
  8616.   i = fread (terminalBuffer, 1, 1 /*TERM_BUFF_SIZE*/, termInputFile);
  8617.  
  8618.   if (feof (termInputFile) && termInputFile == stdin) {
  8619.     printf ("\n\r*****  EOF on input ignored: Use Control-C to halt execution  *****\n\r");
  8620.     fseek (stdin, 0l, SEEK_SET);
  8621.     return 0;
  8622.   }
  8623.  
  8624.   if (i >= 1) {
  8625.     ch = terminalBuffer [0];
  8626.   } else {
  8627.     return 0;
  8628.   }
  8629.  
  8630.   /* If not in raw mode, then put the remaining characters on this line
  8631.      into the typeAheadBuffer. */
  8632.   if (!terminalInRawMode && ch != '\n') {
  8633.     while (1) {
  8634.       i = fread (terminalBuffer, 1, 1 /*TERM_BUFF_SIZE*/, termInputFile);
  8635.       if (i == 0) break;
  8636.       other = terminalBuffer [0];
  8637.       /* printf ("    Adding 0x%02X to buffer\n", other); */
  8638.       addToTypeAhead (other);
  8639.       if (other == '\n')  break;
  8640.     }
  8641.   }
  8642.  
  8643.   if (termInputFile == stdin) {
  8644.     if (ch == 3) {   /* if ch = Control-C... */
  8645.       printf ("\n\r*****  Control-C  *****\n\r");  /* raw mode: use \n\r... */
  8646.       controlCPressed = 1;
  8647.       // printf ("  returning (ch == contgrol-C): \"\\0\"...\n");
  8648.       return 0;
  8649.     }
  8650.   }
  8651.  
  8652.   return ch;
  8653. }
  8654.  
  8655.  
  8656.  
  8657. /* characterAvailableOnStdin ()
  8658. **
  8659. ** Return true if there is a character available for reading on stdin,
  8660. ** and return false otherwise.  Do not wait.  This function works by calling
  8661. ** the Unix function "select".  This function requires <fcntl.h>.
  8662. */
  8663. int characterAvailableOnStdin () {
  8664.   int numbits = 32;
  8665.   int rfd = 1;
  8666.   int wfd = 0;
  8667.   int xfd = 0;
  8668.   int retval;
  8669.   struct timeval pollTime;
  8670.   pollTime.tv_sec = 0;
  8671.   pollTime.tv_usec = 0;
  8672.   retval = select (numbits,
  8673.                    (fd_set *) &rfd,
  8674.                    (fd_set *) &wfd,
  8675.                    (fd_set *) &xfd,
  8676.                    &pollTime);
  8677.   if ((retval != 1) && (retval != 0)) {
  8678.     fatalError ("Problems with Unix function select");
  8679.   }
  8680.   return retval;
  8681. }
  8682.  
  8683.  
  8684.  
  8685. /* initializeDisk ()
  8686. **
  8687. ** This routine initializes the disk file and variables associated with the DISK.
  8688. */
  8689. void initializeDisk () {
  8690.   long len;
  8691.   int magic, length;
  8692.  
  8693.   currentDiskSector = 0;
  8694.   currentDiskStatus = OPERATION_COMPLETED_OK;
  8695.   futureDiskStatus = OPERATION_COMPLETED_OK;
  8696.   diskTrackCount = 0;
  8697.   diskSectorCount = 0;
  8698.   diskBufferLow = 0;
  8699.   diskBufferHigh = 0;
  8700.   diskMemoryAddressRegister = 0x00000000;
  8701.   diskSectorNumberRegister = 0x00000000;
  8702.   diskSectorCountRegister = 0x00000000;
  8703.  
  8704.   /* Close the DISK file if open... */
  8705.   if (diskFile != NULL) {
  8706.     fclose (diskFile);
  8707.   }
  8708.  
  8709.   /* Open the DISK file for updating... */
  8710.   diskFile = fopen (diskFileName, "r+");
  8711.   if (diskFile == NULL) {
  8712.     fprintf (stderr,
  8713.              "Error in DISK File: File \"%s\" could not be opened for updating.  Simulated disk I/O has been disabled!\n",
  8714.              diskFileName);
  8715.  
  8716.     return;
  8717.   }
  8718.  
  8719.   /* Get the size of the DISK file... */
  8720.   errno = 0;
  8721.   if (fseek (diskFile, 0l, SEEK_END)) {
  8722.     if (errno) perror ("Error on DISK file");
  8723.     fatalError ("Error during call to fseek");
  8724.   }
  8725.   len = ftell (diskFile);
  8726.  
  8727.   /* Check to see if the file is too big... */
  8728.   if (len > ((long) MAX)) {
  8729.     fprintf (stderr, "The  maximum integer is %d.\n", MAX);
  8730.     fprintf (stderr, "Error in DISK File: The DISK file size exceeds the maximum; You may use the 'format' command to change the file.\n");
  8731.     errno = 0;
  8732.     fclose (diskFile);
  8733.     if (errno) perror ("Error closing DISK file");
  8734.     diskFile = NULL;
  8735.     return;
  8736.   }
  8737.  
  8738.   length = (int) len;
  8739.   /* printf ("The length of the file is %d\n", length); */
  8740.  
  8741.   /* Check for bad file length and abort... */
  8742.   if (length < (SECTORS_PER_TRACK * PAGE_SIZE + 4)) {
  8743.     fprintf (stderr, "The minimum DISK file size is 1 track + 4 bytes (where PageSize = %d bytes and SectorsPerTrack = %d).\n", PAGE_SIZE, SECTORS_PER_TRACK);
  8744.     fprintf (stderr, "Error in DISK File: The DISK file must be large enough for at least 1 track.\n");
  8745.     errno = 0;
  8746.     fclose (diskFile);
  8747.     if (errno) perror ("Error closing DISK file");
  8748.     diskFile = NULL;
  8749.     return;
  8750.   }
  8751.  
  8752.   /* Check for bad file length and abort... */
  8753.   diskSectorCount = (length - 4) / PAGE_SIZE;
  8754.   if (diskSectorCount * PAGE_SIZE + 4 != length) {
  8755.     fprintf (stderr, "PageSize = %d bytes, SectorsPerTrack = %d, DISK file size = %d.\n", PAGE_SIZE, SECTORS_PER_TRACK, length);
  8756.     fprintf (stderr, "Error in DISK File: The DISK file size is not an even number of tracks plus 4 bytes\n");
  8757.     errno = 0;
  8758.     fclose (diskFile);
  8759.     if (errno) perror ("Error closing DISK file");
  8760.     diskFile = NULL;
  8761.     return;
  8762.   }
  8763.  
  8764.   diskTrackCount = diskSectorCount / SECTORS_PER_TRACK;
  8765.   /* printf ("diskSectorCount = %d\n", diskSectorCount); */
  8766.   /* printf ("diskTrackCount = %d\n", diskTrackCount); */
  8767.  
  8768.   /* Reposition the DISK file to the beginning. */
  8769.   errno = 0;
  8770.   if (fseek (diskFile, 0l, SEEK_SET)) {
  8771.     if (errno) perror ("Error on DISK file");
  8772.     fclose (diskFile);
  8773.     diskFile = NULL;
  8774.     return;
  8775.   }
  8776.  
  8777.   /* Check the magic number. */
  8778.   magic = readInteger (diskFile);
  8779.   if (magic != 0x424C5A64) {
  8780.     fprintf (stderr, "Error in DISK File: Magic number is not 'BLZd'\n");
  8781.     errno = 0;
  8782.     fclose (diskFile);
  8783.     if (errno) perror ("Error closing DISK file");
  8784.     diskFile = NULL;
  8785.     return;
  8786.   }
  8787.  
  8788. }
  8789.  
  8790.  
  8791.  
  8792. /* performDiskIO (command)
  8793. **
  8794. ** This routine is called whenever the program writes into the DISK_COMMAND_WORD.
  8795. ** It will determine the what operation is called for and perform all error
  8796. ** checking.  It will then perform the actual operation, reading from or writing to
  8797. ** the DISK file.  Finally, it will determine what outcome to simulate (e.g., 
  8798. ** OPERATION_COMPLETED_OK, OPERATION_COMPLETED_WITH_ERROR_3, etc).  It will
  8799. ** schedule an event in the future.  At that future event, an interrupt will occur
  8800. ** and the disk status will then change.
  8801. */
  8802. void performDiskIO (int command) {
  8803.   int seekTime, accessTime, futureTime, currentAngle, desiredAngle, angleChange, transferTime;
  8804.  
  8805.   /* Make sure the DISK is working... */
  8806.   if (diskFile == NULL) {
  8807.     fprintf (stderr, "\n\rERROR:  A store into the DISK_COMMAND_WORD has occurred, but the DISK is currently disabled.  (See the \"format\" command.)\n\r");
  8808.     controlCPressed = 1;
  8809.     return;
  8810.   }
  8811.  
  8812.   /* Make sure the command is legal... */
  8813.   if (command == DISK_READ_COMMAND) {
  8814.     // fprintf (stderr, "\n\rNOTE: A disk read command has been initiated...\n\r");
  8815.   } else if (command == DISK_WRITE_COMMAND) {
  8816.     // fprintf (stderr, "\n\rNOTE: A disk write command has been initiated...\n\r");
  8817.   }  else {
  8818.     currentDiskStatus = DISK_BUSY;
  8819.     futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_5;
  8820.     timeOfNextDiskEvent = currentTime+1;
  8821.     updateTimeOfNextEvent ();
  8822.     fprintf (stderr, "\n\rERROR: The program has stored an invalid command into the DISK_COMMAND_WORD.  An interrupt will occur when you proceed!\n\r");
  8823.     controlCPressed = 1;
  8824.     return;
  8825.   }
  8826.  
  8827.   currentDiskStatus = DISK_BUSY;
  8828.  
  8829.   /* Check for ERROR 1... */
  8830.   if (diskMemoryAddressRegister % PAGE_SIZE != 0) {
  8831.     fprintf (stderr, "\n\rDISK ERROR: The DISK_MEMORY_ADDRESS_REGISTER is not page-aligned.  An interrupt will occur when you proceed!\n\r");
  8832.     futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_1;
  8833.     timeOfNextDiskEvent = currentTime+1;
  8834.     updateTimeOfNextEvent ();
  8835.     controlCPressed = 1;
  8836.     return;
  8837.   }
  8838.  
  8839.   /* Make sure the sector count is positive... */
  8840.   if (diskSectorCountRegister <= 0) {
  8841.     fprintf (stderr, "\n\rDISK ERROR: The DISK_SECTOR_COUNT_REGISTER is not positive.  An interrupt will occur when you proceed!\n\r");
  8842.     futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_1;
  8843.     timeOfNextDiskEvent = currentTime+1;
  8844.     updateTimeOfNextEvent ();
  8845.     controlCPressed = 1;
  8846.     return;
  8847.   }
  8848.  
  8849.   /* Compute the area of memory affected... */
  8850.   diskBufferLow = diskMemoryAddressRegister;
  8851.   diskBufferHigh = diskBufferLow + (diskSectorCountRegister * PAGE_SIZE);
  8852.  
  8853.   /* Make sure the memory buffer is in physical memory... */
  8854.   if (!physicalAddressOk (diskBufferLow) ||
  8855.       !physicalAddressOk (diskBufferHigh-1) ||
  8856.       inMemoryMappedArea (diskBufferLow) ||
  8857.       inMemoryMappedArea (diskBufferHigh-1)) {
  8858.     fprintf (stderr, "\n\rDISK ERROR: The memory buffer is not all in physical memory or is in the memory-mapped region.  An interrupt will occur when you proceed!\n\r");
  8859.     futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_2;
  8860.     timeOfNextDiskEvent = currentTime+1;
  8861.     updateTimeOfNextEvent ();
  8862.     controlCPressed = 1;
  8863.     return;
  8864.   }
  8865.  
  8866.   /* Check that we are accessing legal disk sectors... */
  8867.   if ((diskSectorNumberRegister < 0) ||
  8868.       (diskSectorNumberRegister + diskSectorCountRegister > diskSectorCount)) {
  8869.     fprintf (stderr, "\n\rDISK ERROR: Attempting to read sectors that do not exist on the disk.  An interrupt will occur when you proceed!\n\r");
  8870.     futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_3;
  8871.     timeOfNextDiskEvent = currentTime+1;
  8872.     updateTimeOfNextEvent ();
  8873.     controlCPressed = 1;
  8874.     return;
  8875.   }
  8876.  
  8877.   /* See if we need to simulate a random disk I/O error... */
  8878.   if (command == DISK_READ_COMMAND) {
  8879.     if (DISK_READ_ERROR_PROBABILITY > 0) {
  8880.       if (1 == randomBetween (1, DISK_READ_ERROR_PROBABILITY)) {
  8881.         /***
  8882.         fprintf (stderr, "\n\rDISK ERROR: A random disk read error will be simulated at this time.  An interrupt will occur when you proceed!\n\r");
  8883.         controlCPressed = 1;
  8884.         ***/
  8885.         futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_4;
  8886.         timeOfNextDiskEvent = currentTime+1;
  8887.         updateTimeOfNextEvent ();
  8888.         return;
  8889.       }
  8890.     }
  8891.   } else if (command == DISK_WRITE_COMMAND) {
  8892.     if (DISK_WRITE_ERROR_PROBABILITY > 0) {
  8893.       if (1 == randomBetween (1, DISK_WRITE_ERROR_PROBABILITY)) {
  8894.         /***
  8895.         fprintf (stderr, "\n\rDISK ERROR: A random disk write error will be simulated at this time.  An interrupt will occur when you proceed!\n\r");
  8896.         controlCPressed = 1;
  8897.         ***/
  8898.         futureDiskStatus = OPERATION_COMPLETED_WITH_ERROR_4;
  8899.         timeOfNextDiskEvent = currentTime+1;
  8900.         updateTimeOfNextEvent ();
  8901.         return;
  8902.       }
  8903.     }
  8904.   }
  8905.  
  8906.   /* Everything looks good for a normal read... */
  8907.   futureDiskStatus = OPERATION_COMPLETED_OK;
  8908.  
  8909.   /* Compute a realistic delay... */
  8910.   // printf ("    Current sector = %d\n", currentDiskSector);
  8911.   // printf ("    Future sector = %d\n", diskSectorNumberRegister);
  8912.   // printf ("    Current track = %d\n", currentDiskSector / SECTORS_PER_TRACK);
  8913.   // printf ("    Future track = %d\n", diskSectorNumberRegister / SECTORS_PER_TRACK);
  8914.   accessTime = DISK_SEEK_TIME * abs (
  8915.                 diskSectorNumberRegister / SECTORS_PER_TRACK -
  8916.                 currentDiskSector / SECTORS_PER_TRACK);
  8917.   // printf ("    Seek time = %d\n", accessTime);
  8918.   if (accessTime) {
  8919.     accessTime = accessTime + DISK_SETTLE_TIME;
  8920.   }
  8921.   // printf ("    Access time = %d\n", accessTime);
  8922.   // printf ("    Current time before seek,settle = %d\n", currentTime);
  8923.   futureTime = currentTime + accessTime;
  8924.   // printf ("    Time after seek,settle = %d\n", futureTime);
  8925.   currentAngle = (futureTime / DISK_ROTATIONAL_DELAY) % SECTORS_PER_TRACK; 
  8926.   // printf ("    Rotational Angle (0..15) at that time = %d\n", currentAngle);
  8927.   desiredAngle = diskSectorNumberRegister % SECTORS_PER_TRACK;
  8928.   // printf ("    Desired Angle (0..15) = %d\n", desiredAngle);
  8929.   angleChange = desiredAngle - currentAngle;
  8930.   if (angleChange < 0) {
  8931.     angleChange = angleChange + SECTORS_PER_TRACK;
  8932.   }
  8933.   // printf ("    Angle Change (0..15) = %d\n", angleChange);
  8934.   futureTime = futureTime + angleChange * DISK_ROTATIONAL_DELAY;
  8935.   // printf ("    Time after seek,settle,rotate = %d\n", futureTime);
  8936.   // printf ("    Number of sectors transfered = %d\n", diskSectorCountRegister);
  8937.   transferTime = diskSectorCountRegister * DISK_ROTATIONAL_DELAY;
  8938.   // printf ("    Transfer time = %d\n", transferTime);
  8939.   futureTime = futureTime + transferTime;
  8940.   // printf ("    Time after seek,settle,rotate,transfer = %d\n", futureTime);
  8941.   futureTime = randomBetween (futureTime, futureTime + DISK_ACCESS_VARIATION);
  8942.   // printf ("    Time after seek,settle,rotate,transfer,random = %d\n", futureTime);
  8943.  
  8944.   // Set up the next disk event, based on the computed time of completion...
  8945.   if (futureTime <= currentTime) {
  8946.     timeOfNextDiskEvent = currentTime + 1;
  8947.   } else {
  8948.     timeOfNextDiskEvent = futureTime;
  8949.   }
  8950.   updateTimeOfNextEvent ();
  8951.  
  8952.   /* Set the new Current Disk Position... */
  8953.   currentDiskSector = diskSectorNumberRegister + diskSectorCountRegister;
  8954.  
  8955.   /* Seek to the proper location in the file... */
  8956.   errno = 0;
  8957.   if (fseek (diskFile, ((long) ((diskSectorNumberRegister * PAGE_SIZE) + 4)), SEEK_SET)) {
  8958.     fprintf (stderr, "\n\rError from host OS during DISK read/fseek; Disk I/O has been disabled!\n\r");
  8959.     if (errno) perror ("Host error");
  8960.     fclose (diskFile);
  8961.     diskFile = NULL;
  8962.     controlCPressed = 1;
  8963.     return;
  8964.   }
  8965.  
  8966.   if (command == DISK_READ_COMMAND) {
  8967.  
  8968.     numberOfDiskReads++;
  8969.  
  8970.     /* Read in N sectors of data... */
  8971.     errno = 0;
  8972.     fread ( (void *) (((int) memory) + diskBufferLow),
  8973.             PAGE_SIZE, diskSectorCountRegister, diskFile );
  8974.     if (errno) {
  8975.       fprintf (stderr, "\n\rError from host OS during DISK read; Disk I/O has been disabled!\n\r");
  8976.       if (errno) perror ("Host error");
  8977.       fclose (diskFile);
  8978.       diskFile = NULL;
  8979.       controlCPressed = 1;
  8980.       return;
  8981.     }
  8982.     return;
  8983.  
  8984.   } else if (command == DISK_WRITE_COMMAND) {
  8985.  
  8986.     numberOfDiskWrites++;
  8987.  
  8988.     /* Write in N sectors of data... */
  8989.     errno = 0;
  8990.     fwrite ( (void *) (((int) memory) + diskBufferLow),
  8991.             PAGE_SIZE, diskSectorCountRegister, diskFile );
  8992.     if (errno) {
  8993.       fprintf (stderr, "\n\rError from host OS during DISK write; Disk I/O has been disabled!\n\r");
  8994.       if (errno) perror ("Host error");
  8995.       fclose (diskFile);
  8996.       diskFile = NULL;
  8997.       controlCPressed = 1;
  8998.       return;
  8999.     }
  9000.     return;
  9001.   }
  9002. }
  9003.  
  9004.  
  9005.  
  9006. /* checkDiskBufferError (physAddr)
  9007. **
  9008. ** This routine checks the address to see if it is within the memory that is being used
  9009. ** for a disk operation.  If it is, then a message is printed and execution is halted.
  9010. */
  9011. void checkDiskBufferError (int physAddr) {
  9012.   if (currentDiskStatus == DISK_BUSY && physAddr >= diskBufferLow && physAddr < diskBufferHigh) {
  9013.     fprintf (stderr, "\n\rMEMORY ACCESS ERROR: The BLITZ program has attempted to read or write a memory word that is currently involved in a disk read or write operation!\n\r");
  9014.     controlCPressed = 1;
  9015.   }
  9016. }
  9017.  
  9018.  
  9019.  
  9020.  
  9021. /* setSimulationConstants ()
  9022. **
  9023. ** This routine initializes some important constants related to the simulation.
  9024. ** It gets values from the ".blitzrc" file if it exists, or uses defaults, if not.
  9025. */
  9026. void setSimulationConstants () {
  9027.   int i, errorInValue;
  9028.   FILE * blitzrc;
  9029.   char * first, * second, * p;
  9030.     errorInValue = 0;
  9031.  
  9032.     defaultSimulationConstants ();
  9033.  
  9034.     // Try to open the ".blitzrc" file...
  9035.     blitzrc = fopen (".blitzrc", "r");
  9036.     if (blitzrc != NULL) {
  9037.       // printf ("Reading simulation values from file \".blitzrc\"...\n");
  9038.  
  9039.       while (! feof (blitzrc)) {
  9040.         fgets (inputBuffer, sizeof(inputBuffer), blitzrc);
  9041.  
  9042.         if (feof (blitzrc)) break;
  9043.  
  9044.         /* Ignore comments... */
  9045.         if (inputBuffer[0] == '!') continue;
  9046.  
  9047.         /* Overwrite the \n with \0 to remove it. */
  9048.         inputBuffer [strlen (inputBuffer)-1] = '\0';
  9049.         // printf ("LINE >>>%s<<<\n", inputBuffer);
  9050.  
  9051.         /* Set "first" to point to the first non-whitespace character. */
  9052.         first = inputBuffer;
  9053.         while (1) {
  9054.           if ((*first != ' ') && (*first != '\t')) {
  9055.             break;
  9056.           }
  9057.           first++;
  9058.         }
  9059.  
  9060.         /* Ignore blank lines... */
  9061.         if (*first == '\0') continue;
  9062.  
  9063.         /* Set "p" to point to the next whitespace or \0 character. */
  9064.         p = first;
  9065.         while (1) {
  9066.           if ((*p == ' ') || (*p == '\t') || (*p == '\0')) {
  9067.             break;
  9068.           }
  9069.           p++;
  9070.         }
  9071.  
  9072.         // printf ("  First Token >>>%s<<<\n", first);
  9073.  
  9074.         if (*p == '\0') {
  9075.           fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  The line beginning \"%s\" has no value!\n", first);
  9076.           errorInValue = 1;
  9077.           continue;
  9078.         }
  9079.  
  9080.         *p = '\0';
  9081.         // printf ("  First Token >>>%s<<<\n", first);
  9082.  
  9083.         /* Set "second" to point to the next non-whitespace character. */
  9084.         second = p+1;
  9085.         while (1) {
  9086.           if ((* second != ' ') && (* second != '\t')) {
  9087.             break;
  9088.           }
  9089.           second ++;
  9090.         }
  9091.  
  9092.         /* Set "p" to point to the next whitespace or \0 character. */
  9093.         p = second;
  9094.         while (1) {
  9095.           if ((*p == ' ') || (*p == '\t') || (*p == '\0')) {
  9096.             break;
  9097.           }
  9098.           p++;
  9099.         }
  9100.  
  9101.         if (*p != '\0') {
  9102.           *p = '\0';
  9103.           /* Make sure that there is nothing but whitespace until the \0 character. */
  9104.           p++;
  9105.           while (*p != '\0') {
  9106.             if ((*p != ' ') && (*p != '\t')) {
  9107.               fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  Extraneous characters (\"%s\") on line beginning \"%s\"!\n", p, first);
  9108.               errorInValue = 1;
  9109.               break;
  9110.             }
  9111.             p++;
  9112.           }
  9113.         }
  9114.  
  9115.         if (*second == '\0') {
  9116.           fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  The line beginning \"%s\" has no value!\n", first);
  9117.           errorInValue = 1;
  9118.           continue;
  9119.         }
  9120.  
  9121.         // printf ("  PROCESSING: First Token >>>%s<<<    ", first);
  9122.         // printf ("  Second Token >>>%s<<<\n", second);
  9123.         if (second[0] == '0' &&
  9124.             second[1] == 'x') {
  9125.           second = second + 2;
  9126.           sscanf (second, "%x", &i);
  9127.         } else {
  9128.           sscanf (second, "%d", &i);
  9129.         }
  9130.         // printf ("------- i = 0x%08X (decimal: %d)\n", i, i);
  9131.  
  9132.         if (!strcmp (first, "KEYBOARD_WAIT_TIME")) {
  9133.           if (i < 0) {
  9134.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  KEYBOARD_WAIT_TIME is negative!\n");
  9135.             errorInValue = 1;
  9136.           } else {
  9137.             KEYBOARD_WAIT_TIME = i;
  9138.           }
  9139.         } else if (!strcmp (first, "KEYBOARD_WAIT_TIME_VARIATION")) {
  9140.           if (i < 0) {
  9141.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  KEYBOARD_WAIT_TIME_VARIATION is negative!\n");
  9142.             errorInValue = 1;
  9143.           } else {
  9144.             KEYBOARD_WAIT_TIME_VARIATION = i;
  9145.           }
  9146.         } else if (!strcmp (first, "TERM_OUT_DELAY")) {
  9147.           if (i < 0) {
  9148.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  TERM_OUT_DELAY is negative!\n");
  9149.             errorInValue = 1;
  9150.           } else {
  9151.             TERM_OUT_DELAY = i;
  9152.           }
  9153.         } else if (!strcmp (first, "TERM_OUT_DELAY_VARIATION")) {
  9154.           if (i < 0) {
  9155.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  TERM_OUT_DELAY_VARIATION is negative!\n");
  9156.             errorInValue = 1;
  9157.           } else {
  9158.             TERM_OUT_DELAY_VARIATION = i;
  9159.           }
  9160.         } else if (!strcmp (first, "TIME_SLICE")) {
  9161.           if (i < 0) {
  9162.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  TIME_SLICE is negative!\n");
  9163.             errorInValue = 1;
  9164.           } else {
  9165.             TIME_SLICE = i;
  9166.           }
  9167.         } else if (!strcmp (first, "TIME_SLICE_VARIATION")) {
  9168.           if (i < 0) {
  9169.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  TIME_SLICE_VARIATION is negative!\n");
  9170.             errorInValue = 1;
  9171.           } else {
  9172.             TIME_SLICE_VARIATION = i;
  9173.           }
  9174.         } else if (!strcmp (first, "DISK_SEEK_TIME")) {
  9175.           if (i < 0) {
  9176.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_SEEK_TIME is negative!\n");
  9177.             errorInValue = 1;
  9178.           } else {
  9179.             DISK_SEEK_TIME = i;
  9180.           }
  9181.         } else if (!strcmp (first, "DISK_SETTLE_TIME")) {
  9182.           if (i < 0) {
  9183.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_SETTLE_TIME is negative!\n");
  9184.             errorInValue = 1;
  9185.           } else {
  9186.             DISK_SETTLE_TIME = i;
  9187.           }
  9188.         } else if (!strcmp (first, "DISK_ROTATIONAL_DELAY")) {
  9189.           if (i < 1) {
  9190.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_ROTATIONAL_DELAY must be >= 1!\n");
  9191.             errorInValue = 1;
  9192.           } else {
  9193.             DISK_ROTATIONAL_DELAY = i;
  9194.           }
  9195.         } else if (!strcmp (first, "DISK_ACCESS_VARIATION")) {
  9196.           if (i < 0) {
  9197.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_ACCESS_VARIATION is negative!\n");
  9198.             errorInValue = 1;
  9199.           } else {
  9200.             DISK_ACCESS_VARIATION = i;
  9201.           }
  9202.         } else if (!strcmp (first, "DISK_READ_ERROR_PROBABILITY")) {
  9203.           if (i < 0) {
  9204.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_READ_ERROR_PROBABILITY is negative!\n");
  9205.             errorInValue = 1;
  9206.           } else {
  9207.             DISK_READ_ERROR_PROBABILITY = i;
  9208.           }
  9209.         } else if (!strcmp (first, "DISK_WRITE_ERROR_PROBABILITY")) {
  9210.           if (i < 0) {
  9211.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_WRITE_ERROR_PROBABILITY is negative!\n");
  9212.             errorInValue = 1;
  9213.           } else {
  9214.             DISK_WRITE_ERROR_PROBABILITY = i;
  9215.           }
  9216.         } else if (!strcmp (first, "INIT_RANDOM_SEED")) {
  9217.           if (i <= 0) {
  9218.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  INIT_RANDOM_SEED is <= 0!\n");
  9219.             errorInValue = 1;
  9220.           } else if (i > 2147483646) {
  9221.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  INIT_RANDOM_SEED is > 2147483646!\n");
  9222.             errorInValue = 1;
  9223.           } else {
  9224.             INIT_RANDOM_SEED = i;
  9225.           }
  9226.         } else if (!strcmp (first, "MEMORY_SIZE")) {
  9227.           /* Check that the MEMORY_SIZE is a multiple of PAGE_SIZE. */
  9228.           if (i % PAGE_SIZE != 0 || i <= 0) {
  9229.             fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  Memory size is not a multiple of page size!\n");
  9230.             errorInValue = 1;
  9231.           } else {
  9232.             MEMORY_SIZE = i;
  9233.           }
  9234.         } else if (!strcmp (first, "MEMORY_MAPPED_AREA_LOW")) {
  9235.           MEMORY_MAPPED_AREA_LOW = i;
  9236.         } else if (!strcmp (first, "MEMORY_MAPPED_AREA_HIGH")) {
  9237.           MEMORY_MAPPED_AREA_HIGH = i;
  9238.         } else if (!strcmp (first, "SERIAL_STATUS_WORD_ADDRESS")) {
  9239.           SERIAL_STATUS_WORD_ADDRESS = i;
  9240.         } else if (!strcmp (first, "SERIAL_DATA_WORD_ADDRESS")) {
  9241.           SERIAL_DATA_WORD_ADDRESS = i;
  9242.         } else if (!strcmp (first, "DISK_STATUS_WORD_ADDRESS")) {
  9243.           DISK_STATUS_WORD_ADDRESS = i;
  9244.         } else if (!strcmp (first, "DISK_COMMAND_WORD_ADDRESS")) {
  9245.           DISK_COMMAND_WORD_ADDRESS = i;
  9246.         } else if (!strcmp (first, "DISK_MEMORY_ADDRESS_REGISTER")) {
  9247.           DISK_MEMORY_ADDRESS_REGISTER = i;
  9248.         } else if (!strcmp (first, "DISK_SECTOR_NUMBER_REGISTER")) {
  9249.           DISK_SECTOR_NUMBER_REGISTER = i;
  9250.         } else if (!strcmp (first, "DISK_SECTOR_COUNT_REGISTER")) {
  9251.           DISK_SECTOR_COUNT_REGISTER = i;
  9252.         } else {
  9253.           fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  An attempt to set non-existent value \"%s\"!\n", first);
  9254.           errorInValue = 1;
  9255.         }
  9256.  
  9257.       }
  9258.  
  9259.       if (MEMORY_MAPPED_AREA_LOW < 0 ||
  9260.           MEMORY_MAPPED_AREA_HIGH >= MEMORY_SIZE ||
  9261.           MEMORY_MAPPED_AREA_LOW >= MEMORY_MAPPED_AREA_HIGH ||
  9262.           MEMORY_MAPPED_AREA_LOW % 4 != 0 ||
  9263.           (MEMORY_MAPPED_AREA_HIGH+1) % 4 != 0) {
  9264.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  MEMORY_MAPPED_AREA_HIGH or MEMORY_MAPPED_AREA_LOW are invalid!\n");
  9265.         errorInValue = 1;
  9266.       }
  9267.       if (SERIAL_STATUS_WORD_ADDRESS < MEMORY_MAPPED_AREA_LOW ||
  9268.           SERIAL_STATUS_WORD_ADDRESS > MEMORY_MAPPED_AREA_HIGH ||
  9269.           SERIAL_STATUS_WORD_ADDRESS % 4 != 0) {
  9270.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  SERIAL_STATUS_WORD_ADDRESS is not within the Memory Mapped Area or is not word-aligned!\n");
  9271.         errorInValue = 1;
  9272.       }
  9273.       if (SERIAL_DATA_WORD_ADDRESS < MEMORY_MAPPED_AREA_LOW ||
  9274.           SERIAL_DATA_WORD_ADDRESS > MEMORY_MAPPED_AREA_HIGH ||
  9275.           SERIAL_DATA_WORD_ADDRESS % 4 != 0) {
  9276.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  SERIAL_DATA_WORD_ADDRESS is not within the Memory Mapped Area or is not word-aligned!\n");
  9277.         errorInValue = 1;
  9278.       }
  9279.       if (DISK_STATUS_WORD_ADDRESS < MEMORY_MAPPED_AREA_LOW ||
  9280.           DISK_STATUS_WORD_ADDRESS > MEMORY_MAPPED_AREA_HIGH ||
  9281.           DISK_STATUS_WORD_ADDRESS % 4 != 0) {
  9282.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_STATUS_WORD_ADDRESS is not within the Memory Mapped Area or is not word-aligned!\n");
  9283.         errorInValue = 1;
  9284.       }
  9285.       if (DISK_COMMAND_WORD_ADDRESS < MEMORY_MAPPED_AREA_LOW ||
  9286.           DISK_COMMAND_WORD_ADDRESS > MEMORY_MAPPED_AREA_HIGH ||
  9287.           DISK_COMMAND_WORD_ADDRESS % 4 != 0) {
  9288.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_COMMAND_WORD_ADDRESS is not within the Memory Mapped Area or is not word-aligned!\n");
  9289.         errorInValue = 1;
  9290.       }
  9291.       if (DISK_MEMORY_ADDRESS_REGISTER < MEMORY_MAPPED_AREA_LOW ||
  9292.           DISK_MEMORY_ADDRESS_REGISTER > MEMORY_MAPPED_AREA_HIGH ||
  9293.           DISK_MEMORY_ADDRESS_REGISTER % 4 != 0) {
  9294.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_MEMORY_ADDRESS_REGISTER is not within the Memory Mapped Area or is not word-aligned!\n");
  9295.         errorInValue = 1;
  9296.       }
  9297.       if (DISK_SECTOR_NUMBER_REGISTER < MEMORY_MAPPED_AREA_LOW ||
  9298.           DISK_SECTOR_NUMBER_REGISTER > MEMORY_MAPPED_AREA_HIGH ||
  9299.           DISK_SECTOR_NUMBER_REGISTER % 4 != 0) {
  9300.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_SECTOR_NUMBER_REGISTER is not within the Memory Mapped Area or is not word-aligned!\n");
  9301.         errorInValue = 1;
  9302.       }
  9303.       if (DISK_SECTOR_COUNT_REGISTER < MEMORY_MAPPED_AREA_LOW ||
  9304.           DISK_SECTOR_COUNT_REGISTER > MEMORY_MAPPED_AREA_HIGH ||
  9305.           DISK_SECTOR_COUNT_REGISTER % 4 != 0) {
  9306.         fprintf (stderr, "\n*****  ERROR in \".blitzrc\" file:  DISK_SECTOR_COUNT_REGISTER is not within the Memory Mapped Area or is not word-aligned!\n");
  9307.         errorInValue = 1;
  9308.       }
  9309.  
  9310.       if (errorInValue) {
  9311.         fprintf (stderr, "*****  ERROR in \".blitzrc\" file:  All values in the file have been ignored.\n");
  9312.         defaultSimulationConstants ();
  9313.       }
  9314.  
  9315.       fclose (blitzrc);
  9316.     }
  9317. }
  9318.  
  9319.  
  9320.  
  9321. /* defaultSimulationConstants ()
  9322. **
  9323. ** This routine sets the simulation constants to their default values.
  9324. */
  9325. void defaultSimulationConstants () {
  9326.     KEYBOARD_WAIT_TIME =                 30000;
  9327.     KEYBOARD_WAIT_TIME_VARIATION =         100;
  9328.     TERM_OUT_DELAY =                       100;
  9329.     TERM_OUT_DELAY_VARIATION =              10;
  9330.     TIME_SLICE =                          5000;
  9331.     TIME_SLICE_VARIATION =                  30;
  9332.     DISK_SEEK_TIME =                     10000;
  9333.     DISK_SETTLE_TIME =                    1000;
  9334.     DISK_ROTATIONAL_DELAY =                100;
  9335.     DISK_ACCESS_VARIATION =                 10;
  9336.     DISK_READ_ERROR_PROBABILITY =          500;  // 0=never, 1=always, n="about 1/n"
  9337.     DISK_WRITE_ERROR_PROBABILITY =         500;  // 0=never, 1=always, n="about 1/n"
  9338.     INIT_RANDOM_SEED =              1829742401;  // Default random seed
  9339.     MEMORY_SIZE =                   0x01000000;  // 16 MBytes
  9340.     MEMORY_MAPPED_AREA_LOW =        0x00ffff00;
  9341.     MEMORY_MAPPED_AREA_HIGH =       0x00ffffff;
  9342.     SERIAL_STATUS_WORD_ADDRESS =    0x00ffff00;
  9343.     SERIAL_DATA_WORD_ADDRESS =      0x00ffff04;
  9344.     DISK_STATUS_WORD_ADDRESS =      0x00ffff08;
  9345.     DISK_COMMAND_WORD_ADDRESS =     0x00ffff08;
  9346.     DISK_MEMORY_ADDRESS_REGISTER =  0x00ffff0c;
  9347.     DISK_SECTOR_NUMBER_REGISTER =   0x00ffff10;
  9348.     DISK_SECTOR_COUNT_REGISTER =    0x00ffff14;
  9349. }
  9350.  
  9351.  
  9352.  
  9353. /* printKPLStmtCode ()
  9354. **
  9355. ** This routine looks at the value in r10 and uses to print the name of
  9356. ** some high-level KPL statement, such as "ASSIGN" or "RETURN".
  9357. */
  9358. void printKPLStmtCode () {
  9359.   int stmtCode;
  9360.   if (statusS) {
  9361.     stmtCode = systemRegisters [10];
  9362.   } else {
  9363.     stmtCode = userRegisters [10];
  9364.   }
  9365.   printf ("About to execute "); 
  9366.   switch (stmtCode) {
  9367.     case '\0\0AS':   printf ("ASSIGN statement                 ");
  9368.                      break;
  9369.     case '\0\0FU':   printf ("FUNCTION ENTRY                   ");
  9370.                      break;
  9371.     case '\0\0ME':   printf ("METHOD ENTRY                     ");
  9372.                      break;
  9373.     case '\0\0IF':   printf ("IF statement                     ");
  9374.                      break;
  9375.     case '\0\0TN':   printf ("THEN statement                   ");
  9376.                      break;
  9377.     case '\0\0EL':   printf ("ELSE statement                   ");
  9378.                      break;
  9379.     case '\0\0CA':   printf ("FUNCTION CALL                    ");
  9380.                      break;
  9381.     case '\0\0CF':   printf ("FUNCTION CALL (via pointer)      ");
  9382.                      break;
  9383.     case '\0\0CE':   printf ("FUNCTION CALL (external function)");
  9384.                      break;
  9385.     case '\0\0SE':   printf ("SEND                             ");
  9386.                      break;
  9387.     case '\0\0WH':   printf ("WHILE LOOP (expr evaluation)     ");
  9388.                      break;
  9389.     case '\0\0WB':   printf ("WHILE LOOP (body statements)     ");
  9390.                      break;
  9391.     case '\0\0DO':   printf ("DO-UNTIL (body statements)       ");
  9392.                      break;
  9393.     case '\0\0DU':   printf ("DO-UNTIL (expr evaluation)       ");
  9394.                      break;
  9395.     case '\0\0BR':   printf ("BREAK statement                  ");
  9396.                      break;
  9397.     case '\0\0CO':   printf ("CONTINUE statement               ");
  9398.                      break;
  9399.     case '\0\0RE':   printf ("RETURN statement                 ");
  9400.                      break;
  9401.     case '\0\0FO':   printf ("FOR statement                    ");
  9402.                      break;
  9403.     case '\0\0FB':   printf ("FOR (body statements)            ");
  9404.                      break;
  9405.     case '\0\0SW':   printf ("SWITCH                           ");
  9406.                      break;
  9407.     case '\0\0TR':   printf ("TRY statement                    ");
  9408.                      break;
  9409.     case '\0\0TH':   printf ("THROW statement                  ");
  9410.                      break;
  9411.     case '\0\0FR':   printf ("FREE statement                   ");
  9412.                      break;
  9413.     case '\0\0DE':   printf ("DEBUG statement                  ");
  9414.                      break;
  9415.     case '\0\0CC':   printf ("CATCH clause                     ");
  9416.                      break;
  9417.     default:         printf ("***INVLALID HIGH-LEVEL STATEMENT CODE IN REGISTER r10***\n");
  9418.                      return;
  9419.   }
  9420.   printCurrentFileLineAndFunction ();
  9421.   printf ("\n");
  9422. }
  9423.  
  9424.  
  9425.  
  9426. /* printCurrentFileLineAndFunction ()
  9427. **
  9428. ** This routine looks at the registers and the current frame and prints
  9429. ** the current file name, the current line number, and the function/method
  9430. ** name like this:
  9431. **        foo (Main.c, line 123)
  9432. ** If any problems, it simply gives up and returns.
  9433. */
  9434. void printCurrentFileLineAndFunction () {
  9435.   int lineNum, fp, physAddr, addrOfRoutineDescriptor, filenamePtr,
  9436.       ptrToFunName;
  9437.  
  9438.   // Get "r13" and "r14/fp"...
  9439.   if (statusS) {
  9440.     lineNum = systemRegisters [13];
  9441.     fp = systemRegisters [14];
  9442.   } else {
  9443.     lineNum = userRegisters [13];
  9444.     fp = userRegisters [14];
  9445.   }
  9446.  
  9447.   if (fp == 0) {
  9448.     printf ("***Invalid FP***\n");
  9449.     return;
  9450.   }
  9451.  
  9452.   // printf ("frame pointer = ");
  9453.   // printNumberNL (fp);
  9454.  
  9455.   // Get ptr to routine descriptor
  9456.   physAddr = translate (fp-8, 1, 0, 0);  // reading=1, wantPrinting=0, doUpdates=0
  9457.   if (translateCausedException) {
  9458.     printf ("***Invalid fp***\n");
  9459.     return;
  9460.   }
  9461.   addrOfRoutineDescriptor = getPhysicalWord (physAddr);
  9462.   // printf ("addrOfRoutineDescriptor = ");
  9463.   // printNumberNL (addrOfRoutineDescriptor);
  9464.  
  9465.   // Get ptr to filename...
  9466.   physAddr = translate (addrOfRoutineDescriptor, 1, 0, 0);
  9467.   if (translateCausedException) {
  9468.     printf ("***Invalid routine descriptor***");
  9469.     return;
  9470.   }
  9471.   filenamePtr = getPhysicalWord (physAddr);
  9472.   // printf ("filenamePtr = ");
  9473.   // printNumberNL (filenamePtr);
  9474.  
  9475.   // Get ptr to function name...
  9476.   physAddr = translate (addrOfRoutineDescriptor+4, 1, 0, 0);
  9477.   if (translateCausedException) {
  9478.     printf ("***Invalid routine descriptor***");
  9479.     return;
  9480.   }
  9481.   ptrToFunName = getPhysicalWord (physAddr);
  9482.   // printf ("ptrToFunName = ");
  9483.   // printNumberNL (ptrToFunName);
  9484.  
  9485.   // Print the function name...
  9486.   printf (" in ");
  9487.   if (!printAsciiDataInWidth (ptrToFunName, 0)) return;
  9488.  
  9489.   // Print the Filename...
  9490.   printf (" (");
  9491.   if (!printAsciiDataInWidth (filenamePtr, 0)) return;
  9492.  
  9493.   // Print the line number...
  9494.   printf (", line %d)", lineNum);
  9495.  
  9496.   // Print the cuurent time...
  9497.   printf ("  time = %d", currentTime);
  9498.  
  9499. }
  9500.