home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / smmaclnk.ark / MAC2.C < prev    next >
Text File  |  1987-09-10  |  14KB  |  564 lines

  1. /*
  2. ** MAC2.c -- Small-Mac Assembler -- Part 2: pass 1 and 2 Functions
  3. **
  4. **    Copyright 1985 J. E. Hendrix
  5. */
  6. #include <stdio.h>
  7. #include "mac.h"
  8. #include "rel.h"
  9. #include "ext.h"
  10. #define NOCCARGC
  11.  
  12. extern int iloc;        /* instr location */
  13.  
  14. /*
  15. ** add a new symbol to the table
  16. */
  17. addsym() {
  18.   char *dest, *sour;
  19.   if(*stptr) error("- Symbol Table Overflow");
  20.   stp[stn++] = stptr;        /* set symbol pointer */
  21.   dest = stptr; sour = stsym;
  22.   while(*dest++ = toupper(*sour++));
  23.   }
  24.  
  25. /*
  26. ** determine if an assembler insrtruction
  27. */
  28. aifind() {
  29.   char *cp; cp = lp;
  30.   while(isgraph(*lp)) ++lp;
  31.   while(isspace(*lp)) ++lp;
  32.        if(fldcmp(cp, "DW")  == 0) return (DW);
  33.   else if(fldcmp(cp, "DB")  == 0) return (DB);
  34.   else if(fldcmp(cp, "DS")  == 0) return (DS);
  35.   else if(fldcmp(cp, "EXT") == 0) return (EX);
  36.   else if(fldcmp(cp, "SET") == 0) return (SET);
  37.   else if(fldcmp(cp, "EQU") == 0) return (EQU);
  38.   else if(fldcmp(cp, "ORG") == 0) return (ORG);
  39.   else if(fldcmp(cp, "END") == 0) return (END);
  40.   return (ERR);
  41.   }
  42.  
  43. /*
  44. ** begin a line in the listing
  45. */
  46. begline() {
  47.   char str[6];
  48.   if(pass == 2 && list) {
  49.     if(begpage()) {
  50.       puts("line  loc ----object----  source"); puts("");
  51.       lline += 2;
  52.       }
  53.     itou(lin, str, 5); fputs(str, stdout);
  54.     itox(loc, str, 6); fputs(str, stdout);
  55.     putchar(' '); ccnt = 0; ++lline;
  56.     }
  57.   }
  58.  
  59. /*
  60. ** begin a page?
  61. */
  62. begpage() {
  63.   char str[4];
  64.   if(lline >= 58) {
  65.     lline = 2;
  66.     ++lpage;
  67.     if(lpage > 1) puts("\n\n\n\n\n\n\n");
  68.     fputs("file: ", stdout); fputs(srcfn, stdout);
  69.     itou(lpage, str, 4);
  70.     fputs("   page: ", stdout); puts(str); puts("");
  71.     return (YES);
  72.     }
  73.   return (NO);
  74.   }
  75.  
  76. /*
  77. ** detect assembler instruction and process it
  78. */
  79. doasm() {
  80.   int j;
  81.   if(atend(*lp) && (!stsym[0] || gotlabel)) return;
  82.   if((j = aifind()) == ERR) {    /* lp -> 2nd field or end */
  83.     lp = skip(1, line);        /* lp -> 1st field */
  84.     j = aifind();
  85.     stsym[0] = NULL;        /* declare no symble */
  86.     }
  87.   switch(j) {
  88.     case  EX: doext();       return;
  89.     case  DW: dodat(INTSZ);  return;
  90.     case  DB: dodat(1);      return;
  91.     case  DS: doloc(YES);    return;
  92.     case ORG: doloc(NO);     return;
  93.     case SET: doval(SETBIT); return;
  94.     case EQU: doval(0);      return;
  95.     case END: doend();       return;
  96.     }
  97.   oprerr();
  98.   }
  99.  
  100. /*
  101. ** define data (DB & DW)
  102. */
  103. dodat(sz) int sz; {
  104.   int dlm;
  105.   while(!atend(*lp)) {
  106.     if(isspace(*lp) || *lp == ',') ++lp;
  107.     else if(*lp == '\"' || *lp == '\'') {    /* string? */
  108.       dlm = *lp;
  109.       while(!atend(*++lp)) {
  110.     if(*lp == dlm && *++lp != dlm) break;
  111.     if(pass == 2) {field = *lp; genabs(sz);}
  112.     else loc += sz;
  113.     }
  114.       }
  115.     else {
  116.       ep = lp;                    /* expression? */
  117.       expr(&field, &type);
  118.       lp = ep;
  119.       if(pass == 2) {
  120.     type &= RELBITS;
  121.     if(type == ABS) genabs(sz);
  122.     else {
  123.       if(sz == 1) {relerr(); genabs(1);}    /* 1-byte relocatable? */
  124.       else genrel();            /* output relocatable item */
  125.       }
  126.     }
  127.       else loc += sz;
  128.       }
  129.     }
  130.   }
  131.  
  132. /*
  133. ** process END instruction
  134. */
  135. doend() {
  136.   eom = YES;            /* flag end of module */
  137.   onexpr();
  138.   if((type & RELBITS) == PREL) {
  139.     endt = PREL;
  140.     endv = field;
  141.     }
  142.   else if(field) relerr();
  143.   }
  144.  
  145. /*
  146. ** define external reference (ECT)
  147. */
  148. doext() {
  149.   while(!atend(*lp)) {
  150.     while(isspace(*lp) || *lp == ',') {++lp; continue;}
  151.     lp = getsym(lp, NO);            /* fetch the next symbol */
  152.     if(badsym) {symerr(); continue;}    /* symbol error */
  153.     else if(stfind()) {            /* already in table? */
  154.       if(stptr[STFLAG] & (LABBIT|EQUBIT|SETBIT)) {rederr(); continue;}
  155.       }
  156.     else addsym();            /* not yet defined */
  157.     if(pass == 1) stptr[STFLAG] |= XRBIT|ABS;    /* 1st ext ref is ABS 0 */
  158.     }
  159.   }
  160.  
  161. /*
  162. ** detect label and stow it away
  163. */
  164. dolabel() {
  165.   lp = skip(1, line);            /* locatefirst field */
  166.   lp = getsym(lp, NO);            /* fetch a symble */
  167.   if(gotlabel) {            /* got label */
  168.     if(badsym) {laberr(); return;}
  169.     if(stfind()) {            /* already in table */
  170.       if(pass == 1) {
  171.     if(stptr[STFLAG] & (LABBIT|EQUBIT|SETBIT|XRBIT))
  172.       {rederr(); return;}
  173.     }
  174.       else if(stptr[STFLAG] & (LABBIT2|EQUBIT|SETBIT|XRBIT))
  175.     {rederr(); return;}
  176.       else stptr[STFLAG] |= LABBIT2;
  177.       }
  178.     else addsym();            /* not defined, stow it */
  179.     if(pass == 1) {
  180.       putint(stptr + STVALUE, loc);    /* value */
  181.       if(gotep)                /* flags */
  182.        stptr[STFLAG] = LABBIT|PREL|EPBIT;
  183.       else stptr[STFLAG] = LABBIT|PREL;
  184.       }
  185.     }
  186.   }
  187.  
  188. /*
  189. ** set location counter (ORG, DS)
  190. */
  191. doloc(bump) int bump; {
  192.   if(onexpr()) {
  193.     if(bump) field = loc += field;
  194.     else if(loc <= field) loc = field;
  195.     else bakerr();
  196.     if(pass == 2) {item = SETLC; type = PREL; putrel();}
  197.     }
  198.   }
  199.  
  200. /*
  201. ** detect machine instruction and process it
  202. */
  203. domach() {
  204.   char *fmt, *cp;
  205.   if(gotlabel) cp = lp;
  206.   else         cp = skip(1, line);    /* backup if no label */
  207.   if(fmt = find(cp)) {            /* machine instruction? */
  208.     fmt += INTSZ;            /* locate format byte in mit */
  209.     if(pass == 2) domac2(fmt);        /* do pass 2 processing */
  210.     else loc += (*fmt & 3) + 1;        /* bump location counter */
  211.     return (YES);
  212.     }
  213.   return (NO);                /* may be pseudo-op */
  214.   }
  215.  
  216. /*
  217. ** detect machine instruction and generate object code
  218. */
  219. domac2(ptr) char *ptr; {
  220.   int format, len, ilen, pcr, t, v, opcode, holding;
  221.   format = getint(ptr++);        /* ptr is now 1 byte early */
  222.   len = ilen = (format & 7) + 1;
  223.   format >>= 3;                /* first code/expr bit */
  224.   iloc = loc;                /* preserve istr loc for $ */
  225.   holding = NO;
  226.   ep = expbuf;                /* set up for expr() */
  227.   while(len-- > 0) {            /* for each byte of code */
  228.     if(format & 1) {            /* expression */
  229.       if(holding) {
  230.     holding = NO;
  231.     field = opcode + opadj;    /* adjust last byte before expr */
  232.     opadj = 0;
  233.     genabs(1);
  234.     }
  235.       expr(&v, &t);            /* evaluate next expression */
  236.       format >>= 1;            /* pc relative bit */
  237.       if(format & 1) {
  238.     if((t & RELBITS) == PREL) {
  239.       v -= ilen + iloc;        /* calc offset from this instr */
  240.       t = (t & ~RELBITS) + ABS;    /* now abs, may be 1 byte */
  241.       }
  242.     else v -= ilen;            /* adjust offset from this instr */
  243.     pcr = YES;            /* remember it's pc relative */
  244.     }
  245.       else pcr = NO;
  246.       format >>= 1;            /* size bit */
  247.       if(format & 1) {            /* 2-byte expr */
  248.     if(t & XRBIT) {            /* ext ref */
  249.       if(v) {            /* must be offset from ext ref */
  250.         item = XPOFF;
  251.         type = ABS;
  252.         field = v;
  253.         listcode(2, "+ ");        /* list offset */
  254.         putrel();            /* write 2-byte offset */
  255.         }
  256.       field = prior;        /* will link to prior ref */
  257.       }
  258.     else field = v;            /* expr value */
  259.     if((t & RELBITS) == ABS)
  260.          genabs(2);            /* write 2 absolute bytes */
  261.     else genrel();            /* write 2 relocatable bytes */
  262.     --len;
  263.     }
  264.       else {                /* 1-byte expr */
  265.     if((t & RELBITS) == PREL)
  266.       relerr();            /* 1 byte can't be relocatable */
  267.     if(pcr && (v > 127 || v < -128))
  268.       rngerr();            /* range error */
  269.     field = v;            /* expr value */
  270.     genabs(1);            /* write 1 absolute byte */
  271.     }
  272.       }
  273.     else {                /* code byte */
  274.       if(holding) {
  275.     field = opcode;            /* don't adjust, not last byte */
  276.     genabs(1);            /* write prior code byte */
  277.     }
  278.       opcode = *++ptr & 255;        /* hold this one, may be more */
  279.       holding = YES;
  280.       }
  281.     format >>= 1;
  282.     }
  283.   if(holding) {
  284.     field = opcode + opadj;
  285.     genabs(1);                /* write last code byte */
  286.     }
  287.   }
  288.  
  289. /*
  290. ** define a symbol value (SET, EQU)
  291. */
  292. doval(set) int set; {
  293.   char *ptr; int found;
  294.   if(!stsym[0] || badsym || gotlabel) {symerr(); return;}
  295.   if((found = stfind()) == 0) addsym();/* not defined */
  296.   ptr = stptr;                /* preserve stptr */
  297.   onexpr();                /* evaluate expression */
  298.   if(pass == 1 || set) {
  299.     if(found == 0 || ptr[STFLAG] & set) {
  300.       putint(ptr + STVALUE, field);    /* value */
  301.       ptr[STFLAG] = set|type;        /* flags */
  302.       }
  303.     else rederr();
  304.     }
  305.   else if(ptr[STFLAG] & (LABBIT|EQUBIT|SETBIT|XRBIT)) rederr();
  306.   else ptr[STFLAG] |= EQUBIT;
  307.   if(pass == 2) {            /* list value */
  308.     if((ptr[STFLAG] & RELBITS) == PREL)
  309.      listcode(2, "' =");
  310.     else listcode(2, "  =");
  311.     }
  312.   }
  313.  
  314. /*
  315. ** end a line in the listing
  316. */
  317. endline() {
  318.   char *cp; int col; col = 0;
  319.   if(pass == 2 && list) {
  320.     if(part1) puts("");
  321.     else {
  322.       part1 = YES;
  323.       while(ccnt++ < 16) putchar(' ');
  324.       cp = line;
  325.       while(*cp) {
  326.     if(*cp != '\t') {++col; putchar(*cp++);}
  327.     else {do putchar(' '); while(++col % 8); ++cp;}
  328.     }
  329.       }
  330.     }
  331.   }
  332.  
  333. /*
  334. ** generate an absolute value of sz bytes
  335. */
  336. genabs(sz) int sz; {
  337.   listcode(sz, " ");
  338.   loc += sz;            /* bump location counter */
  339.   item = ABS;
  340.   while(sz--) {putrel(); field >>= 8;}
  341.   }
  342.  
  343. /*
  344. ** generate a relocatable item
  345. */
  346. genrel() {
  347.   listcode(2, "' ");
  348.   loc += 2;            /* bump location counter */
  349.   item = PREL;
  350.   putrel();            /* write 2-byte relocatable item */
  351.   }
  352.  
  353. /*
  354. ** gripe about errors in a line
  355. */
  356. gripe() {
  357.   if(lerr) {
  358.     if(!list) outerr(line);
  359.     if(lerr &    1) outerr("- Backward Movement\n");
  360.     if(lerr &    2) outerr("- Bad Number\n");
  361.     if(lerr &    4) outerr("- Bad Expression\n");
  362.     if(lerr &    8) outerr("- Bad Label\n");
  363.     if(lerr &   16) outerr("- Bad Operation\n");
  364.     if(lerr &   32) outerr("- Redundant Definition\n");
  365.     if(lerr &   64) outerr("- Bad Symbol\n");
  366.     if(lerr &  128) outerr("- Relocation Error\n");
  367.     if(lerr &  256) outerr("- Undefined Symbol\n");
  368.     if(lerr &  512) outerr("- Bad Parameter\n");
  369.     if(lerr & 1024) outerr("- Range Error\n");
  370.     if(pause) wait();
  371.     outerr("\n");
  372.     err = YES;
  373.     }
  374.   }
  375.  
  376. bakerr() {lerr |=    1;}
  377. numerr() {lerr |=    2;}
  378. experr() {lerr |=    4;}
  379. laberr() {lerr |=    8;}
  380. oprerr() {lerr |=   16;}
  381. rederr() {lerr |=   32;}
  382. symerr() {lerr |=   64;}
  383. relerr() {lerr |=  128;}
  384. underr() {lerr |=  256;}
  385. parerr() {lerr |=  512;}
  386. rngerr() {lerr |= 1024;}
  387.  
  388. /*
  389. ** list a code item
  390. */
  391. listcode(sz, suff) int sz; char suff[]; {
  392.   int i; char str[3];
  393.   if(list) {
  394.     i = sz + sz + strlen(suff);
  395.     if((ccnt + i) > 16) {endline(); begline();}
  396.     while(sz--) {
  397.       if(sz) itox((field >> 8) & 255, str, 3);
  398.       else   itox(field & 255, str, 3);
  399.       if(*str == ' ') *str = '0';
  400.       fputs(str, stdout);
  401.       }
  402.     fputs(suff, stdout);
  403.     ccnt += i;
  404.     }
  405.   }
  406.  
  407. /*
  408. ** output an error line
  409. */
  410. outerr(str) char *str; {
  411.   begpage(); fputs(str, stdout); ++lline;
  412.   }
  413.  
  414. /*
  415. ** require one expression only
  416. */
  417. onexpr() {
  418.   ep = lp;
  419.   expr(&field, &type);
  420.   if(atend(*ep)) return (YES);
  421.   experr();
  422.   return (NO);
  423.   }
  424.  
  425. /*
  426. ** output end of program and file
  427. */
  428. putend() {
  429.   item = EPROG; type = endt; field = endv; putrel();
  430.   item = EFILE; type = ABS;  field = 0;    putrel();
  431.   }
  432.  
  433. /*
  434. ** output entry points
  435. */
  436. putent() {
  437.   char *cp;
  438.   cp = st;
  439.   while(cp < stend) {
  440.     poll(YES);
  441.     if(*cp) {
  442.       if(cp[STFLAG] & EPBIT) {        /* entry point **/
  443.     item = ENAME;
  444.     strncpy(symbol, cp, MAXSYM + 1);
  445.     putrel();
  446.     }
  447.       }
  448.     cp += STENTRY;
  449.     }
  450.   }
  451.  
  452. /*
  453. ** output entry point or external reference
  454. */
  455. putex(cp, i) char *cp; int i; {
  456.   item = i;
  457.   type = cp[STFLAG] & RELBITS;
  458.   field = getint(cp + STVALUE);
  459.   strncpy(symbol, cp, MAXSYM + 1);
  460.   putrel();
  461.   }
  462.  
  463. /*
  464. ** output ent pnt and ext ref symbols
  465. */
  466. putexs() {
  467.   int i; char *cp;
  468.   ccnt = 0;                /* init for show() */
  469.   shell(0, stn - 1);            /* sort the symbols */
  470.   if(list && !begpage()) {++lline; puts("");}
  471.   for(i = 0; i < stn; ++i) {
  472.     poll(YES);
  473.     cp = stp[i];
  474.     if(list) show(cp);
  475.     if(cp[STFLAG] & XRBIT) putex(cp, XCHAIN);
  476.     if(cp[STFLAG] & EPBIT) putex(cp, EPOINT);
  477.     }
  478.   puts("");
  479.   }
  480.  
  481. /*
  482. ** output module name
  483. */
  484. putname() {
  485.   int i, j;
  486.   item = PNAME;
  487.   if(objfn[1] == ':') i = 2; else i = 0;
  488.   j = 0;
  489.   while(objfn[i] && objfn[i] != '.' && j < MAXSYM)
  490.     symbol[j++] = objfn[i++];
  491.   symbol[j] = NULL;
  492.   putrel();
  493.   }
  494.  
  495. /*
  496. ** output program size
  497. */
  498. putsz() {
  499.   item = PSIZE;
  500.   type = PREL;
  501.   field = loc;
  502.   putrel();
  503.   }
  504.  
  505. /*
  506. ** shell sort the symbols
  507. */
  508. shell(l, u) int l, u; {
  509.   int gap, i, j, k, jg;
  510.   gap = (u - l + 1) >> 1;
  511.   while(gap > 0) {
  512.     i = gap + l;
  513.     while(i <= u) {
  514.       j = i++ - gap;
  515.       while(j >= l) {
  516.     jg = j + gap;
  517.     if(strcmp(stp[j], stp[jg]) <= 0) break;
  518.     k = stp[jg]; stp[jg] = stp[j]; stp[j] = k;
  519.     j -= gap;
  520.     }
  521.       }
  522.     gap >>= 1;
  523.     }
  524.   }
  525.  
  526. /*
  527. ** show a symbol
  528. */
  529. show(cp) char *cp; {
  530.   char str[5];
  531.   begpage();
  532.   itox(getint(cp + STVALUE), str, 5); fputs(str, stdout);
  533.   if((cp[STFLAG] & RELBITS) == PREL) fputs("' ", stdout);
  534.   else fputs("  ", stdout);
  535.   fputs(cp, stdout);
  536.   ccnt += 6 + strlen(cp);
  537.   if(cp[STFLAG] & LABBIT) {putchar(':'); ++ccnt;}
  538.   if(cp[STFLAG] & EPBIT)  {putchar(":"); ++ccnt;}
  539.   if(cp[STFLAG] & XRBIT)  {fputs("##", stdout); ccnt += 2;}
  540.   if(ccnt < 60)
  541.     while(ccnt % 20) {putchar(' '); ++ccnt;}
  542.   else {puts(""); ++lline; ccnt = 0;}
  543.   }
  544.  
  545. /*
  546. ** find stsym in symbol table
  547. ** leave stptr pointing to desired or null entry
  548. ** return true if found, else false
  549. */
  550. stfind(){
  551.   char *start;
  552.   stptr = start = st + hash(stsym, stmax) * STENTRY;
  553.   while(*stptr) {
  554.     if(strcmp(stsym, stptr) == 0) return (YES);
  555.     if((stptr += STENTRY) >= stend) stptr = st;
  556.     if(stptr == start) break;
  557.     }
  558.   return (NO);
  559.   }
  560.     return (YES);
  561.     if((stptr += STENTRY) >= stend) stptr = st;
  562.     if(stptr == start) break;
  563.     }
  564.   ret