Files
Arquivotheca.SunOS-4.1.4/usr.etc/fpa/microassembler/scan.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

924 lines
18 KiB
C

/* @(#)scan.c 1.1 94/10/31 SMI */
/*
* Microassembler scanner for FPA
* scan.c 1.1 30 May 1985
*/
#include "micro.h"
#include <stdio.h>
#include <ctype.h>
#define scansp(c) while(isspace(c = *curpos)) curpos++
#define scanb(c) scansp(c); if (c == ',' ){c = nextc(); scansp(c);} else
#define nextc() (*++curpos)
#define peekc() (*curpos)
#define MAXSYMBOL 256
#define MAXLINE 1024
int curlineno;
char *curfilename;
char *curpos;
char *curline;
char inputline[MAXLINE];
/* The following 2 lines added by PWC to count lines of ucode. */
extern NODE n[NNODE];
extern NODE *curnode;
extern short curaddr;
extern RAMNODE ram[NINST];
extern Boolean aseq();
extern Boolean aweitek();
extern Boolean adata();
extern Boolean arecreg();
extern Boolean aram();
extern Boolean aptr();
extern char *strcpy();
Boolean
newline(){
/* glom a new input line.
* clobber comments. do
* continuation-line collection, as well.
*/
register char * maxpos = inputline + sizeof inputline - 1;
register char *cp;
char *end;
register c;
int len;
cp = inputline;
restart:
curlineno++;
do {
c = getchar();
if (c == '&') {
while ( getchar() != '\n' );
goto restart;
}
*cp++ = c;
} while ( c != '\n' && c != EOF && cp < maxpos );
if ( c == EOF ) return False;
end = cp;
*cp = '\0';
if (cp == maxpos){
error("Sorry, line(s) too long");
goto process;
}
process:
curpos = inputline;
len = end-inputline;
curline = (char*)malloc(len+2);
if (curline == 0) {
error("unable to get sufficient storage\n");
return False;
}
strcpy( curline, inputline );
return True;
}
char *
scansym( )
{
static char stuff[MAXSYMBOL];
register char *cp;
register char c;
Boolean ok = True;
cp = stuff;
curpos -= 1; /*back up to get a running start*/
while( ok ){
while (isalnum(*cp++ = c = nextc()));
switch(c){
case '.':
case '_':
case '\\':
continue;
default:
ok = False;
}
}
*--cp = '\0';
return( stuff );
}
int
getnum( )
{
register char c = *curpos;
register int val, base;
int sign;
sign = 1;
if (c == '-') {
sign = -1;
c = nextc();
} else if (c == '+') {
c = nextc();
}
val = c - '0';
base = (val==0)? 010 : 10;
c = nextc();
if ( val == 0 && (c == 'x' || c == 'X') ){
base = 0x10;
c = nextc();
}
while(isxdigit(c)){
val *= base;
if( isdigit(c) )
val += c -'0';
else if (islower(c))
val += c -'a' + 10;
else
val += c -'A' + 10;
c = nextc();
}
if (sign == -1) {
val = -val;
}
return( val );
}
Boolean
seqpart (name)
char *name;
{
register char c;
register RESERVED *rp;
register char *cp;
int brnch = 040; /* default next */
int state = 4; /* default */
int latch = 0;
int restore = 0;
int offset;
SYMTYPE which = NEITHER;
int num = 0;
static char buff[MAXSYMBOL];
char *labl = buff;
#define CHEK if(c==';') {c=nextc(); scanb(c); return ASEQ;} \
rp = resw_lookup( cp = scansym( ) ); \
if ( rp == 0 ) goto wbotch;
#define ASEQ aseq(brnch, which, num, labl, state, latch, restore)
if ( name == 0 && peekc() == ';') { /* no seq field */
c = nextc();
scanb(c);
return ASEQ;
}
start:
rp = resw_lookup( cp = name );
if ( rp == 0 ) goto wbotch;
if ( rp->type == Branch1) {
brnch = rp->value1;
scanb(c);
if ( rp->value2 == 2 ) {
curnode->jumpop = True;
if ( isdigit(c) || c == '.' ) goto address;
if ( isalpha(c) ) {
rp = resw_lookup(cp = scansym());
if ( rp == 0 ) {
which = ALPHA;
strcpy (labl, cp);
scanb(c);
CHEK;
}
} else goto botch;
} else {
CHEK
}
}
if ( rp->type == Branch2 ) {
brnch += rp->value1;
address:
curnode->jumpop = True;
scanb(c);
if (isdigit(c)) {
which = NUMBER;
num = getnum( );
scanb(c);
} else if (isalpha(c)) {
which = ALPHA;
strcpy (labl, scansym( ));
scanb(c);
} else if (c == '.') {
which = NUMBER;
offset = 0;
c = nextc();
scanb(c);
if (c == '+') {
c = nextc();
scanb(c);
offset = getnum();
scanb(c);
} else if (c == '-') {
c = nextc();
scanb(c);
offset = -getnum();
scanb(c);
}
num = curaddr - 1 + offset;
} else goto botch;
CHEK
}
if ( rp->type == State ) {
state = rp->value1;
scanb(c);
CHEK
}
if ( rp->type == Latch && rp->value2 == 1 ) {
latch = rp->value1;
scanb(c);
CHEK
if ( rp->type == Latch && rp->value2 == 2 ) {
if (rp->value1 == 1)
restore = 1;
else
latch += rp->value1;
scanb(c);
CHEK
}
}
if ( rp->type == Latch && rp->value2 == 3 ) {
latch += rp->value1;
scanb(c);
if ( c == ';' ) {
c = nextc();
scanb(c);
return ASEQ;
}
}
wbotch :
error ("%s found in seq_state field", cp );
return False;
botch:
error ("seq_state field syntax error, character %c is not expected", c);
return False;
#undef ASEQ
#undef CHEK
}
Boolean
weitekpart ( ) {
register char c;
register RESERVED *rp;
char *cp;
int foo;
int lplus = 0,
func = 0,
csl = 0,
csux = 0,
u = 0,
woe = 0;
#define CHEK if(c==';') {c=nextc(); scanb(c); return AWEITEK;} \
rp = resw_lookup( cp = scansym( ) ); \
if ( rp == 0 ) goto wbotch;
#define AWEITEK aweitek(lplus, func, csl, csux, u, woe)
scanb(c);
if ( c == ';' ) { /* no weitek field */
c = nextc();
scanb(c);
return AWEITEK;
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if (rp->type != Loadctrl && rp->type != Mode) goto csux_l;
if (rp->type == Loadctrl ) {
lplus = rp->value1;
if (rp->value2 == 0) {
scanb(c);
if (c == ';') {
error("function expected");
return False;
} else {
CHEK
if ( rp->type == Function ) {
func = rp->value1;
scanb(c);
if (c == ';') {
error("csl control expected");
return False;
} else {
CHEK
}
} else {
error("function expected");
return False;
}
}
scanb(c);
goto csl_l;
}
scanb(c);
if (c == ';') {
error("csl control expected");
return False;
} else {
CHEK
}
goto csl_l;
}
if ( rp->type == Mode) { /*LMODE*/
scanb(c);
lplus = rp->value1;
func = rp->value2;
if ( func == 0x40 ) {
if (c == ';') {
error("csl control expected");
return False;
} else {
CHEK
}
goto csl_l;
}
if ( isdigit(c) ) {
foo = getnum( );
if ( foo > 0x10 || foo < 0 ) {
error ("number %d is out of range for the mode field", foo );
return False;
}
func += foo;
} else goto wbotch;
scanb(c);
if (c == ';') {
error("csl control expected");
return False;
} else {
CHEK
}
}
csl_l:
if ( rp->type == Csl ) {
csl = rp->value1;
scanb(c);
CHEK
} else {
error("csl control expected");
return False;
}
csux_l:
if ( rp->type == Csux ) {
csux = rp->value1;
scanb(c);
if (c == ';') {
error("u+ control expected");
return False;
} else {
CHEK
}
if ( rp->type == U ) {
u = rp->value1;
scanb(c);
CHEK
} else {
error("u+ control expected");
return False;
}
}
if ( rp->type == Woe ) {
woe = rp->value1;
scanb(c);
if ( c == ';' ) {
c = nextc();
scanb(c);
return AWEITEK;
}
}
error ("WeitekInst syntax error, character %c is not expected", c);
return False;
wbotch :
error ("%s found in WeitekInst field", cp );
return False;
#undef CHEK
#undef AWEITEK
}
Boolean
datapart( )
{
register char c;
register RESERVED *rp;
char *cp;
int dctrl = 0;
#define ADATA adata(dctrl)
#define CHEK if(c==';') {c=nextc(); scanb(c); return ADATA;} \
rp = resw_lookup( cp = scansym( ) ); \
if ( rp == 0 ) goto wbotch;
scanb(c);
if ( c == ';' ) { /* no datamuxing field */
c = nextc();
scanb(c);
return ADATA;
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if (rp->type == Datactrl ) {
dctrl = rp->value1;
scanb(c);
if ( rp->value2 == 0 ) goto end;
CHEK
if (rp->type == Datactrl && rp->value1 == 021 ) { /* dtor */
dctrl += 1;
scanb(c);
end:
if (c == ';') {
c = nextc();
scanb(c);
return ADATA;
}
}
}
error ("datamuxing syntax error, character %c is not expected", c);
return False;
wbotch :
error ("%s found in datamuxing field", cp );
return False;
#undef ADATA
#undef CHEK
}
Boolean
recpart ( )
{
register char c;
register RESERVED *rp;
char *cp;
int recreg = 0;
#define CHEK if(c==';') {c=nextc(); scanb(c); return arecreg (recreg );}\
rp = resw_lookup( cp = scansym( ) ); \
if ( rp == 0 ) goto wbotch;
scanb(c);
if ( c == ';' ) { /* no recreg control field */
c = nextc();
scanb(c);
return arecreg( recreg );
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if (rp->type == Recoe ) {
recreg = rp->value1;
scanb(c);
CHEK
}
if (rp->type == Reclk ) {
recreg += rp->value1;
scanb(c);
if ( c == ';' ) {
c = nextc();
scanb(c);
return arecreg (recreg);
}
}
error ("recovery reg field syntax error, character %c is not expected", c);
return False;
wbotch :
error ("%s found in recovery reg field", cp );
return False;
#undef CHEK
}
Boolean
rampart ( )
{
register char c;
register RESERVED *rp;
char *cp;
int ramctrl = 0,
ramcs = 0,
ptr = 0;
#define CHEK if(c==';') {c=nextc(); scanb(c); return ARAM;} \
rp = resw_lookup(cp=scansym( )); \
if ( rp == 0 ) goto wbotch;
#define ARAM aram (ramctrl, ramcs, ptr)
scanb(c);
if ( c == ';' ) { /* no ramctrl field */
c = nextc();
scanb(c);
return ARAM;
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if (rp->type == Ramwe ) {
ramctrl = rp->value1;
scanb(c);
CHEK
}
if (rp->type == Ramcs && rp->value2 == 1 ) {
ramcs = rp->value1;
scanb(c);
CHEK
}
if (rp->type == Ramcs && rp->value2 == 2 ) {
ramcs += rp->value1;
scanb(c);
CHEK
}
if (rp->type == Pointer ) {
if ( rp->value2 == 2 ) {
error("pointer %s is not allowed here", cp);
return False;
}
ptr = rp->value1;
scanb(c);
if (c == ';') {
c = nextc();
scanb(c);
return ARAM;
}
}
error ("ram control field syntax error, character %c is not expected", c);
return False;
wbotch :
error ("%s found in ram control field", cp );
return False;
#undef CHEK
#undef ARAM
}
Boolean
ptrpart ( )
{
register char c;
register RESERVED*rp;
register char *cp;
int ptr = 0;
int act = 0;
SYMTYPE which = NEITHER;
int num;
char *sym;
#define APTR aptr( ptr, act, which, num, sym)
scanb(c);
if ( c== '|' || c == '\0' ) { /* no ptr_action field */
c = nextc();
scanb(c);
return APTR;
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if ( rp->type == Pointer ) {
if ( rp->value2 == 1 ) {
error("pointer %s is not allowed here", cp);
return False;
}
ptr = rp->value1;
scanb(c);
switch (c) {
case '=' : /* hold */
act = 0;
break;
case '!':
if ( ptr == 1 || ptr == 2 || ptr == 3 || ptr == 4) {
error("action is not allowed for the pointer");
return False;
}
act = 1; /* load */
c = nextc();
scanb(c);
if ( c == '|' || c == '\0' ) return APTR;
if ( curnode->jumpop == True ) {
error("overlap address field with load value");
return False;
}
if (isdigit(c)) {
which = NUMBER;
num = getnum( );
scanb(c);
if ( c == '+') {
c = nextc();
scanb(c);
if (! isdigit(c)) goto wbotch;
num += getnum();
curpos--;
} else {
curpos--;
}
} else if(isalpha(c)) {
which = ALPHA;
sym = scansym( );
} else goto wbotch;
break;
case '+':
if ( ptr == 6 || ptr == 7 ) {
error("action is not allowed for the pointer");
return False;
}
act = 3;
break;
case '-':
if ( ptr == 7 ) {
error("action is not allowed for the pointer");
return False;
}
act = 2;
break;
default :
error ("ptr control field syntax error, character %c is not expected", c);
return False;
}
c = nextc();
scanb(c);
if ( c == '|' || c == '\0' ) return APTR;
}
wbotch :
error ("%s found in ptr control field", cp );
return False;
#undef APTR
}
doramtable ( )
{
register char c;
register dontcare = 0;
register mask = 0;
RESERVED *rp;
char *cp;
char name[20];
char addr[13];
int i;
Boolean first;
int load;
int func;
scanb(c);
cp = scansym( ); /* routine name */
cp = strcpy (name, cp);
name[19] = '\0';
scanb(c);
switch (c) {
case 'r':
addr[0] = '1';
dontcare = 1;
mask = 1;
break;
case 'w':
addr[0] = '0';
dontcare = 1;
mask = 0;
break;
case 'x':
addr[0] = 'x';
dontcare = 0;
mask = 0;
break;
default:
goto botch;
}
for ( i = 1; i < 12; i++ ) {
nextc();
c = peekc();
switch (c) {
case '0':
addr[i] = '0';
dontcare = (dontcare << 1) + 1;
mask = mask << 1;
break;
case '1':
addr[i] = '1';
dontcare = (dontcare << 1) + 1;
mask = (mask << 1) + 1;
break;
case 'x':
addr[i] = 'x';
dontcare = dontcare << 1;
mask = mask << 1;
break;
default:
goto botch;
}
}
addr[12] = '\0';
nextc();
scanb(c);
rp = resw_lookup( cp = scansym( ) ); /* load ctrl */
if ( rp == 0 ) goto wbotch;
if ( rp->type != Loadctrl ) goto wbotch;
if ( rp->value2 != 1 ) {
error("bad load control");
return;
}
load = rp->value1;
scanb(c);
rp = resw_lookup( cp = scansym( ) ); /* func ctrl */
if ( rp == 0 ) goto wbotch;
if ( rp->type != Function ) goto wbotch;
if ( rp->value2 == 2 ) {
error("bad function control");
return;
}
func = rp->value1;
first = True;
for ( i = 0; i < NINST; i++ ) {
if ( (i & dontcare ) == mask ) {
if ( ram[i].addr[0] != 0 ) {
error ("overlapping at ram addr %4x", i);
continue;
}
if (first) {
cp = strcpy (ram[i].name, name);
cp = strcpy (ram[i].addr, addr);
first = False;
} else {
ram[i].addr[0] = 'm';
}
ram[i].entry = curaddr;
ram[i].load = load;
ram[i].func = func;
}
}
return;
wbotch :
error ("%s found in routine pseudo_op", rp );
return;
botch:
error ("%c is not expected in routine pseudo_op", cp );
}
label(sp)
SYMBOL *sp;
{
if (sp->defined){
error("label %s already defined", sp->name );
return;
}
sp->defined = True;
sp->node = curnode+1;
DEBUG("Label: defining %s\n", sp->name);
}
Boolean
cpp(){
/* the scanner just saw a '#' -- treat as cpp leaving */
register char c ;
char *sp;
int leng;
int cln;
nextc();
scanb(c);
cln = curlineno;
curlineno = getnum( ) - 1;
scanb(c);
if (c != '"') {
curlineno = cln;
error("#-line not of form output by C preprocessor");
return False;
}
/* just saw the " */
c = nextc(); /* skip it */
sp = curpos;
while( (c=nextc()) != '"' );
*curpos = '\0';
leng = strlen( sp );
curfilename = (char *)malloc( leng+1 );
if (curfilename == 0) {
error("unable to get sufficient storage\n");
return False;
}
strcpy( curfilename, sp );
DEBUG("# %d \"%s\"\n", curlineno+1, curfilename);
return True;
}
scanprog()
{
/*
for each line in the program text:
if it is blank, continue.
if it begins with a '#', its a cpp dropping
look at the first symbol on the line.
if it is followed by a :, its a label,
so define the label and scan out the next symbol
assemble the seq_state part
assemble the Weitek instruction part
assemble the datamuxing part
assemble the recover reg ctrl part
assemble the ram control part
assemble the pointer actoin part
*/
char c;
char *name;
SYMBOL *sp;
Boolean stopsw = False;
Boolean bkptsw = False;
int debugsw = 0;
int foo;
register RESERVED *rp;
while (newline()){
if (*curpos == '#'){
cpp();
continue;
}
restart:
scanb(c);
if( c == '\0') {
continue; /* blank line */
}
if (c == ';') {
name = 0;
anext();
goto doseq;
}
if (!isalnum(c)) {
if (c != '|') {
error("character %c unexpected", c);
}
anext();
curnode->org_pseudo = True;
continue;
}
name = scansym( );
scanb(c);
if(c== ':') {
/* what we have here is a label */
sp = lookup( name );
if (sp == 0)
sp = enter( name );
label( sp );
nextc();
scanb(c);
(curnode+1)->addr = curaddr;
if (c == '\0') {
anext();
curnode->org_pseudo = True;
}
goto restart;
}
anext();
rp = resw_lookup( name );
if (rp != 0 && rp->type == Pseudo) {
/* it's a pseudo-op */
switch (rp->value1) {
case 1: /*org */
scanb(c);
if (!isdigit(c)) {
error("expected digit; found %c", c);
continue;
}
curnode->org_pseudo = True;
foo = getnum();
if ( foo < curaddr ) {
error("org %d over write lower address space", foo);
continue;
}
curaddr = foo;
break;
case 2: /* sccsid */
scanb(c);
asccs(curpos);
curnode->addr = curaddr++;
break;
case 3: /* routine */
curnode->routine = True;
curnode->org_pseudo = True;
doramtable( );
break;
}
continue;
}
doseq:
curnode->addr = curaddr++;
if (seqpart(name) == False) continue;
if (weitekpart( ) == False) continue;
if (datapart( ) == False) continue;
if (recpart( ) == False) continue;
if (rampart( ) == False) continue;
ptrpart( );
}
}