home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol140 / seg2x68.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  9.3 KB  |  388 lines

  1. /*    M6800 Cross Assembler                */
  2. /*    Overlay Segment SEG2.C        Version A.1    */
  3. /*    Pass Two of X68 M6800 cross assembler        */
  4.  
  5. /*
  6.  *    PERMISSION IS GRANTED FOR THE PUBLIC DOMAIN
  7.  *    NON COMMERCIAL USE OF THIS SOFTWARE.
  8.  *
  9.  *    (C) CHRIS UNDERY 25th OCTOBER 1982
  10.  *    11 MARGARET ST NEWTOWN 2042
  11.  *    SYDNEY, AUSTRALIA
  12.  */
  13.  
  14. /*
  15.     This pass of X68 reads the UFN.TMP searching for
  16.  undefined hex code signified by a '?' in the I2 field of
  17.  and instruction. If the I3 field is also undefined, a word
  18.  reference is assumed. The program looks up the operand in the
  19.  symbol table and fills in the blanks. If the symbol is still
  20.  undefined, a fatal error is assumed.
  21.  
  22.     This module is an overlay, loaded by the swapin function
  23. in X68.c
  24.  
  25. */
  26.  
  27. #include "x68.h"
  28.  
  29. main()
  30. {
  31.  
  32.     struct nlist *lookup(), *install(), *ptr;
  33.     char asfile[15], temp[150], listfile[15];
  34.     char hbuf[BUFSIZ];
  35.  
  36.     pageno = linecnt = 0;
  37.     printf("Pass two (Version A.1)\n");
  38.     strcpy(asfile,filename);    /* get primary file name */
  39.     strcat(asfile,".TMP");        /* add temp filetype    */
  40.     if (fopen(asfile,ibuf) == ERROR ) {
  41.         printf("Cannot open %s\007\n",asfile);
  42.         exit();            /* Halt progress     */
  43.     }
  44.     if (xing) {
  45.         if (fcreat(hexname,hbuf) == ERROR) {
  46.             printf("Disk probably full: Cannot create hex file\n");
  47.             exit();
  48.         }
  49.     }
  50.     if (listing) {
  51.         if (fcreat(lstname,obuf) == ERROR ) {
  52.             printf("Disk probably full: Cannot create %s\007\n",listfile);
  53.             exit();
  54.         }
  55.     }
  56.     lineno = 0;
  57.     header();
  58.     while (fgets(line,ibuf)) {
  59.         pass2();        /* Do pass 2 */
  60.         if (line[0] != ';') makeline();
  61.         else {
  62.             if (listing) {
  63.                 putc(TAB,obuf); /* Pretty up the listing */
  64.                 putc(TAB,obuf);
  65.             }
  66.             if (printing) printf("\t\t");
  67.         }
  68.         if (linecnt++ == 55) header();
  69.         if (xing) wrhex(hbuf);        /* Write hex file */
  70.         if (listing) fputs(line,obuf);
  71.         if (printing) printf("%s",line);
  72.     }
  73.     putsym();                /* Write symbols to lst */
  74.     if (listing) {
  75.         fprintf(obuf,"\n\nEND OF ASSEMBLY ");
  76.         fprintf(obuf,"%d FATAL ERROR(S) DETECTED\n",errors);
  77.         putc(0x1a,obuf);
  78.         fflush(obuf);
  79.         fclose(obuf);
  80.     }
  81.     fclose(ibuf);
  82.     if (xing) {
  83.         fprintf(hbuf,":00000001FF\n");
  84.         putc(0x1a,hbuf);
  85.         fflush(hbuf);
  86.         fclose(hbuf);
  87.     }
  88.     if (!debug) unlink(asfile);
  89. }                /* PAss 2 done */
  90.  
  91.  
  92. pass2()
  93. {
  94.     struct nlist *ptr, *alt, *lookup();
  95.     unsigned current, branch, relative;
  96.     char swopper[16], fiddled;
  97.  
  98.     current = branch = relative = 0;
  99.     lineno++;
  100.     tokenise();        /* Get tokens */
  101.     if (temp[8] != '?') return(1);    /* No wuckers */
  102.  
  103. /* Version A.1 has expression evaluator in root module x68.com */
  104. /* the old version was in seg1 overlay and as result, seg2 could */
  105. /* not be very intelligent. This version can evaluate failed */
  106. /* operand complexes from pass 1 */
  107.  
  108.     fiddled = 0;    
  109.     if (operand[0] == '#') {
  110.         strcpy(swopper,&operand[1]);
  111.         strcpy(operand,swopper);
  112.         fiddled = 1;
  113.     }
  114.     getsub(operand);    /* split operand down the middle */
  115.     if ((ptr = lookup(xp1)) != NULL) goto itil;
  116.     if ((alt = lookup(xp2)) == NULL) {
  117.         B1090();    /* Total failure undefined symbol */
  118.         return(1);
  119.     }
  120. itil:    if ((index(alt->def,"??") >=0) || (index(ptr->def,"??") >= 0)) {
  121.         B1090();    /* trap unresolved references */
  122.         return(1);
  123.     }
  124.     if (!evaluate(operand)) { /* only now is it safe to evaluate it */
  125.         B1090();
  126.         return(1);
  127.     }
  128.  
  129. /* if this line has a label then install the label now in case further */
  130. /* references are made to it, this takes care of foward refs on an equ */
  131.  
  132.     getok(label,&line[18],1,16);    /* extract label from line */
  133.     tohex(labrec,dec);    /* convert result to hex string */
  134.     if (label[0] != '\0') { /* install label reference */
  135.         if ((alt = install(label,labrec)) == NULL) {
  136.             printf("I just creamed the symbol table boss!\n");
  137.             exit();
  138.         }
  139.     }
  140.     if (fiddled) {
  141.         strcpy(swopper,"#");
  142.         strcat(swopper,operand);
  143.         strcpy(operand,swopper);
  144.     }
  145.     strcpy(labad,labrec);
  146.     if (line[10] == '?' ) {        /* Word reference eg JMP */
  147.         if (index(mnem,"EQU") >= 0) {
  148.             temp[13] = labrec[0];
  149.             temp[14] = labrec[1];
  150.             temp[15] = labrec[2];
  151.             temp[16] = labrec[3];
  152.             temp[8] = ' ';
  153.             temp[9] = ' ';
  154.             temp[10] = ' '; temp[11] = ' ';
  155.         }
  156.         else {
  157.             temp[8] = labrec[0];
  158.             temp[9] = labrec[1];
  159.             temp[10] = labrec[2];
  160.             temp[11] = labrec[3];
  161.         }
  162.     return(1);
  163.     }
  164.     smov(hex,&temp[0],4);         /* Rel brnch, get current address */
  165.     current = todec(hex,16);        /* Convert to hex    */
  166.     branch = todec(labrec,16);        /* ready for diff test  */
  167.     relative = branch - current + 254;
  168.     if (relative < 128 ) B1095();
  169.     if (relative > 383 ) B1095();
  170.     tohex(hex,relative);        /* convert back to hex   */
  171.     temp[8] = hex[2];
  172.     temp[9] = hex[3];        /* Replace ?? with result */
  173.     temp[13] = labad[0];        /* Now pretty up with label addr */
  174.     temp[14] = labad[1];
  175.     temp[15] = labad[2];
  176.     temp[16] = labad[3];
  177.     return(1);
  178. }                /* While not end of file     */
  179.  
  180. B1090()
  181. {
  182.     printf("Variable <%s> not defined at line <%u> in module %s\n",operand,lineno,title);
  183.     printf("%s\n",line);
  184.     if (listing) fprintf(obuf,"*** ERROR *** UNDEFINED VARIABLE: %s \n",operand);
  185.     errors++;
  186.     if (lineno++ == 55) header();
  187.     return(1);
  188. }
  189.  
  190.  
  191. B1095()
  192. {    
  193.     printf("Branch out of range at line <%u> in module %s\n",lineno,title);
  194.     printf("%s\n",line);
  195.     if (listing) fprintf(obuf,"*** ERROR ***  BRANCH DISPLACEMENT OUT OF RANGE \n");
  196.     errors++;
  197.     if (lineno++ == 55) header();
  198.     return(1);
  199. }
  200.  
  201. /*    Get set of tokens from temporary pass 1 file */
  202.  
  203. tokenise()
  204. {
  205.     int slew_count;
  206.  
  207.     getok(temp,line,1,30);    /* Will also get LABEL code field */
  208.     getok(mnem,line,2,9);    /* Get mnemonic field */
  209.     getok(operand,line,3,80);    /* Get operand field */
  210.     getcomment(line);
  211.     if (index(mnem,"TITLE") >= 0) smov(title,operand,32);
  212.     if (index(mnem,"PAGE") >= 0) header();
  213.     if (index(mnem,"NOLIST") >= 0) printing = 0;
  214.     if (index(mnem,"LIST") >= 0) printing = 1;
  215.     if (index(mnem,"SPACE") >= 0) {    /* accomodate excesses of tek ass */
  216.         if (evaluate(operand)) {
  217.             slew_count = 0;
  218.             while (slew_count++ < dec) {
  219.                 if (listing) fprintf(obuf,"\n");
  220.                 if (printing) printf("\n");
  221.                 if (lineno++ == 55) header();
  222.             }
  223.         }
  224.     }
  225. }
  226.  
  227. makeline()        /* Build up output line */
  228. {
  229.     int adjuster;
  230.  
  231.  
  232.     strcpy(line,temp);    /* First stuff incl label */
  233.     adjuster = 30 - strlen(temp);
  234.     while (adjuster--) strcat(line," ");
  235.     strcat(line,"\t");
  236.     strcat(line,mnem);
  237.     strcat(line,"\t");
  238.     strcat(line,operand);
  239.     strcat(line,"\t");
  240.     strcat(line,comment);
  241. }
  242.  
  243. header()        /* Produce page header */
  244. {
  245.     if (listing) {
  246.         putc(0x0c,obuf);    /* Form feed */
  247.         fprintf(obuf,"X68 Motorola 6800 Cross Assembler Version A.1");
  248.         fprintf(obuf,"           Page # %5d  File: %s ",++pageno,filename);
  249.         fprintf(obuf,"Module name: %s\n\n",title);
  250.         fprintf(obuf,"Addr Code            Source Statement\n\n");
  251.         linecnt = 0;
  252.     }
  253.     if (printing) {
  254.         if (!listing) pageno++;    /* dont double up page numbering */
  255.         putc(0x0c,1);
  256.         printf("X68 Motorola 6800 Cross Assembler Version A.1");
  257.         printf("           Page # %5d File: %s ",pageno,filename);
  258.         printf("Module name: %s\n\n",title);
  259.         printf("Addr Code        Source Statement\n\n");
  260.         if (!listing) linecnt = 0;
  261.     }
  262. }
  263.  
  264. gethex()        /* Get hex record from output line */
  265. {            /* Returning numberof data bytes */
  266.     int count;
  267.     int k, i;
  268.     char fudge[10];
  269.  
  270.     count = i = 0;
  271.     hexrec[0] = '0';
  272.     hexrec[1] = '0';
  273.     hexrec[2] = NULL;
  274.     smov(fudge,temp,4);
  275.     k = todec(fudge,16);    /* convert address to dec */
  276.     k = (k - bias);
  277.     tohex(fudge,k);
  278.     hexrec[2] = fudge[0];
  279.     hexrec[3] = fudge[1];
  280.     hexrec[4] = fudge[2];
  281.     hexrec[5] = fudge[3];
  282.     hexrec[6] = '\0';
  283.     i = 6;
  284.     strcat(hexrec,"00");    /* record type */
  285.     i += 2;
  286.     if (!isspace(temp[5])) {
  287.         hexrec[i++] = temp[5];
  288.         hexrec[i++] = temp[6];
  289.         count++;
  290.     }
  291.     if (!isspace(temp[8])) {
  292.         hexrec[i++] = temp[8];
  293.         hexrec[i++] = temp[9];
  294.         count++;
  295.     }
  296.     if (!isspace(temp[10])) {
  297.         hexrec[i++] = temp[10];
  298.         hexrec[i++] = temp[11];
  299.         count++;
  300.     }
  301.     hexrec[i] = '\0';
  302.     hexrec[1] = (0x30 + count);
  303.     return(count);    /* one more for checksum */
  304. }
  305.  
  306. genbin(c)        /* Generate binary image of hex record */
  307. int c;        /* Count for countfield */
  308. {
  309.     int m, i, g, j, k;    /* Indices    */
  310.     char tb[5];
  311.     bcc = i = j = k = m = 0;
  312.     g = (strlen(hexrec)-1);
  313.     while (m < g) {        /* Loop converting hexrec to binary */
  314.         tb[0] = hexrec[m++];
  315.         tb[1] = hexrec[m++];
  316.         tb[2] = '\0';
  317.         k = todec(tb,16);
  318.         bcc += k;    /* update checksum */
  319.     }
  320.     bcc=(~bcc)+1;        /* Take twos complement */
  321.     return(1);        /* number of characters to send */
  322. }
  323.  
  324. wrhex(h)                /* Write hex record */
  325. char *h;
  326. {
  327.     int c, e, d;
  328.  
  329.     d = 0;
  330.     if (temp[0] == ';' || temp[0] == '*') return(1);
  331.     if (index(mnem,"SPACE") >= 0) return(1);  /*PA - return if directive*/
  332.     if (index(mnem,"NOLIST") >= 0) return(1);
  333.     if (index(mnem,"LIST") >= 0) return(1);
  334.     if (index(mnem,"PAGE") >= 0) return(1);
  335.     if (index(mnem,"TITLE") >= 0) return(1);
  336.     if (index(mnem,"PURGE") >= 0) return(1);
  337.     if (!gethex()) return(0);    /* no stuff to write */
  338.     c = genbin(e);
  339.     fprintf(h,":");
  340.     fprintf(h,"%s",hexrec);
  341.     tohex(temp,bcc);
  342.     putc(temp[2],h);
  343.     putc(temp[3],h);
  344.     fprintf(h,"\n");
  345. }
  346.  
  347. /*    Write symbol table to listing device */
  348.  
  349. putsym()
  350. {
  351.     struct nlist *tp, *lookup();
  352.     int bucket, num;
  353.  
  354.     bucket = num = 0;
  355.     if ((!listing) && (!printing)) return(1);
  356.     if (listing) {
  357.         putc(0x0c,obuf);
  358.         fprintf(obuf,"Symbols:\n\n");
  359.     }
  360.     if (printing) {
  361.         putc(0x0c);
  362.         printf("Symbols:\n\n");
  363.     }
  364.     while (bucket < HASHSIZE) {
  365.         for (tp = hashtab[bucket]; tp != NULL; tp = tp->next) {
  366.             if (listing) {
  367.                 fprintf(obuf,"%s\t%s\t",tp->name,tp->def);
  368.                 if (num == 5) {
  369.                      fprintf(obuf,"\n");
  370.                       if (linecnt++ == 55)  header();
  371.                      num = 0;
  372.                 }
  373.             }
  374.             if (printing) {    /* to console or printer */
  375.                 printf("%s\t%s\t",tp->name,tp->def);
  376.                 if (num == 4) {
  377.                      printf("\n");
  378.                      if (linecnt++ == 55) header();
  379.                      num = 0;
  380.                 }
  381.             }
  382.             num++;
  383.         }
  384.     bucket++;
  385.     }
  386.     if (printing) putc(0x0c,1);
  387. }
  388.