home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / pdp8_sys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-29  |  13.0 KB  |  410 lines

  1. /* pdp8_sys.c: PDP-8 simulator interface
  2.  
  3.    Copyright (c) 1993, 1994, 1995, 1996, Robert M Supnik,
  4.    Digital Equipment Corporation
  5.    Commercial use prohibited
  6. */
  7.  
  8. #include "pdp8_defs.h"
  9. #include <ctype.h>
  10.  
  11. extern DEVICE cpu_dev;
  12. extern UNIT cpu_unit;
  13. extern DEVICE ptr_dev, ptp_dev;
  14. extern DEVICE tti_dev, tto_dev;
  15. extern DEVICE clk_dev, lpt_dev;
  16. extern DEVICE rk_dev, rx_dev;
  17. extern DEVICE rf_dev;
  18. extern DEVICE mt_dev;
  19. extern REG cpu_reg[];
  20. extern unsigned short M[];
  21. extern char *get_glyph (char *cptr, char *gbuf, char term);
  22. extern int get_unum (char *cptr, int radix, unsigned int max,
  23.     unsigned int *val);
  24.  
  25. /* SCP data structures and interface routines
  26.  
  27.    sim_name        simulator name string
  28.    sim_PC        pointer to saved PC register descriptor
  29.    sim_emax        maximum number of words for examine/deposit
  30.    sim_devices        array of pointers to simulated devices
  31.    sim_stop_messages    array of pointers to stop messages
  32.    sim_load        binary loader
  33. */
  34.  
  35. char sim_name[] = "PDP-8";
  36.  
  37. REG *sim_PC = &cpu_reg[0];
  38.  
  39. int sim_emax = 4;
  40.  
  41. DEVICE *sim_devices[] = { &cpu_dev,
  42.     &ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
  43.     &clk_dev, &lpt_dev,
  44.     &rk_dev, &rx_dev, &rf_dev,
  45.     &mt_dev,
  46.     NULL };
  47.  
  48. const char *sim_stop_messages[] = {
  49.     "Unknown error",
  50.     "Unimplemented instruction",
  51.     "HALT instruction",
  52.     "Breakpoint"  };
  53.  
  54. /* Binary loader
  55.  
  56.    Loader format consists of a string of 12-bit words (made up from 7 bit
  57.    characters) between leader and trailer (200).  The last word on tape
  58.    is the checksum.  A word with the "link" bit set is a new origin;
  59.    a character > 0200 indicates a change of field.
  60. */
  61.  
  62. int sim_load (FILE *fileref)
  63. {
  64. int rubout, word, low, high, origin, csum, field, state, i;
  65.  
  66. rubout = state = field = origin = csum = 0;
  67. while ((i = getc (fileref)) != EOF) {
  68.     if (rubout) {
  69.         rubout = 0;
  70.         continue;  }
  71.     if (i == 0377) {
  72.         rubout = 1;
  73.         continue;  }
  74.     if (i > 0200) {
  75.         field = (i & 070) << 9;
  76.         continue;  }
  77.     switch (state) {
  78.     case 0:                        /* leader */
  79.         if ((i != 0) && (i != 0200)) state = 1;
  80.         high = i;                /* save as high */
  81.         break;
  82.     case 1:                        /* low byte */
  83.         low = i;
  84.         state = 2;
  85.         break;
  86.     case 2:                        /* high with test */
  87.         word = (high << 6) | low;
  88.         if (i == 0200) {            /* end of tape? */
  89.             if ((csum - word) & 07777) return SCPE_CSUM;
  90.             return SCPE_OK;  }
  91.         csum = csum + low + high;
  92.         if (word >= 010000) origin = word & 07777;
  93.         else {    if ((field | origin) >= MEMSIZE) return SCPE_NXM;
  94.             M[field | origin] = word & 07777;
  95.             origin = (origin + 1) & 07777;  }
  96.         high = i;
  97.         state = 1;
  98.         break;  }                /* end switch */
  99.     }                        /* end while */
  100. return SCPE_FMT;                    /* eof? error */
  101. }                            /* end sim_loader */
  102.  
  103. /* Symbol tables */
  104.  
  105. #define I_V_FL        18                /* flag start */
  106. #define I_M_FL        07                /* flag mask */
  107. #define I_V_NPN        0                /* no operand */
  108. #define I_V_FLD        1                /* field change */
  109. #define I_V_MRF        2                /* mem ref */
  110. #define I_V_IOT        3                /* general IOT */
  111. #define I_V_OP1        4                /* operate 1 */
  112. #define I_V_OP2        5                /* operate 2 */
  113. #define I_V_OP3        6                /* operate 3 */
  114. #define I_NPN        (I_V_NPN << I_V_FL)
  115. #define I_FLD        (I_V_FLD << I_V_FL)
  116. #define I_MRF        (I_V_MRF << I_V_FL)
  117. #define I_IOT        (I_V_IOT << I_V_FL)
  118. #define I_OP1        (I_V_OP1 << I_V_FL)
  119. #define I_OP2        (I_V_OP2 << I_V_FL)
  120. #define I_OP3        (I_V_OP3 << I_V_FL)
  121.  
  122. static const int masks[] = {
  123.  07777, 07707, 07000, 07000,
  124.  07416, 07571, 017457 };
  125.  
  126. static const char *opcode[] = {
  127.  "SKON", "ION", "IOF", "SRQ",
  128.  "GTF", "RTF", "SGT", "CAF",
  129.  "RPE", "RSF", "RRB", "RFC", "RFC RRB",
  130.  "PCE", "PSF", "PCF", "PPC", "PLS",
  131.  "KCF", "KSF", "KCC", "KRS", "KIE", "KRB",
  132.  "TLF", "TSF", "TCF", "TPC", "SPI", "TLS",
  133.  "SBE", "SPL", "CAL",
  134.  "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK",
  135.  "CINT", "RDF", "RIF", "RIB",
  136.  "RMF", "SINT", "CUF", "SUF",
  137.  "ADCL", "ADLM", "ADST", "ADRB",
  138.  "ADSK", "ADSE", "ADLE", "ADRS",
  139.  "DCMA", "DMAR", "DMAW",
  140.  "DCIM", "DSAC", "DIML", "DIMA",
  141.  "DFSE", "DFSC", "DISK", "DMAC",
  142.  "DCXA", "DXAL", "DXAC",
  143.  "PSKF", "PCLF", "PSKE",
  144.  "PSTB", "PSIE", "PCLF PSTB", "PCIE",
  145.  "LWCR", "CWCR", "LCAR",
  146.  "CCAR", "LCMR", "LFGR", "LDBR",
  147.  "RWCR", "CLT", "RCAR",
  148.  "RMSR", "RCMR", "RFSR", "RDBR",
  149.  "SKEF", "SKCB", "SKJD", "SKTR", "CLF",
  150.  "DSKP", "DCLR", "DLAG",
  151.  "DLCA", "DRST", "DLDC", "DMAN",
  152.  "LCD", "XDR", "STR",
  153.  "SER", "SDN", "INTR", "INIT",
  154.  "DTRA", "DTCA", "DTXA", "DTLA",
  155.  "DTSF", "DTRB", "DTLB",
  156.  "CIF", "CDF", "CIF CDF",
  157.  "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT",
  158.  "NOP", "NOP2", "NOP3", "SWAB", "SWBA",
  159.  "STL", "GLK", "STA", "LAS", "CIA",
  160.  "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR",
  161.  "SKP", "SNL", "SZL",
  162.  "SZA", "SNA", "SZA SNL", "SNA SZL",
  163.  "SMA", "SPA", "SMA SNL", "SPA SZL",
  164.  "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL",
  165.  "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",
  166.  "SCA", "SCA SCL", "SCA MUY", "SCA DVI",
  167.  "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR",
  168.  "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR",
  169.  "SCA", "DAD", "DST", "SWBA",
  170.  "DPSZ", "DPIC", "DCIM", "SAM",
  171.  "CLA", "CLL", "CMA", "CML", "IAC",            /* encode only */
  172.  "CLA", "OAS", "HLT",
  173.  "CLA", "MQA", "MQL",
  174.  NULL, NULL, NULL, NULL,                /* decode only */
  175.  NULL  };
  176.  
  177. static const int opc_val[] = {
  178.  06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN,
  179.  06004+I_NPN, 06005+I_NPN, 06006+I_NPN, 06007+I_NPN,
  180.  06010+I_NPN, 06011+I_NPN, 06012+I_NPN, 06014+I_NPN, 06016+I_NPN,
  181.  06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN,
  182.  06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN,
  183.  06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN,
  184.  06101+I_NPN, 06102+I_NPN, 06103+I_NPN,
  185.  06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN,
  186.  06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN,
  187.  06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN,
  188.  06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN,
  189.  06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN,
  190.  06601+I_NPN, 06603+I_NPN, 06605+I_NPN,
  191.  06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN,
  192.  06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN,
  193.  06641+I_NPN, 06643+I_NPN, 06645+I_NPN,
  194.  06661+I_NPN, 06662+I_NPN, 06663+I_NPN,
  195.  06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN,
  196.  06701+I_NPN, 06702+I_NPN, 06703+I_NPN,
  197.  06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN,
  198.  06711+I_NPN, 06712+I_NPN, 06713+I_NPN,
  199.  06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN,
  200.  06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN,
  201.  06741+I_NPN, 06742+I_NPN, 06743+I_NPN,
  202.  06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN,
  203.  06751+I_NPN, 06752+I_NPN, 06753+I_NPN,
  204.  06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN,
  205.  06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN,
  206.  06771+I_NPN, 06772+I_NPN, 06774+I_NPN,
  207.  06201+I_FLD, 06202+I_FLD, 06203+I_FLD,
  208.  00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF,
  209.  04000+I_MRF, 05000+I_MRF, 06000+I_IOT,
  210.  07000+I_NPN, 07400+I_NPN, 07401+I_NPN, 07431+I_NPN, 07447+I_NPN,
  211.  07120+I_NPN, 07204+I_NPN, 07240+I_NPN, 07604+I_NPN, 07041+I_NPN,
  212.  07002+I_OP1, 07004+I_OP1, 07006+I_OP1,
  213.  07010+I_OP1, 07012+I_OP1, 07014+I_OP1, 07016+I_OP1,
  214.  07410+I_OP2, 07420+I_OP2, 07430+I_OP2,
  215.  07440+I_OP2, 07450+I_OP2, 07460+I_OP2, 07470+I_OP2,
  216.  07500+I_OP2, 07510+I_OP2, 07520+I_OP2, 07530+I_OP2,
  217.  07540+I_OP2, 07550+I_OP2, 07560+I_OP2, 07570+I_OP2,
  218.  07403+I_OP3, 07405+I_OP3, 07407+I_OP3,
  219.  07411+I_OP3, 07413+I_OP3, 07415+I_OP3, 07417+I_OP3,
  220.  07441+I_OP3, 07443+I_OP3, 07445+I_OP3, 07447+I_OP3,
  221.  07451+I_OP3, 07453+I_OP3, 07455+I_OP3, 07457+I_OP3,
  222.  017403+I_OP3, 017405+I_OP3, 0174017+I_OP3,
  223.  017411+I_OP3, 017413+I_OP3, 017415+I_OP3, 017417+I_OP3,
  224.  017441+I_OP3, 017443+I_OP3, 017445+I_OP3, 017447+I_OP3,
  225.  017451+I_OP3, 017453+I_OP3, 017455+I_OP3, 017457+I_OP3,
  226.  07200+I_OP1, 07100+I_OP1, 07040+I_OP1, 07020+I_OP1, 07001+I_OP1,
  227.  07600+I_OP2, 07404+I_OP2, 07402+I_OP2,
  228.  07601+I_OP3, 07501+I_OP3, 07421+I_OP3,
  229.  07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3,
  230.  -1 };
  231.  
  232. /* Operate decode
  233.  
  234.    Inputs:
  235.     inst    =    mask bits
  236.     class    =    instruction class code
  237.     sp    =    space needed?
  238.    Outputs:
  239.     status    =    space needed
  240. */
  241.  
  242. int oprf (int inst, int class, int sp)
  243. {
  244. int i, j;
  245.  
  246. for (i = 0; opc_val[i] >= 0; i++) {            /* loop thru ops */
  247.     j = (opc_val[i] >> I_V_FL) & I_M_FL;        /* get class */
  248.     if ((j == class) && (opc_val[i] & inst)) {    /* same class? */
  249.         inst = inst & ~opc_val[i];        /* mask bit set? */
  250.         printf ((sp? " %s": "%s"), opcode[i]);
  251.         sp = 1;  }  }
  252. return sp;
  253. }
  254.  
  255. /* Symbolic decode
  256.  
  257.    Inputs:
  258.     addr    =    current PC
  259.     *val    =    pointer to data
  260.     cflag    =    true if decoding for CPU
  261.     sw    =    switches
  262.    Outputs:
  263.     return    =    status code
  264. */
  265.  
  266. #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
  267. #define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100)
  268.  
  269. int print_sym (unsigned int addr, unsigned int *val, int cflag, int sw)
  270. {
  271. int i, j, sp, inst, disp, mask;
  272. extern int emode;
  273.  
  274. if (sw & SWMASK ('A')) {                /* ASCII? */
  275.     if (val[0] > 0377) return SCPE_ARG;
  276.     printf (FMTASC (val[0] & 0177));
  277.     return SCPE_OK;  }
  278. if (sw & SWMASK ('C')) {                /* characters? */
  279.     putchar (SIXTOASC ((val[0] >> 6) & 077));
  280.     putchar (SIXTOASC (val[0] & 077));
  281.     return SCPE_OK;  }
  282. if (!(sw & SWMASK ('M'))) return SCPE_ARG;
  283.  
  284. /* Instruction decode */
  285.  
  286. inst = val[0] | ((emode & 1) << 12);            /* include EAE mode */
  287. for (i = 0; opc_val[i] >= 0; i++) {            /* loop thru ops */
  288.     j = (opc_val[i] >> I_V_FL) & I_M_FL;        /* get class */
  289.     if ((opc_val[i] & 017777) == (inst & masks[j])) {    /* match? */
  290.  
  291.     switch (j) {                    /* case on class */
  292.     case I_V_NPN:                    /* no operands */
  293.         printf ("%s", opcode[i]);        /* opcode */
  294.         break;
  295.     case I_V_FLD:                    /* field change */
  296.         printf ("%s %-o", opcode[i], (inst >> 3) & 07);
  297.         break;
  298.     case I_V_MRF:                    /* mem ref */
  299.         disp = inst & 0177;            /* displacement */
  300.         printf ("%s%s", opcode[i], ((inst & 00400)? " I ": " "));
  301.         if (inst & 0200) {            /* current page? */
  302.             if (cflag) printf ("%-o", (addr & 07600) | disp);
  303.             else printf ("T %-o", disp);  }
  304.         else printf ("%-o", disp);        /* page zero */
  305.         break;
  306.     case I_V_IOT:                    /* IOT */
  307.         printf ("%s %-o", opcode[i], inst & 0777);
  308.         break;
  309.     case I_V_OP1:                    /* operate group 1 */
  310.         sp = oprf (inst & 0361, j, 0);        /* mask bits */
  311.         if (opcode[i]) printf ((sp? " %s": "%s"), opcode[i]);
  312.         break;
  313.     case I_V_OP2:                    /* operate group 2 */
  314.         if (opcode[i]) printf ("%s", opcode[i]);    /* skips */
  315.         oprf (inst & 0206, j, opcode[i] != NULL);    /* mask bits */
  316.         break;    
  317.     case I_V_OP3:                    /* operate group 3 */
  318.         sp = oprf (inst & 0320, j, 0);        /* mask bits */
  319.         if (opcode[i]) printf ((sp? " %s": "%s"), opcode[i]);
  320.         break;  }                /* end case */
  321.     return SCPE_OK;  }                /* end if */
  322.     }                        /* end for */
  323. return SCPE_ARG;
  324. }
  325.  
  326. /* Symbolic input
  327.  
  328.    Inputs:
  329.     *cptr    =    pointer to input string
  330.     addr    =    current PC
  331.     cflag    =    true if parsing for CPU
  332.     *val    =    pointer to output values
  333.    Outputs:
  334.     status    =    error status
  335. */
  336.  
  337. int parse_sym (char *cptr, unsigned int addr, int cflag, unsigned int *val)
  338. {
  339. int i, j, k;
  340. unsigned int r;
  341. char gbuf[CBUFSIZE];
  342.  
  343. while (isspace (*cptr)) cptr++;                /* absorb spaces */
  344. if (cptr[0] == '\'') {                    /* single char? */
  345.     if (cptr[1] == 0) return SCPE_ARG;
  346.     val[0] = (unsigned int) cptr[1] | 0200;
  347.     return SCPE_OK;  }
  348. if (cptr[0] == '"') {                    /* string? */
  349.     if (cptr[1] == 0) return SCPE_ARG;
  350.     val[0] = (((unsigned int) cptr[1] & 077) << 6) |
  351.           ((unsigned int) cptr[2] & 077);
  352.     return SCPE_OK;  }
  353.  
  354. /* Instruction parse */
  355.  
  356. cptr = get_glyph (cptr, gbuf, 0);            /* get opcode */
  357. for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  358. if (opcode[i] == NULL) return SCPE_ARG;
  359. val[0] = opc_val[i] & 07777;                /* get value */
  360. j = (opc_val[i] >> I_V_FL) & I_M_FL;            /* get class */
  361.  
  362. switch (j) {                        /* case on class */
  363. case I_V_IOT:                        /* IOT */
  364.     cptr = get_glyph (cptr, gbuf, 0);        /* get dev+pulse */
  365.     if (get_unum (gbuf, 8, 0777, &r) != SCPE_OK) return SCPE_ARG;
  366.     val[0] = val[0] | r;
  367.     break;
  368. case I_V_FLD:                        /* field */
  369.     for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
  370.         cptr = get_glyph (cptr, gbuf, 0)) {
  371.         for (i = 0; (opcode[i] != NULL) &&
  372.             (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  373.         if (opcode[i] != NULL) {
  374.             k = (opc_val[i] >> I_V_FL) & I_M_FL;
  375.             if (k != j) return SCPE_ARG;
  376.             val[0] = val[0] | (opc_val[i] & 07777);  }
  377.         else {    if (get_unum (gbuf, 8, 07, &r) != SCPE_OK)
  378.                 return SCPE_ARG;
  379.             val[0] = val[0] | (r << 3);
  380.             break;  }  }
  381.         break;
  382. case I_V_MRF:                        /* mem ref */
  383.     cptr = get_glyph (cptr, gbuf, 0);        /* get next field */
  384.     if (strcmp (gbuf, "I") == 0) {            /* indirect? */
  385.         val[0] = val[0] | 0400;
  386.         cptr = get_glyph (cptr, gbuf, 0);  }
  387.     if ((k = (strcmp (gbuf, "T") == 0)) || (strcmp (gbuf, "Z") == 0)) {
  388.         cptr = get_glyph (cptr, gbuf, 0);
  389.         if (get_unum (gbuf, 8, 0177, &r) != SCPE_OK) return SCPE_ARG;
  390.         val[0] = val[0] | r | (k? 0200: 0);  }
  391.     else {    if (get_unum (gbuf, 8, 07777, &r) != SCPE_OK) return SCPE_ARG;
  392.         if (r <= 0177) val[0] = val[0] | r;
  393.         else if (cflag && (((addr ^ r) & 07600) == 0))
  394.             val[0] = val[0] | (r & 0177) | 0200;
  395.         else return SCPE_ARG;  }
  396.     break;
  397. case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3:    /* operates */
  398.     for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
  399.         cptr = get_glyph (cptr, gbuf, 0)) {
  400.         for (i = 0; (opcode[i] != NULL) &&
  401.             (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  402.         k = opc_val[i] & 07777;
  403.         if ((opcode[i] == NULL) || (((k ^ val[0]) & 07000) != 0))
  404.             return SCPE_ARG;
  405.         val[0] = val[0] | k;  }
  406.     break;  }                    /* end case */
  407. if (*cptr != 0) return SCPE_ARG;            /* junk at end? */
  408. return SCPE_OK;
  409. }
  410.