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

725 lines
14 KiB
C

#ifndef lint
static char sccsid[] = "@(#)scan.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* 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);}
#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[];
extern NODE *curnode;
extern short curaddr;
extern short maxaddr;
extern CODE code[];
extern CODE *curword;
extern Boolean aseq();
extern Boolean ati8847();
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 = 001; /* default to next */
int condition = 0; /* default to never */
int state = 0; /* default */
int latch = 1;
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, condition, which, num, labl, state, latch )
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 ) {
condition = 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 ) {
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
tipart()
{
register char c;
register RESERVED *rp;
char *cp;
int func = 0x020, /* default to spass */
src = 0xff, /* default to RA input register */
regctl = 0,
csrc = 0,
output = 0x2,
conf = 1,
halt = 0;
#define CHEK if(c==';') {c=nextc(); scanb(c); return ATI8847;} \
rp = resw_lookup( cp = scansym( ) ); \
if ( rp == 0 ) goto wbotch;
#define ATI8847 ati8847( func, src, regctl, csrc, output, halt, conf )
scanb(c);
if ( c == ';' ) { /* no TIinst field */
c = nextc();
scanb(c);
return ATI8847;
}
rp = resw_lookup(cp=scansym( ));
if ( rp == 0 ) goto wbotch;
if ( rp->type == Function ) {
func = rp->value1;
scanb( c );
CHEK;
if ( rp->type == Source && rp->value2 == 1 ) {
src = ( src & ~0x03 ) | rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Source && rp->value2 == 2 ) {
src = ( src & ~0x0c ) | rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Source && rp->value2 == 3 ) {
src = ( src & ~0x30 ) | rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Source && rp->value2 == 4 ) {
src = ( src & ~0xc0 ) | rp->value1;
scanb( c );
CHEK;
}
}
if ( rp->type == Regctl && rp->value2 == 1 ) {
regctl = rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Regctl && rp->value2 == 2 ) {
regctl += rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Csrc && rp->value2 == 1 ) {
csrc = rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Csrc && rp->value2 == 2 ) {
csrc += rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Output && rp->value2 == 1 ) {
output = rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Output && rp->value2 == 2 ) {
output += rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Config ) {
conf = rp->value1;
scanb( c );
CHEK;
}
if ( rp->type == Halt ) {
halt = rp->value1;
scanb( c );
if (c == ';') {
c = nextc();
scanb(c);
return ATI8847;
}
}
wbotch :
error ("%s found in TIinst field", cp );
return False;
botch:
error ("TIinst syntax error, character %c is not expected", c);
return False;
#undef CHEK
#undef ATI8847
}
Boolean
ramoppart()
{
register char c;
register RESERVED *rp;
char *cp;
int dctrl = 017; /* default to idle state */
#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 == Regram ) {
dctrl = rp->value1;
scanb(c);
if (c == ';') {
c = nextc();
scanb(c);
return ADATA;
}
}
error ("ramop syntax error, character %c is not expected", c);
return False;
wbotch :
error ("%s found in ramop field", cp );
return False;
#undef ADATA
#undef CHEK
}
Boolean
ramctlpart()
{
register char c;
register RESERVED *rp;
char *cp;
int 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 ( 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 == Ramcs ) {
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 */
if ( c == '|' ) {
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
}
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;
register RESERVED *rp;
Boolean checkeol();
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;
curaddr = getnum();
break;
case 2: /* sccsid */
scanb(c);
acode();
asccs(curpos);
curnode->addr = curaddr++;
if ( curaddr > maxaddr ) {
maxaddr = curaddr;
}
break;
case 3: /* routine */
doramtable( );
break;
}
continue;
}
doseq:
acode();
curnode->addr = curaddr++;
if ( curaddr > maxaddr ) {
maxaddr = curaddr;
}
if (seqpart(name) == False) continue;
if (tipart( ) == False) continue;
if (ramoppart( ) == False) continue;
if (ramctlpart( ) == False) continue;
ptrpart( );
}
}