mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
888 lines
24 KiB
C
888 lines
24 KiB
C
/*
|
|
Copyright 1983
|
|
Alcyon Corporation
|
|
8716 Production Ave.
|
|
San Diego, Ca. 92121
|
|
*/
|
|
|
|
char *version = "@(#)main.c 1.5 12/28/83";
|
|
|
|
/*
|
|
* 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).
|
|
*/
|
|
|
|
#include "as68.h"
|
|
#include "def.h"
|
|
#ifndef DECC
|
|
# include <signal.h>
|
|
#else
|
|
# include "Isignal"
|
|
# define strcpy rstrcpy
|
|
#endif
|
|
|
|
/*sw
|
|
* Define Temporary and Init file names per O/S. We use code here to
|
|
* allow re-directing temp files and the init file via command line
|
|
* switches.
|
|
*/
|
|
/************************************/
|
|
#ifdef CPM /* CPM is easy */
|
|
char *tdname = ""; /* Temp files in same directory */
|
|
char *idname = "0:"; /* Init file in user 0 */
|
|
#endif /************************************/
|
|
#ifdef WHITESM /* On whitesmith's VMS systems */
|
|
char *tdname = ""; /* Temp files in same directory */
|
|
char *idname = "bin:"; /* Init file in "bin:" */
|
|
#endif /************************************/
|
|
#ifdef UNIX /* UNIX systems are different */
|
|
char *tdname = "/tmp/"; /* Temp files in /tmp */
|
|
char *idname = "/lib/"; /* Init file in /lib */
|
|
#endif /************************************/
|
|
char tfilebase[] = {"a6AXXXXXX"}; /* Temp file basename */
|
|
char initbase[] = {"as68symb.dat"}; /* Init file basename */
|
|
/************************************/
|
|
|
|
#define INIT(op,ptr) pack(op,lmte); ptr=lemt(TRUE,oirt)
|
|
|
|
main(argc,argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
register short i, ttmp;
|
|
register long longtmp;
|
|
|
|
nerror = initflg = 0;
|
|
prtchidx = prtchars;
|
|
|
|
if( signal(SIGINT,SIG_IGN) != SIG_IGN ) /*[mac] 4.2a*/
|
|
signal(SIGINT,rubout);
|
|
if( signal(SIGQUIT,SIG_IGN) != SIG_IGN )
|
|
signal(SIGQUIT,rubout);
|
|
if( signal(SIGHUP,SIG_IGN) != SIG_IGN )
|
|
signal(SIGHUP,rubout);
|
|
signal(SIGTERM,rubout);
|
|
|
|
pitix = itbuf;
|
|
pexti = extbl;
|
|
#ifndef DECC
|
|
ttmp = (STESIZE*SZMT) + 2;
|
|
bmte = sbrk(ttmp);
|
|
longtmp = bmte; /* 11 apr 83, for vax */
|
|
if(longtmp&1L) /* 11 apr 83, for vax */
|
|
bmte++; /*make it even*/
|
|
emte = bmte + ttmp - 2; /*end of main table*/
|
|
#endif
|
|
if(argc<=1)
|
|
usage();
|
|
i = 1;
|
|
shortadr = 0; /*long addresses...*/
|
|
while(argv[i][0] == '-') { /*may be print or initialize*/
|
|
switch(argv[i++][1]) {
|
|
|
|
case 'a': /*[vlh] 4.2, short addresses only*/
|
|
shortadr = -1;
|
|
break;
|
|
|
|
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*/
|
|
case 'n': /*sw */
|
|
didorg++;
|
|
break;
|
|
|
|
case 'L': /*4.2 OBSOLETE, long addresses only*/
|
|
case 'l': /*sw */
|
|
shortadr = 0;
|
|
break;
|
|
|
|
case 'T': /*generating code suitable for the 68010*/
|
|
case 't': /*sw Why is this a switch? */
|
|
m68010++;
|
|
break;
|
|
|
|
case 'f': /*sw Redirect temp files */
|
|
tdname = argv[i++];
|
|
break;
|
|
|
|
case 's': /*sw Change symbol table prefix */
|
|
idname = argv[i++];
|
|
break;
|
|
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
if(i>=argc)
|
|
usage();
|
|
sfname = argv[i]; /* Remember source filename */
|
|
ifn=openfi(argv[i],0,0); /*open source file*/
|
|
setldfn(argv[i]); /*create relocatable object file name*/
|
|
lfn=openfi(ldfn,1,1); /*open loader file*/
|
|
|
|
tfilname[0] = '\0'; /* Init for strcat */
|
|
initfnam[0] = '\0'; /* */
|
|
strcat(tfilname,tdname); /*sw Build temp file */
|
|
strcat(tfilname,tfilebase); /* names */
|
|
mktemp(tfilname); /* Make it unique */
|
|
tfilptr = &tfilname[strlen(tfilname)-1] - 6; /* Points to 'A' in name */
|
|
strcat(initfnam,idname); /* Build Symbol file */
|
|
strcat(initfnam,initbase); /* name */
|
|
|
|
#ifdef DECC
|
|
if(prtflg) { /* open file for assembler listing */
|
|
setlsfn(argv[i]);
|
|
stdofd = openfi(lsfn,1,0);
|
|
sptr = fdopen(stdofd,"w");
|
|
}
|
|
else
|
|
sptr = fdopen(1,"w");
|
|
#endif
|
|
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;
|
|
#ifndef DECC
|
|
ttmp = (STESIZE*SZMT) + 2;
|
|
bmte = sbrk(ttmp-1);
|
|
longtmp = bmte; /* 11 apr 83, for vax */
|
|
if(longtmp&1L) /* 11 apr 83, for vax */
|
|
bmte++; /*make it even*/
|
|
emte = bmte + ttmp - 2; /*end of main table*/
|
|
#endif
|
|
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); /*[vlh]define global (public) symbols*/
|
|
mdemt("xref",9); /*[vlh]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(orgstr1,14); /*[vlh] internal, *= */
|
|
mdemt(orgstr2,14); /*[vlh] org location, also *= */
|
|
mdemt("mask2",15); /*[vlh] 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*/
|
|
INIT(orgstr2,orgptr);
|
|
INIT(endstr,endptr);
|
|
INIT(equstr,equptr);
|
|
INIT("add",addptr);
|
|
INIT("addi",addiptr);
|
|
INIT("addq",addqptr);
|
|
INIT("sub",subptr);
|
|
INIT("subi",subiptr);
|
|
INIT("subq",subqptr);
|
|
INIT("cmp",cmpptr);
|
|
INIT("adda",addaptr);
|
|
INIT("cmpa",cmpaptr);
|
|
INIT("suba",subaptr);
|
|
INIT("cmpm",cmpmptr);
|
|
INIT("and",andptr);
|
|
INIT("andi",andiptr);
|
|
INIT("or",orptr);
|
|
INIT("ori",oriptr);
|
|
INIT("cmpi",cmpiptr);
|
|
INIT("eor",eorptr);
|
|
INIT("eori",eoriptr);
|
|
INIT("move",moveptr);
|
|
INIT("moveq",moveqptr);
|
|
INIT("exg",exgptr);
|
|
INIT("jsr",jsrptr);
|
|
INIT("bsr",bsrptr);
|
|
INIT("nop",nopptr);
|
|
INIT(evnstr,evenptr);
|
|
}
|
|
mloop();
|
|
}
|
|
|
|
usage()
|
|
{
|
|
#ifndef CPM
|
|
rpterr("Usage: as68 [-p] [-u] [-L] [-N] sourcefile\n");
|
|
#else
|
|
rpterr("Usage: as68 [-p] [-u] [-l] [-n] [-s d:] [-f d:] sourcefile\n");
|
|
#endif
|
|
endit();
|
|
}
|
|
|
|
|
|
/*main loop*/
|
|
mloop()
|
|
{
|
|
register short 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 short *p1,*p2;
|
|
register short (*dirop)();
|
|
register short 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] = (char)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.loword == '=') {
|
|
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(TRUE,oirt))==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 = BYTESIZ;
|
|
mode = BYTE;
|
|
break;
|
|
case 'w':
|
|
case 'W':
|
|
modelen = WORDSIZ;
|
|
mode = WORD;
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
modelen = LONGSIZ;
|
|
mode = LONG;
|
|
break;
|
|
default:
|
|
peekc = fchr;
|
|
fchr = '.';
|
|
goto getm1;
|
|
}
|
|
explmode++;
|
|
fchr = gchr();
|
|
igblk();
|
|
return;
|
|
}
|
|
getm1:
|
|
if(opcpt == exgptr) { /*length is long*/
|
|
modelen = LONGSIZ;
|
|
mode = LONG;
|
|
}
|
|
else {
|
|
mode = WORD; /*default is word*/
|
|
modelen = WORDSIZ;
|
|
}
|
|
}
|
|
|
|
/* 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==BYTESIZ?FALSE:TRUE);
|
|
case 4 :
|
|
case 25 :
|
|
return(modelen==BYTESIZ?TRUE:FALSE);
|
|
case 7 :
|
|
case 9 :
|
|
return(modelen==WORDSIZ?FALSE:TRUE);
|
|
case 5 :
|
|
case 11 :
|
|
case 28 :
|
|
return(modelen==WORDSIZ?TRUE:FALSE);
|
|
case 6 :
|
|
return(modelen==LONGSIZ?FALSE:TRUE);
|
|
case 12 :
|
|
case 30 :
|
|
case 22 :
|
|
case 29 :
|
|
return(modelen==LONGSIZ?TRUE:FALSE);
|
|
default :
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
/* calculate the instruction length in bytes*/
|
|
calcilen()
|
|
{
|
|
register short i;
|
|
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:
|
|
case 31:
|
|
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 > BYTESIZ) /*[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)
|
|
int lidx;
|
|
{
|
|
if(immed[lidx])
|
|
return(mode==LONG?LONGSIZ:WORDSIZ);
|
|
return(shiftea(lidx));
|
|
}
|
|
|
|
shiftea(lidx)
|
|
int lidx;
|
|
{
|
|
if(indir[lidx] && numreg[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()
|
|
{
|
|
if(lbt[0]) { /*got a label*/
|
|
pack(lbt,lmte); /*put label in main table*/
|
|
lblpt=lemt(FALSE,sirt); /*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*/
|
|
if(rlflg == TEXT)
|
|
lblpt->flags |= SYRO;
|
|
else if(rlflg == DATA)
|
|
lblpt->flags |= SYRA;
|
|
else if(rlflg == BSS)
|
|
lblpt->flags |= SYBS;
|
|
/* No flags to set if absolute */
|
|
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 short 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.loword==',') {
|
|
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(FALSE,sirt);
|
|
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 char *sp;
|
|
|
|
symcon = 0;
|
|
if(itype==ITSP) { /*special symbol*/
|
|
if(ival.loword==',' && !plevel) { /* another operand */
|
|
numops++;
|
|
if(!opdix)
|
|
opdix++;
|
|
}
|
|
if(ival.loword==')')
|
|
symcon = 1; /* star is multiply */
|
|
if(ival.loword==' ') { /*end of operands*/
|
|
while(fchr!=EOLC) /*ignore rest of statement*/
|
|
fchr=gchr();
|
|
return;
|
|
}
|
|
if(ival.loword==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(FALSE,sirt); /*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 if(sp->vl1) /*yes, a register & not D0 */
|
|
numreg[opdix] = sp->vl1;
|
|
return;
|
|
}
|
|
else if(itype == ITCN ) {
|
|
if(ival.hiword && ival.hiword != -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.loword != '-')
|
|
return;
|
|
l = -l;
|
|
}
|
|
p = stbuf[2].itop.ptrw2;
|
|
if(p==moveptr) {
|
|
if(explmode && modelen != LONGSIZ) /*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;
|
|
register int alen;
|
|
{
|
|
register char *str1, *str2;
|
|
|
|
str1 = astr1;
|
|
str2 = astr2;
|
|
while (--alen != -1)
|
|
*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 short i;
|
|
|
|
for( s = str, i = 0; *s != '\0'; i++ )
|
|
if( *s++ == chr )
|
|
return(i);
|
|
return(-1);
|
|
}
|
|
|