Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/oldas68/main.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1031 lines
23 KiB
C

/*
Copyright 1981
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
char *sccs "@(#)as68 - Mar 16, 1983";
/*
* a two pass relocatable assembler for the Motorola 68000 microprocessor
* Bill Allen
* Modified by Vicki Hutchison
* after any of this assembler is recompiled, it must be initialized
* before it will execute properly. To initialize, become super user
* and execute the command:
* as68 -i as68init
* where as68 is the newly compiled version of the assembler. With-
* out this initialization, the assembler will not run (probably bus
* error).
*/
/*
* Revisions :
*
* Added fix to make location relative equates
* correct even if branch optimization occurs. vlh 15-sep-82
* Recognizes commands in uppercase. vlh 17-sep-82
* Added recognization of upper case directives
* which do not have the preceding '.'. vlh 17-sep-82
* Added recognizing of ignored directives
* IDNT, ORG and MASK2. vlh 17-sep-82
* Added new directives XDEF, XREF. vlh 17-sep-82
* Added COMLINE and SECTION. vlh 20-sep-82
* Added new directive REG. vlh 21-sep-82
* Added new directives DCB and OFFSET. vlh 22-sep-82
* Recognizes branch extensions and takes
* the appropriate action. vlh 22-sep-82
* Added assembler directives ifeq, ifne,
* ifle, iflt, ifge, ifgt. vlh 23-sep-82
* Added character '$' to set of legitimate
* characters in a symbol. vlh 23-sep-82
* Added new ignored directive OPT. vlh 23-sep-82
* Recognizes non-opcodes starting in column 1
* as labels. vlh 23-sep-82
* Added conditional assembler directives
* ifc, ifnc. vlh 27-sep-82
* Major reworking of expression handler vlh 1-oct-82
* More revisions to expression stacks vlh 4-oct-82
* Added the recognition and handling of vlh 26-oct-82
* the 'illegal' instruction.
* Added handling of the jmp suffixes vlh 26-oct-82
* Fixed problem with -p flag and external vlh 27-oct-82
* variable listings.
* Added checking for legitimate command vlh 28-oct-82
* suffixes.
* Added comma as a legitimate register vlh 28-oct-82
* divisor for the REG directive.
* Fixed second pass error/instr len problem vlh 28-oct-82
* Added checking for invalid bit ranges. vlh 1-nov-82
* Added proper 2nd pass handling of the vlh 2-nov-82
* '*' symbol (avoid turning jsr to bra).
* Fixed first pass guess if operand is vlh 4-nov-82
* (rx,rx) instead of d(rx,rx).
* Check for appropriate range of 16-bit vlh 5-nov-82
* immediate date.
* Operand type check for shift/bit manip. vlh 5-nov-82
* Turn and/or/eor #xxx,sr/ccr into the vlh 5-nov-82
* corresponding immediate instruction.
* Generate an error when an illegal pc vlh 10-nov-82
* relative ea is specified.
* Ignore PAGE and TTL macros. vlh 21-dec-82
* Generate an error on ".bss\n.dc.b 1\n". vlh 7-jan-83
* Generate an error on "move ccr,??". vlh 19-jan-83
* Fixed problem of )* in expression. bea 9-mar-83
* .ds should be allowed inside .offset vlh 16-mar-83
*/
# include "as68.h"
char tfilname[] {"/tmp/a6xxxxA"}; /*temp file for it*/
char initfnam[] {"/lib/as68symb"}; /*initialize file name*/
char ldfn[40]; /*name of the relocatable object file*/
int brkln1 077777; /*pass 1 break line number for debugging*/
int opcval; /*opcode*/
int chmvq;
int hopd(), hend(), send(), horg(), sorg(), hequ(), hreg();
int hds(), sds();
int hdsect(), hpsect(), sdsect(), spsect();
int hsection(), ssection(), hoffset();
int hent(), hext();
int igrst();
int hbss(), sbss();
int heven(), seven();
int hdc(), sdc(), hdcb();
int hmask2(), hcomline(), hidnt(), httl(), hpage();
int hifeq(), hifne(), hiflt(), hifle(), hifgt(), hifge(), hendc();
int hifnc(), hifc(), hopt();
int (*p1direct[])() {
hopd, /*0*/
hend, /*1*/
hdsect, /*2*/
hpsect, /*3*/
hequ, /*4*/
hequ, /*5 .set same as .equ*/
0, /*6*/
0, /*7*/
hdc, /*8*/
hent, /*9*/
hext, /*10*/
hbss, /*11*/
hds, /*12*/
heven, /*13*/
horg, /*14*/
hmask2, /*15*/
hreg, /*16*/
hdcb, /*17*/
hcomline, /*18*/
hidnt, /*19*/
hoffset, /*20*/
hsection, /*21*/
hifeq, /*22*/
hifne, /*23*/
hiflt, /*24*/
hifle, /*25*/
hifgt, /*26*/
hifge, /*27*/
hendc, /*28*/
hifc, /*29*/
hifnc, /*30*/
hopt, /*31*/
httl, /*32*/
hpage, /*33*/
0};
int (*p2direct[])() {
0, /*0*/
send, /*1*/
sdsect, /*2*/
spsect, /*3*/
0, /*4*/
0, /*5*/
0, /*6*/
0, /*7*/
sdc, /*8*/
0, /*9*/
0, /*10*/
sbss, /*11*/
sds, /*12*/
seven, /*13*/
sorg, /*14*/
0, /*15*/
0, /*16*/
sdcb, /*17*/
sds, /*18 comline same as .ds.b*/
0, /*19*/
0, /*20*/
ssection, /*21*/
0, /*22*/
0, /*23*/
0, /*24*/
0, /*25*/
0, /*26*/
0, /*27*/
0, /*28*/
0, /*29*/
0, /*30*/
0, /*31*/
0, /*32*/
0, /*33*/
0};
char *ermsg[] {
"label redefined", /*1*/
"invalid label", /*2*/
"invalid opcode", /*3*/
"no label for opd", /*4*/
"opcode redefined", /*5*/
"illegal expr", /*6*/
"undefined in equate", /*7*/
0, /*8*/
"invalid first operand", /*9*/
"invalid second operand", /*10*/
"absolute value required", /*11*/
"no code or data allowed in offset",/*12*/
"undefined symbol", /*13*/
"illegal index register", /*14*/
"illegal constant", /*15*/
"illegal extension", /*16*/ /*[vlh]*/
"constant required", /*17*/
"illegal format", /*18*/
"illegal string", /*19*/
"illegal addressing mode", /*20*/
0, /*21*/
"illegal relative address", /*22*/
"invalid bit range", /*23*/
"illegal text delimiter", /*24*/
"unexpected endc", /*25*/
"endc expected", /*26*/
"relocation error", /*27*/
"symbol required", /*28*/
"bad use of symbol", /*29*/
"invalid data list", /*30*/
0, /*31*/
"missing )", /*32*/
"register required", /*33*/
"illegal size", /*34*/
"illegal 8-bit displacement", /*35*/
"illegal external", /*36*/
"illegal shift count", /*37*/
"invalid instruction length", /*38*/
"code or data not allowed in bss", /*39*/
"backward assignment to *", /*40*/
"illegal 16-bit displacement", /*41*/
"illegal 16-bit immediate", /*42*/
"illegal 8-bit immediate", /*43*/
0
};
int endit();
int rubout();
int symcon;
char endstr[] "end";
char equstr[] "equ";
char evnstr[] "even";
char orgstr[] "~.yxzorg";
int poslab;
char tlab1[NAMELEN];
int explmode; /*explicit mode length given*/
main(argc,argv)
char **argv;
{
register i, ttmp;
initflg = 0;
prtchidx = prtchars;
signal(2,rubout);
pitix = itbuf;
pexti = extbl;
ttmp = (STESIZE*SZMT) + 2;
bmte = sbrk(ttmp);
if(bmte&1)
bmte++; /*make it even*/
emte = bmte + ttmp - 2; /*end of main table*/
if(argc<=1) usage();
i = 1;
shortadr = -1; /*short addresses ok*/
while(argv[i][0] == '-') { /*may be print or initialize*/
switch(argv[i++][1]) {
case 'i': /*initialize the assembler*/
initflg++;
break;
case 'p': /*produce a listing*/
prtflg++;
break;
case 'u': /*make undefined symbols external*/
undflg++;
break;
case 'N': /*no branch optimization*/
didorg++;
break;
case 'L': /*long addresses only*/
shortadr = 0;
break;
default:
usage();
}
}
if(i>=argc) usage();
ifn=openfi(argv[i],0); /*open source file*/
setldfn(argv[i]); /*create relocatable object file name*/
lfn=openfi(ldfn,1); /*open loader file*/
itfn = gettempf(); /*get a temp file for it*/
itfnc = LASTCHTFN; /*remember last char for unlink*/
trbfn = gettempf(); /*temp for text relocation bits*/
trbfnc = LASTCHTFN;
dafn = gettempf(); /*temp for data binary*/
dafnc = LASTCHTFN;
drbfn = gettempf(); /*temp for data relocation bits*/
drbfnc = LASTCHTFN;
if(initflg) { /*initializing te main table*/
lmte=bmte; /*beginning main table*/
cszmt = SZMT; /*current size of main table*/
for(i=0; i<=SZIRT-2; i=+2) {
sirt[i] = &sirt[i]; /*initialize the initial ref tables*/
sirt[i+1] = 0;
oirt[i] = &oirt[i];
oirt[i+1] = 0;
}
/*make entries in main table for directives*/
mdemt("opd",0); /*opcode definition*/
mdemt(endstr,1); /*end statement*/
mdemt("data",2); /*dsect directive(code DATA based)*/
mdemt("text",3); /*psect directive(code TEXT based)*/
mdemt(equstr,4); /*equate*/
mdemt("set",5); /*.set - same as .equ*/
mdemt("dc",8); /*define byte*/
mdemt("globl",9); /*define global (public) symbols*/
mdemt("xdef",9); /*[vl]define global (public symbols*/
mdemt("xref",9); /*[vl]define global (public) symbols*/
mdemt("comm",10); /*define external symbols*/
mdemt("bss",11); /*block storage based*/
mdemt("ds",12); /*block storage based*/
mdemt(evnstr,13); /*round pc*/
mdemt(orgstr,14); /*internal org for *=n*/
mdemt("org",14); /*[vlh]*/
mdemt("mask2",15); /*[vl] assemble for mask2, ignore*/
mdemt("reg",16); /*[vlh] register equate*/
mdemt("dcb",17); /*[vlh] define block*/
mdemt("comline",18); /*[vlh] command line*/
mdemt("idnt",19); /*[vlh] relocateable id record, ignore*/
mdemt("offset",20); /*[vlh] define offsets*/
mdemt("section",21); /*[vlh] define sections*/
mdemt("ifeq",22); /*[vlh] ca if expr = 0*/
mdemt("ifne",23); /*[vlh] ca if expr != 0*/
mdemt("iflt",24); /*[vlh] ca if expr < 0*/
mdemt("ifle",25); /*[vlh] ca if expr <= 0*/
mdemt("ifgt",26); /*[vlh] ca if expr > 0*/
mdemt("ifge",27); /*[vlh] ca if expr >= 0*/
mdemt("endc",28); /*[vlh] end ca*/
mdemt("ifc",29); /*[vlh] ca if string compare*/
mdemt("ifnc",30); /*[vlh] ca if not string compare*/
mdemt("opt",31); /*[vlh] ignored, assemb options*/
mdemt("ttl",32); /*[vlh] ttl define, ignore*/
mdemt("page",33); /*[vlh] page define, ignore*/
}
else { /*not initializing*/
getsymtab(); /*read initialized main table*/
}
rlflg = TEXT; /*code initially TEXT based*/
inoffset = 0; /*[vlh]not in offset mode*/
loctr = 0; /*no generated code*/
ca = 0; /*[vlh]depth of conditional assembly*/
extindx = 0; /*no external symbols yet*/
p2flg = 0; /*pass 1*/
ca_true = 1; /*[vlh]true unless in side false case*/
absln = 1;
sbuflen = -1; /*no source yet*/
fchr = gchr(); /*get first char*/
if(!initflg) { /*not initializing*/
pack(orgstr,lmte);
orgptr = lemt(oirt,TRUE);
pack(endstr,lmte);
endptr = lemt(oirt,TRUE);
pack(equstr,lmte);
equptr = lemt(oirt,TRUE);
pack("add",lmte);
addptr = lemt(oirt,TRUE);
pack("addi",lmte);
addiptr = lemt(oirt,TRUE);
pack("addq",lmte);
addqptr = lemt(oirt,TRUE);
pack("sub",lmte);
subptr = lemt(oirt,TRUE);
pack("subi",lmte);
subiptr = lemt(oirt,TRUE);
pack("subq",lmte);
subqptr = lemt(oirt,TRUE);
pack("cmp",lmte);
cmpptr = lemt(oirt,TRUE);
pack("adda",lmte);
addaptr = lemt(oirt,TRUE);
pack("cmpa",lmte);
cmpaptr = lemt(oirt,TRUE);
pack("suba",lmte);
subaptr = lemt(oirt,TRUE);
pack("cmpm",lmte);
cmpmptr = lemt(oirt,TRUE);
pack("and",lmte);
andptr = lemt(oirt,TRUE);
pack("andi",lmte);
andiptr = lemt(oirt,TRUE);
pack("or",lmte);
orptr = lemt(oirt,TRUE);
pack("ori",lmte);
oriptr = lemt(oirt,TRUE);
pack("cmpi",lmte);
cmpiptr = lemt(oirt,TRUE);
pack("eor",lmte);
eorptr = lemt(oirt,TRUE);
pack("eori",lmte);
eoriptr = lemt(oirt,TRUE);
pack("move",lmte);
moveptr = lemt(oirt,TRUE);
pack("moveq",lmte);
moveqptr = lemt(oirt,TRUE);
pack("exg",lmte);
exgptr = lemt(oirt,TRUE);
pack("jsr",lmte);
jsrptr = lemt(oirt,TRUE);
pack("bsr",lmte);
bsrptr = lemt(oirt,TRUE);
pack("nop",lmte);
nopptr = lemt(oirt,TRUE);
pack(evnstr,lmte);
evenptr = lemt(oirt,TRUE);
}
mloop();
}
usage()
{
rpterr("Usage: as68 [-p] [-u] [-L] [-N] sourcefile\n");
endit();
}
/*main loop*/
mloop()
{
register i;
while(fchr!=EOF) {
if(absln>=brkln1) /*break for debugging the assembler*/
i=0;
fcflg = 0; /*first time thru expr pass one*/
cisit(); /*create it for one statement*/
}
opcpt = endptr;
hend();
}
#define NOCODE ((i>=0&&i<6)||i==9||i==11||i==12||i==16||(i>=20&&i<=30))
/* cond-directives, section, ds, set, equ, reg, globl, end, offset */
/*create intermediate text (it) for one statement*/
/* call with first character of statement in fchr*/
cisit()
{
register int *p1,*p2;
register int (*dirop)();
register int i, col1; /*[vlh] col1 labels in col 1...*/
char str[NAMELEN], *l;
ciss1:
immed[0] = immed[1] = indir[0] = indir[1] = numcon[0] = 0;
numcon[1] = numsym[0] = numsym[1] = numreg[0] = numreg[1]=0;
plevel = numops = opdix = explmode = 0;
cistop:
col1 = 1;
if(fchr==EOLC) {
fchr = gchr();
goto cistop;
}
if(fchr==' ') {
col1 = 0;
igblk();
if(fchr==EOLC) /*blank line*/
goto cistop;
peekc = fchr;
if (fchr != EOF) fchr = ' '; /* [vlh] catch eof... */
}
if(fchr==EOF) return;
if(fchr=='*') { /*ignore comments*/
fchr = gchr();
if(fchr=='=') { /*relocation counter assignment*/
fchr = gchr(); /*pass the =*/
horg(); /*output constants if not bss*/
}
igrst();
fcflg = 0; /*clear expr first time flag for next stmt*/
goto ciss1;
}
/* get the opcode and label*/
mode = 'w'; /*word mode*/
igblk(); /*ignore blanks*/
poslab = 1;
gterm(TRUE);
poslab = 0;
if(fchr==':' || fchr=='=') { /*there is a label*/
label:
col1 = 0;
if(itype!=ITSY) { /*not a symbol*/
uerr(2);
lbt[0] = 0; /*no label*/
}
else {
p2 = &lmte->name[0];
for(p1= &lbt[0]; p1 < &lbt[NAMELEN]; ) {
*p1++ = *p2++;
}
if(fchr==':') fchr=gchr(); /*ignore the colons*/
}
labl1:
ligblk();
if(fchr == EOF) return;
if(fchr == '*') {
igrst(); /*comment*/
goto labl1;
}
gterm(TRUE);
if(fchr==':' || fchr=='=') { /*another label*/
if(lbt[0]) {
strcpy(tlab1,lmte,NAMELEN); /*save current label */
dlabl(); /*define the last one*/
pack(tlab1,lmte); /*restor the old lable*/
}
goto label;
}
}
else {
lbt[0] = 0; /*no label*/
}
igblk();
if(fchr == '=')
goto label;
if(itype==ITSP) {
if(ival.wd2 == '=') {
hequ();
return;
}
}
if(itype!=ITSY) { /*not valid opcode*/
goto cisi3;
}
if (col1) { /* [vlh] could be a label save as is... */
l = &str;
strcpy(l,lmte->name,NAMELEN);
}
if((opcpt=lemt(oirt,TRUE))==lmte) { /*not in opcode table*/
if (col1) { /* [vlh] it's a label... */
strcpy(lmte->name,l,NAMELEN);
goto label;
}
cisi3:
if (ca_true) /* [vlh] report error if not in CA false */
xerr(3);
igrst();
return;
}
getmode(); /*look for .b .w or .l mode flag*/
if(opcpt->flags&OPDR) { /* its a directive*/
i = opcpt->vl1;
if (!ca_true && (i < LOW_CA || i > HI_CA)) { igrst(); return; }
if (inoffset) /* [vlh] */
if (!(NOCODE)) { /* can't generate code in offset */
xerr(12);
return;
}
dirop = p1direct[i]; /*call routine to handle directive*/
(*dirop)();
return;
}
else if (!ca_true) { /* [vlh] */
igrst();
return;
}
else if (inoffset) { /* [vlh] */
xerr(12);
return;
}
opcval = (opcpt->vl1); /*opcode*/
format = (opcpt->flags&OPFF); /*format of this instr*/
if (explmode)
if (!modeok()) { xerr(16); return; }
dlabl(); /*define label*/
opitb(); /*beginning of statement*/
if(format)
opito(); /*may have operands*/
else
igrst(); /*only comments*/
format = (opcpt->flags&OPFF); /* may have changed*/
/*end of statement*/
i = calcilen();
stbuf[1].itrl = i; /*assumed instruction length*/
stbuf[0].itrl = itwc; /*number of it entries*/
wostb(); /*write out statement buffer*/
loctr =+ i;
}
getmode()
{
if (fchr=='.') {
fchr = gchr();
switch (fchr) {
case 'b':
case 'B':
case 's':
case 'S':
modelen = 1;
mode = BYTE;
break;
case 'w':
case 'W':
modelen = 2;
mode = WORD;
break;
case 'l':
case 'L':
modelen = 4;
mode = LONG;
break;
default:
peekc = fchr;
fchr = '.';
goto getm1;
}
explmode++;
fchr = gchr();
igblk();
return;
}
getm1:
if(opcpt == exgptr) { /*length is long*/
modelen = 4;
mode = LONG;
}
else {
mode = WORD; /*default is word*/
modelen = 2;
}
}
/* check to be sure specified mode is legal */
modeok() /* [vlh] */
{
switch(format) {
case 0 :
case 14 :
case 18 :
return(FALSE);
case 13 :
case 15 :
case 20 :
case 21 :
return(modelen==1?FALSE:TRUE);
case 4 :
case 25 :
return(modelen==1?TRUE:FALSE);
case 7 :
case 9 :
return(modelen==2?FALSE:TRUE);
case 5 :
case 11 :
case 28 :
return(modelen==2?TRUE:FALSE);
case 6 :
return(modelen==4?FALSE:TRUE);
case 12 :
case 30 :
case 22 :
case 29 :
return(modelen==4?TRUE:FALSE);
default :
return(TRUE);
}
}
/* calculate the instruction length in bytes*/
calcilen()
{
register i,j;
register long l;
register char *p;
i = 2; /*all instrs at least 2 bytes*/
switch(format) {
case 20:
i =+ 2; /*for reg mask*/
case 1: /*two ea's -- one of which may be a reg*/
case 15:
case 30:
case 26:
case 5:
case 3:
case 21:
i =+ lenea(1);
case 16:
case 24:
case 25:
case 29:
i =+ lenea(0);
break;
case 9: /* [vlh] explicit jmp length... */
if (!explmode)
i =+ lenea(0);
else
return(mode==LONG?6:4); /*[vlh] explicit jmp.? */
break;
case 7:
i =+ (immed[0]) ? 2+lenea(1) : lenea(1);
break;
case 14:
case 11:
case 19:
i =+ 2; /*always 4 bytes*/
break;
case 6: /*relative branches*/
if(itwc == ITOP1+1) {
if(stbuf[ITOP1].itty == ITCN)
l = stbuf[ITOP1].itop;
else if(stbuf[ITOP1].itty == ITSY) {
p = stbuf[ITOP1].itop.ptrw2;
if(p->flags&SYDF)
l = p->vl1; /*symbol value*/
else
goto loffst;
}
else {
goto loffst;
}
l =- (loctr+2);
if(l<=127 && l>=-128) /*8 bit offset*/
break;
}
loffst:
if (!explmode || modelen > 1) /*[vlh] recognize br extensions*/
i =+ 2; /*long offset for branches*/
break;
case 2:
i =+ (mode==LONG?4:2) + lenea(1);
break;
case 23:
if(immed[0])
i =+ (mode==LONG?4:2);
case 17:
case 22:
i =+ lenea(1);
break;
case 8:
if(numops==1) /*memory shift instruction*/
i =+ shiftea(0);
break;
}
return(i);
}
/* calc the length of an effective address*/
lenea(lidx)
{
register i;
if(immed[lidx])
return(mode==LONG?4:2);
return(shiftea(lidx));
}
shiftea(lidx)
{
if(indir[lidx])
return((numcon[lidx] || numsym[lidx]) ? 2 : 0);
if(numsym[lidx] || numcon[lidx])
return((!shortadr || numcon[lidx]==2) ? 4 : 2);
return(0);
}
/*
*define a label if there is one to define
* call with:
* label name in lbt if it exists
* else lbt[0] == 0
*/
dlabl()
{
register i;
if(lbt[0]) { /*got a label*/
pack(lbt,lmte); /*put label in main table*/
lblpt=lemt(sirt,FALSE); /*look up label*/
if(lblpt != lmte) { /*symbol entered previously*/
if(lbt[0] == '~') { /*local symbol -- may be duplicate*/
lblpt = lmte;
mmte();
}
else {
if(lblpt->flags&SYXR) {
uerr(29);
lblpt = 0;
return;
}
if((lblpt->flags)&SYDF) {
uerr(1);
lblpt = 0;
return;
}
}
}
else {
mmte(); /*make label entry in main table*/
}
lblpt->flags =| SYDF; /*label is now defined*/
lblpt->flags =| (rlflg==DATA)?SYRA:(rlflg==BSS)?SYBS:SYRO;
lblpt->vl1 = loctr; /*label value*/
}
else
lblpt = 0;
}
/*
* output it for operands
* gets intput from gterm
* puts output in stbuf using itwc as an index
* itwc should point at the next entry to be made in stbuf
*/
opito()
{
register lopcomma;
lopcomma = symcon = chmvq = 0;
numops++; /*count first operand*/
while(1) {
starmul = symcon; /*star is multiply op if flag is set*/
if(fchr=='\'' || fchr=='"')
lopcomma = 0;
gterm(FALSE); /*get a term*/
if(itwc==ITOP1 && format==CLRFOR && opcval==CLRVAL)
chgclr();
opitoo(); /*output it for one operand*/
if(itype==ITSP && ival.wd2==',') {
if (plevel==1 && !numcon[opdix]) /* [vlh] */
numcon[opdix] = 1;
if(lopcomma)
uerr(30);
lopcomma++;
igblk(); /*ignore blanks for 68000 C compiler*/
}
else
lopcomma=0;
if(ival==EOLC && itype==ITSP) /*end of operands*/
break;
if(fchr==EOLC) {
fchr=gchr();
break;
}
}
if(chmvq) /*changed move to moveq*/
if(numops!=2 || immed[1] || indir[1] || numcon[1] || numsym[1] ||
numreg[1]>=AREGLO) {
stbuf[2].itop.ptrw2 = moveptr; /*change it back*/
opcpt = moveptr;
}
if (stbuf[2].itop.ptrw2==cmpptr) /* [vlh] cmp -> cmpm ?? */
if (numreg[0] && numreg[1] && indir[0] && indir[1]) {
stbuf[2].itop.ptrw2 = cmpmptr;
opcpt = cmpmptr;
}
if(lopcomma)
uerr(30);
}
/* change clr.l An to suba.l An,An*/
chgclr()
{
register char *p;
if(itype==ITSY) { /*first op is symbol*/
p = lemt(sirt,FALSE);
if(p==lmte)
return;
if(!(p->flags&SYER) || p->vl1<AREGLO) /*not A reg*/
return;
opcpt = subaptr; /*make it a suba instr*/
opitb();
opitoo(); /*output first operand -- An*/
itype = ITSP;
ival = ',';
opitoo(); /*output a comma*/
itype = ITSY; /*now the A reg again*/
}
}
/*output it for one operand*/
opitoo()
{
register i;
register char *sp;
symcon = 0;
if(itype==ITSP) { /*special symbol*/
if(ival.wd2==',' && !plevel) { /* another operand */
numops++;
if(!opdix)
opdix++;
}
if(ival.wd2==')')
symcon = 1; /* star is multiply */
if(ival.wd2==' ') { /*end of operands*/
while(fchr!=EOLC) /*ignore rest of statement*/
fchr=gchr();
return;
}
if(ival.wd2==EOLC)
return;
}
else /*symbol or constant*/
symcon = 1;
if(itwc >= STMAX) { /*it overflow*/
rpterr("i.t. overflow\n");
abort();
}
pitw->itty = itype; /*type of it entry*/
/*put symbol in it buffer*/
if(itype==ITSY) {
sp=lemt(sirt,FALSE); /*look up it main table*/
pitw->itop.ptrw2 = sp; /*ptr to symbol entry*/
if(sp==lmte) /*first occurrance*/
mmte();
itwc++; /*count entries in it buffer*/
pitw++;
if(!(sp->flags&SYER)) /*is it a register?*/
numsym[opdix]++;
else /*yes, a register*/
numreg[opdix] = sp->vl1;
return;
}
else if(itype == ITCN ) {
if(ival.wd1 && ival.wd1 != -1)
numcon[opdix] = 2;
else if(!numcon[opdix])
numcon[opdix] = 1;
if(numops == 1)
tryquick();
}
/* special characters and constants*/
pitw->itop = ival;
pitw->itrl = reloc;
itwc++;
pitw++;
}
/* change add into addq and sub into subq if possible*/
tryquick()
{
register char *p;
register long l;
if(fchr!=',' || !immed[0])
return;
l = ival;
if(itwc != ITOP1+1) {
if(itwc!=ITOP1+2 || stbuf[ITOP1+1].itty!=ITSP ||
stbuf[ITOP1+1].itop.wd2 != '-')
return;
l = -l;
}
p = stbuf[2].itop.ptrw2;
if(p==moveptr) {
if(explmode && modelen != 4) /*dont change .w or .b*/
return;
if(l>=-128 && l<=127) {
stbuf[2].itop.ptrw2 = moveqptr;
opcpt = moveqptr;
chmvq++;
}
return;
}
if(l<=0 || l>8) {
return;
}
if(p==addptr || p==addiptr) {
stbuf[2].itop.ptrw2 = opcpt = addqptr;
}
else if(p==subptr || p==subiptr) {
stbuf[2].itop.ptrw2 = opcpt = subqptr;
}
}
strcpy(astr1, astr2, alen)
char *astr1, *astr2;
int alen;
{
register char *str1, *str2;
register int len;
str1 = astr1;
str2 = astr2;
len = alen;
while (--len >= 0)
*str1++ = *str2++;
}
/* index - find the index of a character in a string*/
/* This is identical to Software Tools index.*/
index(str,chr) /* returns index of c in str or -1*/
char *str; /* pointer to string to search*/
char chr; /* character to search for*/
{
register char *s;
register int i;
for( s = str, i = 0; *s != '\0'; i++ )
if( *s++ == chr )
return(i);
return(-1);
}