/* Copyright 1981 Alcyon Corporation 8716 Production Ave. San Diego, Ca. 92121 */ /* Pass 1 and pass 2 directive handling routines */ /* code to handle conditional assembly directives */ #include "as68.h" #include "cout.h" long lseek(); int p1gi(); int p2gi(); int igrst(); /*directive to define an opcode*/ hopd() { if(!lbt[0]) { xerr(4); /*no label*/ return; } setname(); /*move label into main table*/ if((lblpt=lemt(oirt,TRUE))!=lmte) { xerr(5); /*opcode redefined*/ return; } mmte(); /*make main table entry*/ expr(&p1gi); /*get instruction format*/ if(itype!=ITCN || ival<0 || ival>OPFF) { xerr(18); /*illegal format specifier*/ return; } lblpt->flags =| ival|SYIN; /*remember format*/ if(fchr != ',') { /*field separator*/ xerr(10); return; } expr(&p1gi); /*get opcode value*/ if(itype != ITCN) { xerr(17); /*not a constant*/ return; } lblpt->vl1 = ival; /*put value in main table*/ igrst(); /*ignore rest of statement-comment*/ } /* equate directive*/ hequ() { if(lbt[0] == 0) { xerr(4); /*no label*/ return; } setname(); if((lblpt=lemt(sirt,FALSE))!=lmte) { /*aready there*/ if(lbt[0] == '~') { /*local symbol*/ lblpt = lmte; mmte(); } } else mmte(); if(lblpt->flags&SYXR) { xerr(29); return; } lblpt->flags =| SYDF|SYEQ; /*defined & equate*/ equflg = 1; modelen = 4; expr(&p1gi); equflg = 0; if(itype == ITSY && ival.ptrw2->flags&SYER) { lblpt->flags =| SYER; /*equated register*/ ival = ival.ptrw2->vl1; } else if(itype != ITCN) { xerr(7); /*not a constant*/ return; } if (inoffset && reloc != ABS) { /* [vlh] */ xerr(11); return; } if(initflg) /*doing symbol table initialization*/ lblpt->flags =| SYIN; /*internal symbol*/ lblpt->vl1 = ival; if(reloc == DATA) /*check relocation*/ { lblpt->flags =| SYRA; /*DATA relocatable*/ } else if(reloc == TEXT) lblpt->flags =| SYRO; /*TEXT relocatable*/ else if(reloc == BSS) lblpt->flags =| SYBS; /*BSS relocatable*/ else if(fchr==',' && (fchr=gchr())=='r') lblpt->flags =| SYER; /*equated register*/ if (refpc) /*[vlh] flag directive is pc relative */ lblpt->flags =| SYPC; igrst(); } /* process dsect directive*/ hdsect() { dorlst(DATA); } dorlst(xrtyp) { inoffset = 0; /* [vlh] offset mode terminated my sect directive */ chkeven(); /* May need to make pc even */ dlabl(); /*define label on old base if there is one*/ savelc[rlflg] = loctr; /*save old base relocation*/ rlflg = xrtyp; loctr = savelc[xrtyp]; /*set new base relocation ctr*/ opitb(); stbuf[0].itrl = itwc; wostb(); igrst(); } /*process psect directive*/ hpsect() { dorlst(TEXT); } hbss() { dorlst(BSS); } /*make pc even*/ heven() { modelen = 2; /*Try to figure this one out...*/ if(loctr&1) { /*have to make it even*/ dorlst(rlflg); } else { igrst(); } } /*process globl directive*/ hent() { while(1) { gterm(TRUE); /*get entry symbol*/ if(itype!=ITSY) { /*error if not symbol*/ xerr(28); return; } if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/ mmte(); /*not there, make new entry*/ else if(lblpt->flags&SYER) /*already there*/ uerr(29); lblpt->flags =| SYGL; /*symbol is an entry*/ if(lblpt->flags&SYXR) { /*been thru hext code*/ lblpt->flags =& ~(SYXR|SYDF); /*reset for init of .comm*/ } if (inoffset && reloc != ABS) { /* [vlh] */ xerr(11); return; } if(fchr == ',') /*skip ',' between entries*/ fchr = gchr(); else { igrst(); /*statement finished*/ return; } } } /*process comm directive*/ hext() { gterm(TRUE); /*get external symbol*/ if(itype!=ITSY) { /*error if not symbol*/ xerr(28); return; } if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/ mmte(); /*not there, make new entry*/ else if(lblpt->flags&SYDF && (lblpt->flags&SYXR)==0) /*already there*/ uerr(29); lblpt->flags =| SYXR | SYDF; /*symbol is an external*/ mkextidx(lblpt); /*put into external table*/ if(fchr == ',') { /*skip ',' between operands*/ fchr = gchr(); gterm(TRUE); if(itype != ITCN) { xerr(17); return; } lblpt->vl1.wd1 = ival; /* # bytes of storage required*/ } else lblpt->vl1.wd1 = 1; /* default # bytes*/ igrst(); } mkextidx(p) struct symtab *p; { if(extindx >= EXTSZ) { /*check for overflow of external symbol tbl*/ rpterr("overflow of external table\n"); endit(); } p->vl1.wd2 = pexti - extbl; /* external symbol index #*/ *pexti++ = p; /*save external in external table*/ extindx++; } /* end statement*/ hend() { register short i; register int j; inoffset = 0; /*[vlh] turn off inoffset mode*/ lblpt = 0; /*no label*/ opitb(); /*output beginning of statement*/ igrst(); /* [vlh] ignore operands */ stbuf[0].itrl = itwc; /*number of it entries*/ wostb(); /*write out statement buffer*/ for(i=0; i1 && loctr&1) { pi = opcpt; opcpt = evenptr; opitb(); stbuf[0].itrl = itwc; wostb(); opcpt = pi; loctr++; } } /* define byte directive*/ hdc() { chkeven(); hdata(modelen); } /* * define bytes or words of data * call with: * 1 => defining bytes * 2 => defining words * 4 => defining long words */ hdata(mul) { dlabl(); /*define label*/ opitb(); /*beginning of statement*/ numops = 0; /*initialize count for number of operands*/ opito(); /*output it for operands*/ stbuf[0].itrl = itwc; /* # of it entries*/ wostb(); /*write out statement buffer*/ loctr =+ numops*mul; /* count by bytes or words*/ } /* handle org statement*/ horg() { register i; if(rlflg==TEXT && loctr!=0) didorg++; /*can't do branch optimization as separate pass now*/ expr(&p1gi); /*value of new relocation counter*/ if(reloc != rlflg && reloc != ABS) { xerr(27); return; } if(ival < loctr) { xerr(40); /*trying to go backwards*/ return; } opcpt = orgptr; /*org directive for pass 2*/ opitb(); opitoo(); stbuf[0].itrl = itwc; wostb(); loctr = ival; dlabl(); /*define label*/ } /* Assemble for mask2 (R9M), ignore... */ hmask2() /* [vlh] */ { igrst(); } /* Define register list */ hreg() /* [vlh] */ { int mask; if(lbt[0]==0) { xerr(4); /*no label*/ return; } setname(); /*move label into main table*/ if((lblpt=lemt(sirt,FALSE))!=lmte) { xerr(5); /*opcode redefined*/ return; } if (inoffset) if (reloc != ABS) { xerr(11); return; } mmte(); /*make main table entry*/ if ((mask = mkmask()) == -1) { xerr(6); return; } lblpt->flags =| SYDF|SYEQ|SYRM; /* register mask, defined & equated */ lblpt->vl1 = mask; igrst(); } int regmsk[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200, 0100,040,020,010,4,2,1}; /* make a register mask for the reg routine */ mkmask() /* [vlh] */ { register int *p, i, j, mask; p = ®msk; mask = 0; while ((i = chkreg()) != -1) { if (fchr == '-') { fchr = gchr(); if ((j = chkreg()) == -1) { xerr(40); return(-1); } while (i <= j) mask =| p[i++]; } else mask =| p[i]; if (fchr != '/' && fchr != ',') break; /*[vlh] Signetics fix*/ fchr = gchr(); } return(mask); } /* get a register # from file, return -1 if none or illegal */ chkreg() /* [vlh] */ { register int i, j; i = j = 0; if (fchr == 'a' || fchr == 'A') i = 8; else if (fchr != 'd' && fchr != 'r' && fchr != 'D' && fchr != 'R') return(-1); fchr = gchr(); do { j = (j*10) + (fchr - '0'); fchr = gchr(); } while (isdigit(fchr)); if (j < 0 || j > AREGHI) return(-1); i =+ j; if (i >= 0 && i <= AREGHI) return(i); else return(-1); } /* Define constant block */ hdcb() /* [vlh] */ { chkeven(); /* on even boundary if not byte block. */ dlabl(); /* define label... */ opitb(); opito(); stbuf[0].itrl = itwc; numops = stbuf[ITOP1].itop; loctr =+ numops * modelen; wostb(); /* write out statement buffer */ } /* Command line, similar to ds.b */ hcomline() /* [vlh] */ { dlabl(); /*define label maybe*/ modelen = 1; /* byte store... */ opitb(); /*output it for beginning of statement*/ refpc = 0; expr(&p1gi); if(itype!=ITCN) { xerr(17); /*must be constant*/ return; } if(reloc != ABS) { xerr(9); /*must be absolute*/ return; } opitoo(); /*output one operand*/ stbuf[0].itrl = itwc; wostb(); /*write out statement buffer*/ loctr =+ ival; igrst(); } /* Relocateable id record, ignore */ hidnt() /* [vlh] */ { igrst(); } /* Define offsets */ hoffset() /* [vlh] */ { inoffset = 1; expr(&p1gi); /* get new location counter */ if (itype != ITCN) { xerr(17); /* constant required */ return; } if (reloc != ABS) { xerr(9); /* must be absolute */ return; } loctr = ival; igrst(); } /* define sections: map to bss, text and data */ hsection() /* [vlh] */ { inoffset = 0; /* reseting section turns off offset mode */ dlabl(); /* define label on old base if there is one */ savelc[rlflg] = loctr; /* save old base relocation */ opitb(); /* intermediate table... */ expr(&p1gi); /* get section # */ if (itype != ITCN) { xerr(17); /* must be a constant */ return; } if (ival > 15 || ival < 0) { xerr(9); /* proper range 0..15 */ return; } if (ival==14) rlflg = DATA; else if (ival==15) rlflg = BSS; else rlflg = TEXT; loctr = savelc[rlflg]; stbuf[3].itop = loctr; /* pass 1 location counter */ stbuf[3].itrl = rlflg; /* relocation base */ stbuf[0].itrl = itwc; wostb(); igrst(); } /* hopt -- ignore, set up assembler options */ hopt() /* vlh */ { igrst(); } /**** Second pass directive handling routines ****/ /* second pass end statement*/ send() { register int i; savelc[rlflg] = loctr; if(savelc[TEXT]&1) { rlflg = TEXT; outbyte(0,DABS); savelc[TEXT]++; } if(savelc[DATA]&1) { rlflg = DATA; outbyte(0,DABS); savelc[DATA]++; } if(savelc[BSS]&1) { savelc[BSS]++; } ival = 0; reloc = ABS; ckeop(9); print(0); cpdata(); /*copy data to loader file*/ osymt(); /*output symbol table*/ myfflush(&tbuf); /*flush text relocation bits*/ cprlbits(); /*copy relocation bits*/ myfflush(&lbuf); i = (sizeof couthd.ch_magic) + 3*(sizeof couthd.ch_tsize); if((lseek(lfn,(long)i,0) == -1) || write(lfn,&stlen,4) != 4) rpterr("I/O error on loader output file\n"); endit(); /*end*/ } /*second pass define storage - ds*/ sds() { print(0); if(rlflg == TEXT || rlflg==DATA) { expr(&p2gi); if(itype != ITCN) { uerr(13); return; } ival =* modelen; while(ival) { outbyte(0,DABS); loctr++; ival--; } } else loctr =+ stbuf[ITOP1].itop*modelen; /*reserve storage*/ } /* second pass - define block storage, initialized */ sdcb() /* [vlh] */ { register int pfg, i, hflg, len; expr(&p2gi); if (itype != ITCN || reloc != ABS) { uerr(13); /* must be absolute constant */ return; } len = ival; expr(&p2gi); if (modelen==1 && (ival<-128 || ival>=256 || reloc != ABS)) { uerr(20); ival = 0; reloc = ABS; } while (len--) { if (modelen==1) { if (!hflg) { ins[i].hibyte = ival; outbyte(ival.wd2,DABS); hflg++; } else { ins[i++].lobyte = ival; outbyte(ival.wd2,DABS); hflg=0; } goto sdbl2; } else if (modelen==2) { sdbl1: ins[i++] = ival.wd2; outword(ival.wd2, reloc); sdbl2: if (i>3) { instrlen = i*2; print ((pfg++) ? 2 : 1); loctr =+ instrlen; i=0; } } else { /* long word... */ ins[i++] = ival.wd1; outword(ival.wd1,LUPPER); goto sdbl1; } } if (i) { /* more printing */ instrlen = i*2 - hflg; print ((pfg) ? 2 : 1); loctr =+ instrlen; } } /*second pass data*/ sdsect() { savelc[rlflg] = loctr; rlflg = DATA; loctr = savelc[DATA]; print(0); /*print the new location counter*/ } /*second pass text*/ spsect() { savelc[rlflg] = loctr; rlflg = TEXT; loctr = savelc[TEXT]; print(0); /*print the new location counter*/ } sbss() { savelc[rlflg] = loctr; rlflg = BSS; loctr = savelc[BSS]; print(0); /*print the new location counter*/ } /* make loctr even*/ seven() { if(loctr&1) { if(rlflg==TEXT || rlflg==DATA) outbyte(0,DABS); loctr++; } print(0); } /* second pass org*/ sorg() { long l; if(rlflg==TEXT || rlflg==DATA) { /*must put out zeros*/ l = stbuf[ITOP1].itop - loctr; /*# zeroes to output*/ ins[0] = 0; print(1); while(l > 0) { outbyte(0,DABS); loctr++; l--; } } else { /*BSS*/ loctr = stbuf[ITOP1].itop; /*new location counter*/ print(0); } } /* *second pass define data (words or bytes) * call with * 2 => defining words * 1 => defining bytes * 4 => defining long words */ sdata(dtyp) { register pfg,i; register hflg; hflg = i = pfg = 0; while(1) { expr(&p2gi); /*evaluate expression*/ if(pitw < pnite) pitw--; /*expr passed a token*/ if(itype!=ITCN && reloc != EXTRN) { /*must be constant*/ uerr(13); ival=0; reloc = ABS; } if(reloc == EXTRN) reloc = (extref<<3)|EXTVAR; /*gen extern reference*/ if(dtyp==1) { /*defining a byte*/ if(ival<-128 || ival>=256 || reloc!=ABS) { /*not a byte*/ uerr(20); ival=0; reloc = ABS; } if(!hflg) { ins[i].hibyte = ival; outbyte(ival.wd2,DABS); hflg++; } else { ins[i++].lobyte = ival; hflg = 0; outbyte(ival.wd2,DABS); } goto sdal2; } else if(dtyp == 2) { /*defining a word*/ sdal1: ins[i++] = ival.wd2; outword(ival.wd2, reloc); sdal2: if(i>3) { instrlen = i*2; print ((pfg++) ? 2 : 1); loctr =+ instrlen; i=0; } } else { /*long words*/ ins[i++] = ival.wd1; outword(ival.wd1,LUPPER); goto sdal1; } if(!ckeop(15)) /*should be end of operand*/ return; pitw++; if(ckein()) { if(hflg) { ins[i++].lobyte = 0; } if(i) { /*more printing*/ instrlen = i*2 - hflg; print ((pfg) ? 2 : 1); loctr =+ instrlen; } return; } } } sdc() { sdata(modelen); } ssection() /* [vlh] */ { int sect; sect = stbuf[3].itrl; if (sect==DATA) sdsect(); else if (sect==BSS) sbss(); else spsect(); } /*define word statement*/ sdw() { sdata(0); /*defining words*/ } /**** Conditional assembly directives ****/ hifeq() /* [vlh] */ { if (!acok()) return; if (ival) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifne() /* [vlh] */ { if (!acok()) return; if (!ival) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hiflt() /* [vlh] */ { if (!acok()) return; if (ival >= 0) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifle() /* [vlh] */ { if (!acok()) return; if (ival > 0) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifgt() /* [vlh] */ { if (!acok()) return; if (ival <= 0) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifge() /* [vlh] */ { if (!acok()) return; if (ival < 0) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifc() /* [vlh] */ { if (!cmp_ops()) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hifnc() /* [vlh] */ { if (cmp_ops()) { if (ca_true) ca_level = ca; ca_true = 0; } ca++; } hendc() /* [vlh] */ { if (!ca) { xerr(25); /* unexpected endc */ return; } ca--; if (!ca_true) if (ca_level == ca) ca_true = 1; igrst(); } hpage() { opitb(); /* Output beginning */ wostb(); /* Write out buffer */ igrst(); /* Ignore rest of line */ } spage() { print(0); /* Print the directive */ xline = LPP; /* Force page on next print */ page(); } acok() { expr(&p1gi); if (itype != ITCN) { xerr(7); /* must be a constant */ return(0); } if (reloc != ABS) { xerr(11); /* must be absolute, no forward references */ return(0); } igrst(); return(1); } cmp_ops() { char str1[25], str2[25]; register int len1, len2; if (fchr != '\'') { xerr(9); return(0); } len1 = len2 = 0; while (fchr = gchr()) { if (fchr == '\'') break; if (fchr == EOLC) return(0); str1[len1++] = fchr; } if ((fchr=gchr()) != ',') { xerr(9); return; } if ((fchr=gchr()) != '\'') { xerr(10); return;} while (fchr = gchr()) { if (fchr == '\'') break; if (fchr == EOLC) return(0); str2[len2++] = fchr; } igrst(); if (len1 != len2) return(0); str1[len1] = str2[len2] = NULL; if (strcmp(str1,str2) == 0) return(1); return(0); } strcmp(s,t) register char *s, *t; { for( ; *s == *t; s++, t++ ) if( *s == '\0' ) return(0); return( *s - *t ); }