URL
https://opencores.org/ocsvn/System09/System09/trunk
Subversion Repositories System09
Compare Revisions
- This comparison shows the changes necessary to convert path
/System09/trunk/Tools/as09
- from Rev 66 to Rev 74
- ↔ Reverse comparison
Rev 66 → Rev 74
/pseudo.c
0,0 → 1,324
/* |
* pseudo --- pseudo op processing |
*/ |
|
#define RMB 0 /* Reserve Memory Bytes */ |
#define FCB 1 /* Form Constant Bytes */ |
#define FDB 2 /* Form Double Bytes (words) */ |
#define FCC 3 /* Form Constant Characters */ |
#define ORG 4 /* Origin */ |
#define EQU 5 /* Equate */ |
#define ZMB 6 /* Zero memory bytes */ |
#define FILL 7 /* block fill constant bytes */ |
#define OPT 8 /* assembler option */ |
#define NULL_OP 9 /* null pseudo op */ |
#define PAGE 10 /* new page */ |
#define INCLUDE 11 /* include <file> or "file" ver TER_2.0 */ |
#define END 12 /* include <file> terminator ver TER_2.0 */ |
#define IFD 13 /* if define <symbol> ver TER_2.0 */ |
#define IFND 14 /* if not define <symbol> ver TER_2.0 */ |
#define ELSE 15 /* else (for IF statements) ver TER_2.0 */ |
#define ENDIF 16 /* endif (for IF statements) ver TER_2.0 */ |
#define BSS 17 /* block storage segment (RAM) ver TER_2.09 */ |
#define CODE 18 /* code segment ver TER_2.09 25 Jul 89 */ |
#define DATA 19 /* data segment ver TER_2.09 25 Jul 89 */ |
#define AUTO 20 /* data segment ver TER_2.09 25 Jul 89 */ |
|
struct oper pseudo[] = { |
"=", PSEUDO, EQU, 0, /* ver TER_2.09 25 Jul 89 */ |
"auto", PSEUDO, AUTO, 0, /* ver TER_2.09 25 Jul 89 */ |
"bss", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */ |
"bsz", PSEUDO, ZMB, 0, |
"code", PSEUDO, CODE, 0, /* ver TER_2.09 25 Jul 89 */ |
"data", PSEUDO, DATA, 0, /* ver TER_2.09 25 Jul 89 */ |
"else", PSEUDO, ELSE, 0, /* ver TER_2.0 6/17/89 */ |
"end", PSEUDO, END, 0, /* ver TER_2.0 6/17/89 */ |
"endif",PSEUDO, ENDIF, 0, /* ver TER_2.0 6/17/89 */ |
"equ", PSEUDO, EQU, 0, |
"fcb", PSEUDO, FCB, 0, |
"fcc", PSEUDO, FCC, 0, |
"fdb", PSEUDO, FDB, 0, |
"fill", PSEUDO, FILL, 0, |
"ifd", PSEUDO, IFD, 0, /* ver TER_2.0 6/17/89 */ |
"ifnd", PSEUDO, IFND, 0, /* ver TER_2.0 6/17/89 */ |
"include", PSEUDO, INCLUDE, 0, /* ver TER_2.0 6/17/89 */ |
"nam", PSEUDO, NULL_OP,0, |
"name", PSEUDO, NULL_OP,0, |
"opt", PSEUDO, OPT, 0, |
"org", PSEUDO, ORG, 0, |
"pag", PSEUDO, PAGE, 0, |
"page", PSEUDO, PAGE, 0, |
"ram", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */ |
"rmb", PSEUDO, RMB, 0, |
"spc", PSEUDO, NULL_OP,0, |
"ttl", PSEUDO, NULL_OP,0, |
"zmb", PSEUDO, ZMB, 0 |
}; |
|
/* |
* do_pseudo --- do pseudo op processing |
*/ |
do_pseudo(op) |
int op; /* which op */ |
{ |
char fccdelim, *strsave(); |
int fill; |
int c; /*test variable ver TER_2.0 6/18/89 */ |
char *skip_white(), *savept; /* savept is pointer to string save */ |
FILE *FdTemp, *fopen(); /* ver TER_2.0 6/17/89 */ |
void pouterror(), NewPage(), IfMachine(); /* rel TER_2.0 6/18/89 */ |
void PC_Exchange(); /* ver TER_2.09 25 Jul 89 */ |
|
if( op != EQU && *Label ) |
install(Label,Pc); |
|
P_force++; |
|
#ifdef DEBUG3 |
printf("%s, line no. ",Argv[Cfn]); /* current file name */ |
printf("%d: ",Line_num); /* current line number */ |
printf(" Pseudo Op=%u\n",op); |
#endif |
|
switch(op){ |
case RMB: /* reserve memory bytes */ |
if( eval() ){ |
Pc += Result; |
f_record(); /* flush out bytes */ |
} |
else |
error("Undefined Operand during Pass One"); |
break; |
case ZMB: /* zero memory bytes */ |
if( eval() ) |
while( Result-- ) |
emit(0); |
else |
error("Undefined Operand during Pass One"); |
break; |
case FILL: /* fill memory with constant */ |
eval(); |
fill = Result; |
if( *Optr++ != ',' ) |
error("Bad fill"); |
else{ |
Optr = skip_white(Optr); |
eval(); |
while( Result-- ) |
emit(fill); |
} |
break; |
case FCB: /* form constant byte(s) */ |
do{ |
Optr = skip_white(Optr); |
eval(); |
if( Result > 0xFF ){ |
if(!Force_byte) |
warn("Value truncated"); |
Result = lobyte(Result); |
} |
emit(Result); |
}while( *Optr++ == ',' ); |
break; |
case FDB: /* form double byte(s) */ |
do{ |
Optr = skip_white(Optr); |
eval(); |
eword(Result); |
}while( *Optr++ == ',' ); |
break; |
case FCC: /* form constant characters */ |
if(*Operand==EOS) |
break; |
fccdelim = *Optr++; |
while( *Optr != EOS && *Optr != fccdelim) |
emit(*Optr++); |
if(*Optr == fccdelim) |
Optr++; |
else |
error("Missing Delimiter"); |
break; |
case ORG: /* origin */ |
if( eval() ){ |
Old_pc = Pc = Result; |
f_record(); /* flush out any bytes */ |
} |
else |
error("Undefined Operand during Pass One"); |
break; |
case EQU: /* equate */ |
if(*Label==EOS){ |
error("EQU requires label"); |
break; |
} |
if( eval() ){ |
install(Label,Result); |
Old_pc = Result; /* override normal */ |
} |
else |
error("Undefined Operand during Pass One"); |
break; |
case OPT: /* assembler option */ |
P_force=0; |
if( head(Operand,"l") ) |
Lflag=1; |
else if (head(Operand,"nol")) |
Lflag=0; |
else if (head(Operand,"c")){ |
Cflag=1; |
Ctotal=0; |
} |
else if (head(Operand,"noc")) |
Cflag=0; |
else if (head(Operand,"contc")){ |
Cflag=1; |
} |
else if (head(Operand,"s")) |
Sflag = 1; |
else if (head(Operand,"cre")) |
CREflag = 1; |
else if (head(Operand,"p50")){ /* turn on 50 lines/page flag */ |
Pflag50 = 1; |
Pflag75 = 0; |
} /* separately. ver TER_2.0 6/17/89 */ |
else if (head(Operand,"p75")){ /* turn on 75 lines/page flag */ |
Pflag50 = 0; |
Pflag75 = 1; |
} /* separately. ver TER_2.0 6/17/89 */ |
else if (head(Operand,"crlf")) /* add <CR> <LF> to */ |
CRflag = 1; /* S record ver TER_2.08 */ |
else if (head(Operand,"nnf")) /* no extra line no. */ |
nfFlag = 0; /* w include files ver TER_2.08 */ |
else |
error("Unrecognized OPT"); |
break; |
case PAGE: /* go to a new page */ |
P_force=0; |
N_page = 1; |
if (Pass == 2 ) |
if (Lflag) NewPage(); |
break; |
case NULL_OP: /* ignored psuedo ops */ |
P_force=0; |
break; |
case INCLUDE: /* case INCLUDE added ver TER_2.0 6/17/89 */ |
P_force=0; /* no PC in printed output */ |
if ((c=FNameGet(InclFName))==0) |
error("Improper INCLUDE statement"); |
else |
{ |
if (FdCount > MAXINCFILES) |
error("too many INCLUDE files"); |
else |
{ |
if ((FdTemp = fopen(InclFName,"r"))==0) |
{ |
printf("%s, line no. ",Argv[Cfn]); |
/* current file name */ |
printf("%d: ",Line_num); /* current line number */ |
Page_lines++; /* increment lines per page */ |
printf("warning:can't open INCLUDE file %s\n",InclFName); |
} |
else |
{ |
if ((savept=strsave(InclFName))==0) |
error("out of memory for INCLUDE file name"); |
else |
{ |
InclFiles[FdCount].fp=Fd; /* save current fp */ |
if (nfFlag) |
{ |
InclFiles[FdCount].line_num=Line_num; |
/* save current line count */ |
Line_num=0; /* reset for new file */ |
} |
InclFiles[FdCount].name=Argv[Cfn]; |
/* save pointer to current name */ |
Argv[Cfn]=savept; |
/* now replace pointer to current name with |
pointer to name of Include file */ |
Fd=FdTemp; /* now replace current file with |
INCLUDE fp */ |
FdCount++; /* and increment "stack" */ |
#ifdef DEBUG2 |
printf("pseudo INCLUDE: FdCount=%d\n",FdCount); |
printf(" new input file pointer=%d\n",Fd); |
printf(" new file name=%s\n",Argv[Cfn]); |
#endif |
} |
} |
} |
} |
break; |
case END: |
P_force=0; |
if (FdCount>0) /* skip END statements in files |
received from CLI arguments */ |
{ |
fclose(Fd); /* close file from this level nest */ |
FdCount--; /* "pop stack" */ |
Fd=InclFiles[FdCount].fp; /* restore fp from |
nested stack */ |
if(nfFlag) Line_num=InclFiles[FdCount].line_num; |
Argv[Cfn]=InclFiles[FdCount].name; |
/* restore file name pointer */ |
#ifdef DEBUG2 |
printf("pseudo END: FdCount=%d\n",FdCount); |
printf(" new input file pointer=%d\n",Fd); |
printf(" new file name=%s\n",Argv[Cfn]); |
#endif |
} |
break; |
case IFD: |
#ifdef DEBUG3 |
printf("case IFD: in pseudo\n"); |
#endif |
P_force=0; |
c=eval_ifd(); |
IfMachine(c); |
break; |
case IFND: |
P_force=0; |
c=eval_ifnd(); |
IfMachine(c); |
break; |
case ELSE: |
P_force=0; |
IfMachine(IF_ELSE); |
break; |
case ENDIF: |
P_force=0; |
IfMachine(IF_ENDIF); |
break; |
case CODE: /* CODE,DATA,BSS,AUTO ver TER_2.09 */ |
PC_Exchange(0); |
break; |
case DATA: |
PC_Exchange(1); |
break; |
case BSS: |
PC_Exchange(2); |
break; |
case AUTO: |
PC_Exchange(3); |
break; |
default: |
fatal("Pseudo error"); |
break; |
} |
} |
|
|
/* |
* PC_Exchange --- Save current PC and recover requested one |
added ver TER_2.09 |
*/ |
void PC_Exchange(PC_ptr_new) |
int PC_ptr_new; /* request 0=CODE,1=DATA,2=BSS */ |
{ |
P_force = 0; /* no PC in output cuz wrong first time (?) */ |
PC_Save[PC_ptr] = Pc; /* save current PC */ |
PC_ptr = PC_ptr_new; /* remember which one we're using */ |
Old_pc = Pc = PC_Save[PC_ptr]; /* recover the one requested */ |
f_record(); /* flush out any bytes, this is really an ORG */ |
} |
/symtab.c
0,0 → 1,157
/* |
* install --- add a symbol to the table |
*/ |
install(str,val) |
char *str; |
int val; |
{ |
struct link *lp; |
struct nlist *np,*p,*backp; |
struct nlist *lookup(); |
int i; |
char *LastChar(); /* ver TER_2.0 */ |
|
if( !alpha(*str) ){ |
error("Illegal Symbol Name"); |
return(NO); |
} |
if( (np = lookup(str)) != NULL ){ |
if (*LastChar(str) == '@') { /* redefinable symbol ver TER_2.0 */ |
np->def = val; /* redefined */ |
return(YES); |
} |
if( Pass==2 ){ |
np->def2 = 2; /* defined for this pass=Pass ver TER_2.0 */ |
if( np->def == val ) |
return(YES); |
else{ |
error("Phasing Error"); |
return(NO); |
} |
} |
error("Symbol Redefined"); |
return(NO); |
} |
/* enter new symbol */ |
#ifdef DEBUG |
printf("Installing %s as %d\n",str,val); |
#endif |
np = (struct nlist *) alloc(sizeof(struct nlist)); |
if( np == (struct nlist *)ERR ){ |
error("Symbol table full"); |
return(NO); |
} |
np->name = alloc(strlen(str)+1); |
if( np->name == (char *)ERR ){ |
error("Symbol table full"); |
return(NO); |
} |
strcpy(np->name,str); |
np->def = val; |
np->def2 = 1; /* defined for this pass=Pass ver TER_2.0 */ |
np->Lnext = NULL; |
np->Rnext = NULL; |
lp = (struct link *) alloc(sizeof(struct link)); |
np->L_list = lp; |
lp->L_num = Line_num; |
lp->next = NULL; |
p = root; |
backp = NULL; |
while (p != NULL) |
{ |
backp = p; |
i = strcmp (str,p->name); |
if (i<0) |
p=p->Lnext; |
else p=p->Rnext; |
} |
if (backp == NULL) |
root = np; |
else if (strcmp(str,backp->name)<0) |
backp->Lnext = np; |
else backp->Rnext = np; |
return (YES); |
} |
|
/* |
* lookup --- find string in symbol table |
*/ |
struct nlist * |
lookup(name) |
char *name; |
{ |
struct nlist *np; |
int i; |
char *c; /* ver TER_2.0 */ |
|
c = name; /* copy symbol pointer */ |
while(alphan(*c)) /* search for end of symbol */ |
c++; /* next char */ |
*c = EOS; /* disconnect anything after for good compare */ |
/* end of mods for ver TER_2.0 */ |
|
np = root; /* and now go on and look for symbol */ |
while (np != NULL) |
{ |
i = strcmp(name,np->name); |
if (i == 0) |
{ |
Last_sym = np->def; |
return (np); |
} |
else if (i < 0) |
np = np->Lnext; |
else np = np->Rnext; |
} |
Last_sym = 0; |
/* if (Pass == 2) |
error ("symbol Undefined on pass 2"); */ |
/* commented out ver TER_2.0 2 Jul 89 */ |
/* function used in IFD */ |
return (NULL); |
} |
|
|
#define NMNE (sizeof(table)/ sizeof(struct oper)) |
#define NPSE (sizeof(pseudo)/ sizeof(struct oper)) |
/* |
* mne_look --- mnemonic lookup |
* |
* Return pointer to an oper structure if found. |
* Searches both the machine mnemonic table and the pseudo table. |
*/ |
struct oper * |
mne_look(str) |
char *str; |
{ |
struct oper *low,*high,*mid; |
int cond; |
|
/* Search machine mnemonics first */ |
low = &table[0]; |
high = &table[ NMNE-1 ]; |
while (low <= high){ |
mid = low + (high-low)/2; |
if( ( cond = strcmp(str,mid->mnemonic)) < 0) |
high = mid - 1; |
else if (cond > 0) |
low = mid + 1; |
else |
return(mid); |
} |
|
/* Check for pseudo ops */ |
low = &pseudo[0]; |
high = &pseudo[ NPSE-1 ]; |
while (low <= high){ |
mid = low + (high-low)/2; |
if( ( cond = strcmp(str,mid->mnemonic)) < 0) |
high = mid - 1; |
else if (cond > 0) |
low = mid + 1; |
else |
return(mid); |
} |
|
return(NULL); |
} |
/output.c
0,0 → 1,42
/* |
* stable --- prints the symbol table in alphabetical order |
*/ |
stable(ptr) |
|
struct nlist *ptr; |
{ |
if (ptr != NULL) |
{ |
stable (ptr->Lnext); |
printf ("%-10s %04X\n",ptr->name,ptr->def); |
stable (ptr->Rnext); |
} |
} |
/* |
* cross -- prints the cross reference table |
*/ |
cross(point) |
|
struct nlist *point; |
{ |
struct link *tp; |
int i = 1; |
if (point != NULL) |
{ |
cross (point->Lnext); |
printf ("%-10s %04X *",point->name,point->def); |
tp = point->L_list; |
while (tp != NULL) |
{ |
if (i++>10) |
{ |
i=1; |
printf("\n "); |
} |
printf ("%04d ",tp->L_num); |
tp = tp->next; |
} |
printf ("\n"); |
cross (point->Rnext); |
} |
} |
/ifd.c
0,0 → 1,246
/* IfMachine() --- This function implements the IFD & IFND conditional |
assembly machine. |
version 1.0 made for release TER_2.0 cross assembler 27 Jun 89 |
*/ |
|
#define FALSE_BLOCK 0 /* values for state variable */ |
#define TRUE_BLOCK 1 |
#define POP_TEST 2 |
#define ELSE_TEST 3 |
#define FALSE 0 |
#define TRUE 1 |
|
void IfMachine(Token) |
int Token; /* input token from calling machine */ |
/* See file as.h for definition (globals) */ |
{ |
static int State = TRUE_BLOCK, StackPt = 0, IfStack[MAXIFD]; |
/* State variable, pointer to "IF stack pointer" and "Stack" */ |
int Hiatus; /* flag to break out of FSM & resume normal processing */ |
|
Hiatus=FALSE; /* infinite loop to operate machine |
until time to break out */ |
do /* test at end */ |
{ |
|
#ifdef DEBUG3 |
printf("IfMachine state=%u , token=%u\n",State,Token); |
#endif |
|
if (State == TRUE_BLOCK) /* a block of statements processed normally */ |
switch(Token) { |
case IF_TRUE: |
IfStack[StackPt]=TRUE; |
if (++StackPt > MAXIFD) { /* check for over flow */ |
StackPt = MAXIFD; |
error("Error:IFD/IFND nested too deep"); |
} |
/* print_line() will be done in normal processing */ |
Hiatus = TRUE; /* resume normal line processing */ |
break; |
case IF_FALSE: |
IfStack[StackPt]=TRUE; |
if (++StackPt > MAXIFD) { /* check for over flow */ |
StackPt = MAXIFD; |
error("Error:IFD/IFND nested too deep"); |
} |
if (Pass == 2 && Lflag && !N_page) /* need to print here */ |
print_line(); /* cuz will not return to normal */ |
Token = GetToken(); /* get next line & examine for IF */ |
State = FALSE_BLOCK; /* change state */ |
break; |
case IF_ELSE: |
if (StackPt == 0) /* bad IF nesting */ |
error("Error: ELSE without IF"); |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
Token = GetToken(); /* get next line & examine for IF */ |
State = FALSE_BLOCK; |
break; |
case IF_ENDIF: |
if (StackPt == 0) /* bad IF nesting */ |
error("Error: ENDIF without IF"); |
else |
StackPt--; /* popped state must be TRUE */ |
Hiatus = TRUE; |
break; |
/* case NORMAL is not implemented as it represents normal line |
processing. */ |
case IF_END: /* file ended with improperly nested IFD */ |
/* this code can't actually be reached at present |
in a TRUE_BLOCK */ |
fatal("Error: file ended before IFD/IFND/ELSE/ENDIF"); |
break; |
default: /* This code can't be reached at the present. |
Logically would happen if EOF but handled |
else where */ |
fatal("Can't get here from there."); |
break; |
} |
else if (State == FALSE_BLOCK) /* statements not processed */ |
switch(Token) { |
case IF_TRUE: /* doesn't make any diff. Just nest IFs */ |
case IF_FALSE: |
IfStack[StackPt]=FALSE; |
if (++StackPt > MAXIFD) { |
StackPt = MAXIFD; |
error("Error:IFD/IFND nested too deep"); |
} |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
Token = GetToken(); |
break; |
case IF_ELSE: |
/* if (Pass == 2 && Lflag && !N_page) */ |
/* print_line(); */ |
State = ELSE_TEST; |
break; |
case IF_ENDIF: |
State = POP_TEST; |
break; |
case IF_END: /* file ended with improperly nested IFD */ |
fatal("Fatal Error: file ended before last ENDIF"); |
/* Fatal will exit assembler. Things are too |
messed up. Include file handling is else where |
and don't want to duplicate here. */ |
break; |
case IF_NORMAL: /* normal line in a FALSE BLOCK */ |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
Token = GetToken(); |
break; |
default: |
fatal("Fatal Error: file ended before last ENDIF"); |
/* must be EOF or something else terrible */ |
break; |
} |
else if (State == POP_TEST) { /* pop up outside nest state */ |
if (StackPt == 0) { /* bad IF nesting */ |
error("Error: ENDIF without IF"); |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
State = TRUE; |
} |
else { |
StackPt--; /* pop stack */ |
if (IfStack[StackPt] == TRUE) { /* back to normal */ |
/* had to come from FALSE block cuz TRUE block cannot |
be inside FALSE block */ |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
State = TRUE; |
Hiatus = TRUE; /* sleep for normal line processing */ |
} |
else { /* gotta be that stack == FALSE, still inside FALSE nest */ |
if (Pass == 2 && Lflag && !N_page) |
print_line(); |
State = FALSE; |
Token = GetToken(); |
} |
} |
} |
else if (State == ELSE_TEST) { /* change state */ |
if (IfStack[StackPt-1] == TRUE) { |
State = TRUE_BLOCK; |
Hiatus = TRUE; |
} |
else |
State = FALSE_BLOCK; |
} |
} |
while (Hiatus == FALSE); /* loop if not exit */ |
} |
|
|
/* GetToken() --- get another line from within False Block and extract token |
as would be done in pseudo.c. Returns token id: |
IF_TRUE IFD/IFND evaluated to TRUE |
IF_FALSE IFD/IFND evaluated to FALSE |
IF_ELSE ELSE pseudo op |
IF_ENDIF ENDIF pseudo op |
IF_END END pseudo op |
IF_NORMAL none of the above, perhaps assy code |
IF_EOF encountered end of file |
This function exists because conditional assembly was added |
as pseudo op rather than with key character ("%") and did |
not want to disturb original software topology */ |
|
int GetToken() /* get another line and find token in it */ |
{ /* similar to make_pass() except one line at a time */ |
/* most variables & constants are global */ |
|
struct nlist *lookup(); |
|
#ifndef IBM |
if (FGETS(Line,MAXBUF-1,Fd) == (char *)NULL) |
#else |
if (fgets(Line,MAXBUF,Fd) == (char *)NULL) |
#endif |
return(IF_EOF); /* banged into eof */ |
Line_num++; |
P_force=0; |
N_page=0; |
if (!parse_line()) |
return(IF_NORMAL); /* comment line */ |
if (*Op==EOS) /* skipping over label, probably. */ |
return(IF_NORMAL); /* strcmp() returns 0 if arg1 is NULL string */ |
|
if (strcmp(Op,"ifd")==0) |
return(eval_ifd()); |
else if (strcmp(Op,"ifnd")==0) |
return(eval_ifnd()); |
else if (strcmp(Op,"else")==0) |
return(IF_ELSE); |
else if (strcmp(Op,"endif")==0) |
return(IF_ENDIF); |
else if (strcmp(Op,"end")==0) |
return(IF_END); |
else |
return(IF_NORMAL); /* or might be garbage...but who cares? |
This is FALSE BLOCK */ |
} |
|
|
/* |
* eval_ifd() --- evaluate an if define statement for TRUE or FALSE |
*/ |
|
int |
eval_ifd() |
{ |
struct nlist *np; /* symbol structure */ |
|
if (*Operand==EOS) { |
warn("No symbol for IFD"); |
return(IF_FALSE); /* nothing to check */ |
} |
if ((np=lookup(Operand)) == NULL) |
return(IF_FALSE); /* not defined at all...yet */ |
else |
if(np->def2 == Pass) |
return(IF_TRUE); /* defined for this pass */ |
|
return(IF_FALSE); /* not defined this pass */ |
} |
|
/* |
* eval_ifnd() --- evaluate an if not define statement for TRUE or FALSE |
*/ |
|
int |
eval_ifnd() |
{ |
struct nlist *np; /* symbol structure */ |
|
if (*Operand==EOS) { |
warn("No symbol for IFND"); |
return(IF_TRUE); /* nothing to check */ |
} |
if ((np=lookup(Operand)) == NULL) |
return(IF_TRUE); /* not defined at all...yet */ |
else |
if(np->def2 == Pass) |
return(IF_FALSE); /* defined for this pass */ |
|
return(IF_TRUE); /* not defined this pass */ |
} |
/as.c
0,0 → 1,313
char mapdn(); |
char *alloc(); |
/* |
* as --- cross assembler main program |
|
Note: Compile with define DEBUG for function module debug |
statements. Compile with define DEBUG2 for version 2 debug |
statements only. Compile with define IBM to use original, non- |
Amiga, non-MAC, non-UNIX fgets() function. Amiga version will |
accept IBM generated source code but not the other way around. |
Note added version (TER) 2.01 19 June 1989. |
|
Additional modifications to cleanup output listing made by |
Donald W. Coates 1/5/92. Version changed to 2.10 |
*/ |
main(argc,argv) |
int argc; |
char **argv; |
{ |
char **np; |
char *i; |
FILE *fopen(); |
int j = 0; |
void do_op(),f_record(); /* added for ANSI C compat ver TER_2.0 6/18/89 */ |
|
printf("Assembler release DWC_2.0 version 2.11\n"); |
printf("May 6, 2004 (c) Motorola (free ware)\n"); |
|
if(argc < 2){ |
printf("Usage: %s [files]\n",argv[j]); |
exit(1); |
} |
Argv = argv; |
initialize(); |
while ((j<argc) && (*argv[j] != '-')) |
j++; |
N_files = j-1; |
if (j < argc ) |
{ |
argv[j]++; |
while (j<argc) |
{ |
for (i = argv[j]; *i != 0; i++) |
if ((*i <= 'Z') && (*i >= 'A')) |
*i = *i + 32; |
if (strcmp(argv[j],"l")==0) |
Lflag = 1; |
else if (strcmp(argv[j],"nol")==0) |
Lflag = 0; |
else if (strcmp(argv[j],"c")==0) |
Cflag = 1; |
else if (strcmp(argv[j],"noc")==0) |
Cflag = 0; |
else if (strcmp(argv[j],"s")==0) |
Sflag = 1; |
else if (strcmp(argv[j],"cre")==0) |
CREflag = 1; |
else if (strcmp(argv[j],"crlf")==0) /* test for crlf option */ |
CRflag = 1; /* add <CR><LF> to S record */ |
/* ver TER_1.1 June 3, 1989 */ |
else if (strcmp(argv[j],"nnf")==0) /* test for nnf option */ |
nfFlag=0; /* nfFlag=1 means number INCLUDE */ |
/* separately. ver TER_2.0 6/17/89 */ |
else if (strcmp(argv[j],"p50")==0){ /* page every 50 lines */ |
Pflag50 = 1; /* ver (TER) 2.01 19 Jun 89 */ |
Pflag75 = 0; |
} /* separately. ver TER_2.0 6/17/89 */ |
else if (strcmp(argv[j],"p75")==0){ /* page every 75 lines */ |
Pflag50 = 0; /* ver (DWC) 2.10 8 Oct 2001 */ |
Pflag75 = 1; |
} |
j++; |
} |
} |
root = NULL; |
|
Cfn = 0; |
np = argv; |
Line_num = 0; /* reset line number */ |
while( ++Cfn <= N_files ) |
if((Fd = fopen(*++np,"r")) == NULL) |
printf("as: can't open %s\n",*np); |
else{ |
make_pass(); |
fclose(Fd); |
} |
if( Err_count == 0 ){ |
Pass++; |
re_init(); |
Cfn = 0; |
np = argv; |
Line_num = 0; |
FdCount=0; /* Resets INCLUDE file nesting ver TER_2.0 6/17/89 */ |
while( ++Cfn <= N_files) |
if((Fd = fopen(*++np,"r")) != NULL) |
{ |
make_pass(); |
fclose(Fd); |
} |
printf ("Program + Init Data = %d bytes\n",F_total); /* print total bytes */ |
printf ("Error count = %d\n",Err_count); /* rel TER_2.0 */ |
if (Sflag == 1) |
{ |
printf ("\n\f\n"); |
stable (root); |
} |
if (CREflag == 1) |
{ |
printf ("\n\f\n"); |
cross (root); |
} |
if (CRflag == 1) |
fprintf(Objfil,"S9030000FC%c\n",CR); /* ver TER_1.1 print w <CR> */ |
else |
fprintf(Objfil,"S9030000FC\n"); /* at least give a decent ending */ |
fclose(Objfil); /* close file correctly ver TER_1.1 */ |
} |
else /* just note errors, TER_2.0 */ |
{ |
printf ("Program + Init Data = %d bytes\n",F_total); /* print total bytes */ |
printf ("Error count = %d\n",Err_count); |
} |
fwd_done(); |
exit(Err_count); /* neat for UNIX cuz can test return value in script |
but on other systems like Amiga, mostly just makes |
further script statements fail if >10, else |
nothing. Therefore, printed out byte count |
and error level. ver (TER) 2.02 19 Jun 89 */ |
} |
|
initialize() |
{ |
FILE *fopen(); |
int i = 0; |
|
#ifdef DEBUG |
printf("Initializing\n"); |
#endif |
Err_count = 0; |
Pc = 0; |
Pass = 1; |
Lflag = 0; |
Cflag = 0; |
Ctotal = 0; |
Sflag = 0; |
CREflag = 0; |
N_page = 0; |
Line[MAXBUF-1] = NEWLINE; |
|
strcpy(Obj_name,Argv[1]); /* copy first file name into array */ |
do { |
if (Obj_name[i]=='.') |
Obj_name[i]=0; |
} |
while (Obj_name[i++] != 0); |
strcat(Obj_name,".s19"); /* append .out to file name. */ |
if( (Objfil = fopen(Obj_name,"w")) == NULL) |
fatal("Can't create object file"); |
fwdinit(); /* forward ref init */ |
localinit(); /* target machine specific init. */ |
} |
|
re_init() |
{ |
#ifdef DEBUG |
printf("Reinitializing\n"); |
#endif |
Pc = 0; |
E_total = 0; |
P_total = 0; |
Ctotal = 0; |
N_page = 0; |
fwdreinit(); |
} |
|
make_pass() |
{ |
#ifdef IBM |
char *fgets(); /* the original line */ |
#else |
char *FGETS(); /* use own FGETS which is rewrite of lib function */ |
/* such that it discards <CR> so can read code */ |
/* generated on IBM */ |
/* June 3, 1989 rev TER_1.1 */ |
#endif |
|
#ifdef DEBUG |
printf("Pass %d\n",Pass); |
#endif |
|
#ifndef IBM |
while( FGETS(Line,MAXBUF-1,Fd) != (char *)NULL ){ /* changed to FGETS */ |
/* which does not pass on <CR> June 3, 1989 */ |
/* rev TER_1.1 */ |
#else |
while( fgets(Line,MAXBUF,Fd) != (char *)NULL ){ |
|
#endif |
|
Line_num++; |
P_force = 0; /* No force unless bytes emitted */ |
N_page = 0; |
if(parse_line()) |
process(); |
if(Pass == 2 && Lflag && !N_page) |
print_line(); |
P_total = 0; /* reset byte count */ |
Cycles = 0; /* and per instruction cycle count */ |
} |
f_record(); |
} |
|
|
/* |
* parse_line --- split input line into label, op and operand |
*/ |
parse_line() |
{ |
register char *ptrfrm = Line; |
register char *ptrto = Label; |
char *skip_white(); |
|
if( *ptrfrm == '*' || *ptrfrm == '\n' || *ptrfrm == ';' ) |
/* added check for ';' ver TER_1.1 */ |
/* June 3, 1989 */ |
return(0); /* a comment line */ |
|
while( delim(*ptrfrm)== NO ) /* parsing Label */ |
*ptrto++ = *ptrfrm++; |
if(*--ptrto != ':')ptrto++; /* allow trailing : */ |
*ptrto = EOS; |
|
ptrfrm = skip_white(ptrfrm); |
if (*ptrfrm == ';') { /* intercept comment after label, ver TER_2.0 */ |
*Op = *Operand = EOS; /* comment, no Opcode or Operand */ |
return(1); } |
ptrto = Op; |
|
while( delim(*ptrfrm) == NO) /* parsing Opcode */ |
*ptrto++ = mapdn(*ptrfrm++); |
*ptrto = EOS; |
|
ptrfrm = skip_white(ptrfrm); |
if (*ptrfrm == ';') { /* intercept comment, ver TER_2.0 */ |
*Operand = EOS; /* comment, no Operand */ |
return(1); } |
|
ptrto = Operand; |
while( (*ptrfrm != NEWLINE) && (*ptrfrm != ';')) /* ver TER_2.0 */ |
*ptrto++ = *ptrfrm++; /* kill comments */ |
*ptrto = EOS; |
|
#ifdef DEBUG |
printf("Label-%s-\n",Label); |
printf("Op----%s-\n",Op); |
printf("Operand-%s-\n",Operand); |
#endif |
return(1); |
} |
|
/* |
* process --- determine mnemonic class and act on it |
*/ |
process() |
{ |
register struct oper *i; |
struct oper *mne_look(); |
|
Old_pc = Pc; /* setup `old' program counter */ |
Optr = Operand; /* point to beginning of operand field */ |
|
if(*Op==EOS){ /* no mnemonic */ |
if(*Label != EOS) |
install(Label,Pc); |
} |
else if( (i = mne_look(Op))== NULL) |
error("Unrecognized Mnemonic"); |
else if( i->class == PSEUDO ) |
do_pseudo(i->opcode); |
else{ |
if( *Label )install(Label,Pc); |
if(Cflag)Cycles = i->cycles; |
do_op(i->opcode,i->class); |
if(Cflag)Ctotal += Cycles; |
} |
} |
|
#ifndef IBM |
char *FGETS(s, n, iop) /* get at most n chars from iop */ |
/* Added rev TER_1.1 June 3, 1989 */ |
/* Adapted from Kernighan & Ritchie */ |
/* An fgets() that is IBM proof. Not needed if |
this IS an IBM */ |
|
char *s; |
int n; |
register FILE *iop; |
{ |
register int c; |
register char *cs; |
|
cs=s; |
while (--n > 0 && (c = getc(iop)) != EOF) /* read chars if not file end */ |
{ |
if ((*cs = c) != CR) cs++; /* incr buffer pointer if not CR */ |
/* If CR, leave to be written over */ |
if (c == '\n') |
break; |
} |
*cs = '\0'; /* replace NEWLINE with NULL as in standard fgets() */ |
return((c == EOF && cs == s) ? NULL : s); /* return NULL if this is EOF */ |
} |
#endif |
/table09.h
0,0 → 1,152
struct oper table[] = { |
|
"abx", INH, 58, 3, |
"adca", GEN, 137, 2, |
"adcb", GEN, 201, 2, |
"adda", GEN, 139, 2, |
"addb", GEN, 203, 2, |
"addd", LONGIMM, 195, 4, |
"anda", GEN, 132, 2, |
"andb", GEN, 196, 2, |
"andcc", IMM, 28, 3, |
"asl", GRP2, 8, 4, |
"asla", INH, 72, 2, |
"aslb", INH, 88, 2, |
"asr", GRP2, 7, 4, |
"asra", INH, 71, 2, |
"asrb", INH, 87, 2, |
"bcc", REL, 36, 3, |
"bcs", REL, 37, 3, |
"beq", REL, 39, 3, |
"bge", REL, 44, 3, |
"bgt", REL, 46, 3, |
"bhi", REL, 34, 3, |
"bhs", REL, 36, 3, |
"bita", GEN, 133, 2, |
"bitb", GEN, 197, 2, |
"ble", REL, 47, 3, |
"blo", REL, 37, 3, |
"bls", REL, 35, 3, |
"blt", REL, 45, 3, |
"bmi", REL, 43, 3, |
"bne", REL, 38, 3, |
"bpl", REL, 42, 3, |
"bra", REL, 32, 3, |
"brn", REL, 33, 3, |
"bsr", REL, 141, 7, |
"bvc", REL, 40, 3, |
"bvs", REL, 41, 3, |
"clr", GRP2, 15, 4, |
"clra", INH, 79, 2, |
"clrb", INH, 95, 2, |
"cmpa", GEN, 129, 2, |
"cmpb", GEN, 193, 2, |
"cmpd", P2GEN, 131, 5, |
"cmps", P3GEN, 140, 5, |
"cmpu", P3GEN, 131, 5, |
"cmpx", LONGIMM, 140, 4, |
"cmpy", P2GEN, 140, 5, |
"com", GRP2, 3, 4, |
"coma", INH, 67, 2, |
"comb", INH, 83, 2, |
"cpx", LONGIMM, 140, 4, /* for compatibility with old code */ |
"cwai", IMM, 60, 20, |
"daa", INH, 25, 2, |
"dec", GRP2, 10, 4, |
"deca", INH, 74, 2, |
"decb", INH, 90, 2, |
"eora", GEN, 136, 2, |
"eorb", GEN, 200, 2, |
"exg", RTOR, 30, 8, |
"inc", GRP2, 12, 4, |
"inca", INH, 76, 2, |
"incb", INH, 92, 2, |
"jmp", GRP2, 14, 1, |
"jsr", NOIMM, 141, 5, |
"lbcc", P2REL, 36, 6, |
"lbcs", P2REL, 37, 6, |
"lbeq", P2REL, 39, 6, |
"lbge", P2REL, 44, 6, |
"lbgt", P2REL, 46, 6, |
"lbhi", P2REL, 34, 6, |
"lbhs", P2REL, 36, 6, |
"lble", P2REL, 47, 6, |
"lblo", P2REL, 37, 6, |
"lbls", P2REL, 35, 6, |
"lblt", P2REL, 45, 6, |
"lbmi", P2REL, 43, 6, |
"lbne", P2REL, 38, 6, |
"lbpl", P2REL, 42, 6, |
"lbra", P1REL, 22, 5, |
"lbrn", P2REL, 33, 5, |
"lbsr", P1REL, 23, 9, |
"lbvc", P2REL, 40, 6, |
"lbvs", P2REL, 41, 6, |
"lda", GEN, 134, 2, |
"ldaa", GEN, 134, 2, |
"ldab", GEN, 198, 2, |
"ldb", GEN, 198, 2, |
"ldd", LONGIMM, 204, 3, |
"lds", P2GEN, 206, 4, |
"ldu", LONGIMM, 206, 3, |
"ldx", LONGIMM, 142, 3, |
"ldy", P2GEN, 142, 4, |
"leas", INDEXED, 50, 2, |
"leau", INDEXED, 51, 2, |
"leax", INDEXED, 48, 2, |
"leay", INDEXED, 49, 2, |
"lsl", GRP2, 8, 4, |
"lsla", INH, 72, 2, |
"lslb", INH, 88, 2, |
"lsr", GRP2, 4, 4, |
"lsra", INH, 68, 2, |
"lsrb", INH, 84, 2, |
"mul", INH, 61, 11, |
"neg", GRP2, 0, 4, |
"nega", INH, 64, 2, |
"negb", INH, 80, 2, |
"nop", INH, 18, 2, |
"ora", GEN, 138, 2, |
"oraa", GEN, 138, 2, |
"orab", GEN, 202, 2, |
"orb", GEN, 202, 2, |
"orcc", IMM, 26, 3, |
"pshs", RLIST, 52, 5, |
"pshu", RLIST, 54, 5, |
"puls", RLIST, 53, 5, |
"pulu", RLIST, 55, 5, |
"rol", GRP2, 9, 4, |
"rola", INH, 73, 2, |
"rolb", INH, 89, 2, |
"ror", GRP2, 6, 4, |
"rora", INH, 70, 2, |
"rorb", INH, 86, 2, |
"rti", INH, 59, 15, |
"rts", INH, 57, 5, |
"sbca", GEN, 130, 2, |
"sbcb", GEN, 194, 2, |
"sex", INH, 29, 2, |
"sta", NOIMM, 135, 2, |
"staa", NOIMM, 135, 2, |
"stab", NOIMM, 199, 2, |
"stb", NOIMM, 199, 2, |
"std", NOIMM, 205, 3, |
"sts", P2NOIMM, 207, 4, |
"stu", NOIMM, 207, 3, |
"stx", NOIMM, 143, 3, |
"sty", P2NOIMM, 143, 4, |
"suba", GEN, 128, 2, |
"subb", GEN, 192, 2, |
"subd", LONGIMM, 131, 4, |
"swi", INH, 63, 19, |
"swi2", P2INH, 63, 20, |
"swi3", P3INH, 63, 20, |
"sync", INH, 19, 4, |
"sys", SYS, 0, 19, |
"tfr", RTOR, 31, 6, |
"tst", GRP2, 13, 4, |
"tsta", INH, 77, 2, |
"tstb", INH, 93, 2 |
|
}; |
|
/ffwd.c
0,0 → 1,85
/* |
* file I/O version of forward ref handler |
*/ |
|
#define FILEMODE 0644 /* file creat mode */ |
#define UPDATE 2 /* file open mode */ |
#define ABS 0 /* absolute seek */ |
|
int Forward =0; /* temp file's file descriptor */ |
char Fwd_name[] = { "Fwd_refs" } ; |
|
/* |
* fwdinit --- initialize forward ref file |
*/ |
fwdinit() |
{ |
Forward = open(Fwd_name,O_CREAT | O_TRUNC | O_WRONLY, FILEMODE); //creat(Fwd_name,FILEMODE); |
if(Forward <0) |
fatal("Can't create temp file"); |
close(Forward); /* close and reopen for reads and writes */ |
Forward = open(Fwd_name,UPDATE); |
if(Forward <0) |
fatal("Forward ref file has gone."); |
} |
|
/* |
* fwdreinit --- reinitialize forward ref file |
*/ |
fwdreinit() |
{ |
F_ref = 0; |
Ffn = 0; |
lseek(Forward,0L,ABS); /* rewind forward refs */ |
read(Forward,&Ffn,sizeof(Ffn)); |
read(Forward,&F_ref,sizeof(F_ref)); /* read first forward ref into mem */ |
#ifdef DEBUG |
printf("First fwd ref: %d,%d\n",Ffn,F_ref); |
#endif |
} |
|
/* |
* fwdmark --- mark current file/line as containing a forward ref |
*/ |
fwdmark() |
{ |
write(Forward,&Cfn,sizeof(Cfn)); |
write(Forward,&Line_num,sizeof(Line_num)); |
} |
|
/* |
* fwdnext --- get next forward ref |
*/ |
fwdnext() |
{ |
int stat; |
|
stat = read(Forward,&Ffn,sizeof(Ffn)); |
#ifdef DEBUG |
printf("Ffn stat=%d ",stat); |
#endif |
stat = read(Forward,&F_ref,sizeof(F_ref)); |
#ifdef DEBUG |
printf("F_ref stat=%d ",stat); |
#endif |
if( stat < 2 ){ |
F_ref=0;Ffn=0; |
} |
#ifdef DEBUG |
printf("Next Fwd ref: %d,%d\n",Ffn,F_ref); |
#endif |
} |
|
/* |
* fwd_done --- closes & deletes forward reference file |
*/ |
fwd_done() |
{ |
int stat; |
|
stat = close(Forward); /* Have to close first on MS-DOS or you leave lost clusters. */ |
#ifndef DEBUG |
if( stat == 0 ) /* If close was successful, delete file */ |
unlink(Fwd_name); |
#endif |
} |
/eval.c
0,0 → 1,199
/* |
* eval --- evaluate expression |
* |
* an expression is constructed like this: |
* |
* expr ::= expr + term | |
* expr - term ; |
* expr * term ; |
* expr / term ; |
* expr | term ; |
* expr & term ; |
* expr % term ; |
* expr ^ term ; |
* |
* term ::= symbol | |
* * | |
* constant ; |
* |
* symbol ::= string of alphanumerics with non-initial digit |
* |
* constant ::= hex constant | |
* binary constant | |
* octal constant | |
* decimal constant | |
* ascii constant; |
* |
* hex constant ::= '$' {hex digits}; |
* |
* octal constant ::= '@' {octal digits}; |
* |
* binary constant ::= '%' { 1 | 0 }; |
* |
* decimal constant ::= {decimal digits}; |
* |
* ascii constant ::= ''' any printing char; |
* |
*/ |
eval() |
{ |
int left,right; /* left and right terms for expression */ |
char o; /* operator character */ |
|
#ifdef DEBUG |
printf("Evaluating %s\n",Optr); |
#endif |
Force_byte = NO; |
Force_word = NO; |
if(*Optr=='<'){ |
Force_byte++; |
Optr++; |
} |
else if(*Optr=='>'){ |
Force_word++; |
Optr++; |
} |
left = get_term(); /* pickup first part of expression */ |
|
while( is_op(*Optr)){ |
o = *Optr++; /* pickup connector and skip */ |
right = get_term(); /* pickup current rightmost side */ |
switch(o){ |
case '+': left += right; break; |
case '-': left -= right; break; |
case '*': left *= right; break; |
case '/': left /= right; break; |
case '|': left |= right; break; |
case '&': left &= right; break; |
case '%': left %= right; break; |
case '^': left = left^right; break; |
} |
} |
|
Result= left; |
#ifdef DEBUG |
printf("Result=%x\n",Result); |
printf("Force_byte=%d Force_word=%d\n",Force_byte,Force_word); |
#endif |
return(YES); |
} |
|
/* |
* is_op --- is character an expression operator? |
*/ |
is_op(c) |
char c; |
{ |
if( any(c,"+-*/&%|^")) |
return(YES); |
return(NO); |
} |
|
|
/* |
* get_term --- evaluate a single item in an expression |
*/ |
get_term() |
{ |
char hold[MAXBUF]; |
char *tmp; |
int val = 0; /* local value being built */ |
int minus; /* unary minus flag */ |
struct nlist *lookup(),*pointer; |
struct link *pnt,*bpnt; |
|
if( *Optr == '-' ){ |
Optr++; |
minus =YES; |
} |
else |
minus = NO; |
|
while( *Optr == '#' ) Optr++; |
|
/* look at rest of expression */ |
|
if(*Optr=='%'){ /* binary constant */ |
Optr++; |
while( any(*Optr,"01")) |
val = (val * 2) + ( (*Optr++)-'0'); |
} |
else if(*Optr=='@'){ /* octal constant */ |
Optr++; |
while( any(*Optr,"01234567")) |
val = (val * 8) + ((*Optr++)-'0'); |
} |
else if(*Optr=='$'){ /* hex constant */ |
Optr++; |
while( any(*Optr,"0123456789abcdefABCDEF")) |
if( *Optr > '9' ) |
val = (val * 16) + 10 + (mapdn(*Optr++)-'a'); |
else |
val = (val * 16) + ((*Optr++)-'0'); |
} |
else if( any(*Optr,"0123456789")){ /* decimal constant */ |
while(*Optr >= '0' && *Optr <= '9') |
val = (val * 10) + ( (*Optr++)-'0'); |
} |
else if(*Optr=='*'){ /* current location counter */ |
Optr++; |
val = Old_pc; |
} |
else if(*Optr=='\''){ /* character literal */ |
Optr++; |
if(*Optr == EOS) |
val = 0; |
else |
val = *Optr++; |
} |
else if( alpha(*Optr) ){ /* a symbol */ |
tmp = hold; /* collect symbol name */ |
while(alphan(*Optr)) |
*tmp++ = *Optr++; |
*tmp = EOS; |
pointer = lookup(hold); |
if (pointer != NULL) |
{ |
if (Pass == 2) |
{ |
pnt = pointer->L_list; |
bpnt = NULL; |
while (pnt != NULL) |
{ |
bpnt = pnt; |
pnt = pnt->next; |
} |
pnt = (struct link *) alloc(sizeof(struct link)); |
if (bpnt == NULL) |
pointer->L_list = pnt; |
else bpnt->next = pnt; |
pnt->L_num = Line_num; |
pnt->next = NULL; |
} |
val = Last_sym; |
} |
else{ |
if(Pass==1){ /* forward ref here */ |
fwdmark(); |
if( !Force_byte ) |
Force_word++; |
val = 0; |
} |
else /* added ver TER_2.0 2 Jul 89 */ |
error("Symbol undefined Pass 2"); |
} |
if(Pass==2 && Line_num==F_ref && Cfn==Ffn){ |
if( !Force_byte ) |
Force_word++; |
fwdnext(); |
} |
} |
else |
/* none of the above */ |
val = 0; |
|
if(minus) |
return(-val); |
else |
return(val); |
} |
/as.h
0,0 → 1,167
/* |
* machine independent definitions and global variables |
*/ |
|
#define YES 1 |
#define NO 0 |
#define ERR (-1) |
|
#define MAXBUF 128 |
#define MAXOP 10 /* longest mnemonic */ |
#define MAXLAB 16 |
#define E_LIMIT 32 |
#define P_LIMIT 64 |
#define MAXINCFILES 30 /* nestinf levels for INCLUDE files at one time */ |
/* ver TER_2.0 6/17/89 */ |
#define MAXIFD 30 /* max nesting levels for IFD/IFND statements */ |
/* ver TER_2.0 2 Jul 89 */ |
#define IF_FALSE 0 /* tokens for IfMachine (conditional assembly) */ |
#define IF_TRUE 1 /* added ver TER_2.0 27Jun89 */ |
#define IF_ELSE 2 |
#define IF_ENDIF 3 |
#define IF_NORMAL 4 |
#define IF_END 5 |
#define IF_EOF 6 /* end tokens */ |
|
/* Character Constants */ |
#define NEWLINE '\n' |
#define CR 0x0D /* <CR> or ^M ver TER_1.1 June 3, 1989 */ |
#define TAB '\t' |
#define BLANK ' ' |
#define EOS '\0' |
|
/* Opcode Classes */ |
#define INH 0 /* Inherent */ |
#define GEN 1 /* General Addressing */ |
#define IMM 2 /* Immediate only */ |
#define REL 3 /* Short Relative */ |
#define P2REL 4 /* Long Relative */ |
#define P1REL 5 /* Long Relative (LBRA and LBSR)*/ |
#define NOIMM 6 /* General except for Immediate */ |
#define P2GEN 7 /* Page 2 General */ |
#define P3GEN 8 /* Page 3 General */ |
#define RTOR 9 /* Register To Register */ |
#define INDEXED 10 /* Indexed only */ |
#define RLIST 11 /* Register List */ |
#define P2NOIMM 12 /* Page 2 No Immediate */ |
#define P2INH 13 /* Page 2 Inherent */ |
#define P3INH 14 /* Page 3 Inherent */ |
#define GRP2 15 /* Group 2 (Read/Modify/Write) */ |
#define LONGIMM 16 /* Immediate mode takes 2 bytes */ |
#define BTB 17 /* Bit test and branch */ |
#define SETCLR 18 /* Bit set or clear */ |
#define CPD 19 /* compare d 6811 */ |
#define XLIMM 20 /* LONGIMM for X 6811 */ |
#define XNOIMM 21 /* NOIMM for X 6811 */ |
#define YLIMM 22 /* LONGIMM for Y 6811 */ |
#define YNOIMM 23 /* NOIMM for Y 6811 */ |
#define FAKE 24 /* convenience mnemonics 6804 */ |
#define APOST 25 /* A accum after opcode 6804 */ |
#define BPM 26 /* branch reg plus/minus 6804 */ |
#define CLRX 27 /* mvi x,0 6804 */ |
#define CLRY 28 /* mvi y,0 6804 */ |
#define LDX 29 /* mvi x,expr 6804 */ |
#define LDY 30 /* mvi y,expr 6804 */ |
#define MVI 31 /* mvi 6804 */ |
#define EXT 32 /* extended 6804 */ |
#define BIT 33 /* bit manipulation 6301 */ |
#define SYS 34 /* syscalls (really swi) */ |
#define PSEUDO 35 /* Pseudo ops */ |
|
/* global variables */ |
int Line_num =0; /* current line number */ |
int Err_count =0; /* total number of errors */ |
char Line[MAXBUF] = {0}; /* input line buffer */ |
char Label[MAXLAB] = {0}; /* label on current line */ |
char Op[MAXOP] = {0}; /* opcode mnemonic on current line */ |
char Operand[MAXBUF] = {0}; /* remainder of line after op */ |
/* (up to ';' rel TER_2.0) */ |
char *Optr =0; /* pointer into current Operand field */ |
int Result =0; /* result of expression evaluation */ |
int Force_word =0; /* Result should be a word when set */ |
int Force_byte =0; /* Result should be a byte when set */ |
int Pc =0; /* Program Counter */ |
int Old_pc =0; /* Program Counter at beginning */ |
|
int Last_sym =0; /* result of last lookup */ |
|
int Pass =0; /* Current pass # */ |
int N_files =0; /* Number of files to assemble */ |
FILE *Fd =0; /* Current input file structure */ |
int Cfn =0; /* Current file number 1...n */ |
int Ffn =0; /* forward ref file # */ |
int F_ref =0; /* next line with forward ref */ |
char **Argv =0; /* pointer to file names */ |
|
int E_total =0; /* total # bytes for one line */ |
int E_bytes[E_LIMIT] = {0}; /* Emitted held bytes */ |
int E_pc =0; /* Pc at beginning of collection*/ |
|
int Lflag = 0; /* listing flag 0=nolist, 1=list*/ |
|
int P_force = 0; /* force listing line to include Old_pc */ |
int P_total =0; /* current number of bytes collected */ |
int P_bytes[P_LIMIT] = {0}; /* Bytes collected for listing */ |
|
int Cflag = 0; /* cycle count flag */ |
int Cycles = 0; /* # of cycles per instruction */ |
long Ctotal = 0; /* # of cycles seen so far */ |
int Sflag = 0; /* symbol table flag, 0=no symbol */ |
int N_page = 0; /* new page flag */ |
int Page_num = 2; /* page number */ |
int CREflag = 0; /* cross reference table flag */ |
int CRflag = 0; /* flag to add <CR><LF> to S record */ |
/* added ver TER_1.1 June 3, 1989 */ |
int nfFlag = 1; /* if=1 number INCLUDE files separate */ |
/* ver TER_2.0 June 17, 1989 */ |
int FdCount = 0; /* INCLUDE files "stack" pointer */ |
/* ver TER_2.0 June 17, 1989 */ |
char InclFName[MAXBUF]={0}; /* current INCLUDE file name */ |
int F_total = 0; /* total bytes emitted in S file */ |
/* ver (TER) 2.02 19 Jun 89 */ |
int Page_lines = 0; /* total lines this page */ |
/* ver (TER) 2.02 19 Jun 89 */ |
int Pflag50 = 0; /* if 1 then form feed every 50 lines */ |
/* ver (TER) 2.02 19 Jun 89 */ |
int Pflag75 = 0; /* if 1 then form feed every 75 lines */ |
/* ver (DWC) 2.10 8 Oct 2001 */ |
int PC_Save[4] = {0,0,0,0}; /* saved contents of CODE,DATA,BSS,AUTO PCs */ |
/* ver TER_2.09 25 July 89 */ |
int PC_ptr = 0; /* index or pointer to current PC */ |
/* initialized to CODE ver TER_2.09 25 July 89 */ |
|
struct link { /* linked list to hold line numbers */ |
int L_num; /* line number */ |
struct link *next; /* pointer to next node */ |
}; |
|
struct nlist { /* basic symbol table entry */ |
char *name; |
int def; /* value of symbol, assigned by user */ |
int def2; /* value assign by assembler, e.g. defined this pass? */ |
/* added ver TER_2.0 4 Jul 89 */ |
struct nlist *Lnext ; /* left node of the tree leaf */ |
struct nlist *Rnext; /* right node of the tree leaf */ |
struct link *L_list; /* pointer to linked list of line numbers */ |
}; |
|
struct oper { /* an entry in the mnemonic table */ |
char *mnemonic; /* its name */ |
char class; /* its class */ |
int opcode; /* its base opcode */ |
char cycles; /* its base # of cycles */ |
}; |
|
struct nlist *root; /* root node of the tree */ |
|
FILE *Objfil =0; /* object file's file descriptor*/ |
char Obj_name[] = {" "}; |
|
struct InclFile { /* The INCLUDE files nesting "stack" */ |
/* added ver TER_2.0 6/17/89 */ |
FILE *fp; /* saved file pointer (next level up) */ |
int line_num; /* saved line number count */ |
char *name; /* saved file name */ |
}; |
|
struct InclFile InclFiles[MAXINCFILES]; /* the nesting stack itself */ |
/do09.c
0,0 → 1,603
/* |
* MC6809 specific processing |
*/ |
|
#define PAGE2 0x10 |
#define PAGE3 0x11 |
#define IPBYTE 0x9F /* extended indirect postbyte */ |
#define SWI 0x3F |
|
/* register names */ |
|
#define RD 0 |
#define RX 1 |
#define RY 2 |
#define RU 3 |
#define RS 4 |
#define RPC 5 |
#define RA 8 |
#define RB 9 |
#define RCC 10 |
#define RDP 11 |
#define RPCR 12 |
|
/* convert tfr/exg reg number into psh/pul format */ |
int regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0}; |
int rcycl[]= { 2,2, 2, 2, 2, 2, 0,0,1,1,1,1,0}; |
|
/* addressing modes */ |
#define IMMED 0 /* immediate */ |
#define IND 1 /* indexed */ |
#define INDIR 2 /* indirect */ |
#define OTHER 3 /* NOTA */ |
|
/* |
* localinit --- machine specific initialization |
*/ |
localinit() |
{ |
} |
|
/* |
* do_op --- process mnemonic |
* |
* Called with the base opcode and it's class. Optr points to |
* the beginning of the operand field. |
*/ |
void do_op(opcode,class) |
int opcode; /* base opcode */ |
int class; /* mnemonic class */ |
{ |
int dist; /* relative branch distance */ |
int src,dst;/* source and destination registers */ |
int pbyte; /* postbyte value */ |
int amode; /* indicated addressing mode */ |
int j; |
|
amode = set_mode(); /* pickup indicated addressing mode */ |
|
switch(class){ |
case INH: /* inherent addressing */ |
emit(opcode); |
return; |
case GEN: /* general addressing */ |
do_gen(opcode,amode); |
return; |
case IMM: /* immediate addressing */ |
if( amode != IMMED ){ |
error("Immediate Operand Required"); |
return; |
} |
Optr++; |
eval(); |
emit(opcode); |
emit(lobyte(Result)); |
return; |
case REL: /* short relative branches */ |
eval(); |
dist = Result - (Pc+2); |
emit(opcode); |
if( (dist >127 || dist <-128) && Pass==2){ |
error("Branch out of Range"); |
emit(lobyte(-2)); |
return; |
} |
emit(lobyte(dist)); |
return; |
case P2REL: /* long relative branches */ |
eval(); |
dist = Result - (Pc+4); |
emit(PAGE2); |
emit(opcode); |
eword(dist); |
return; |
case P1REL: /* lbra and lbsr */ |
if( amode == IMMED) |
Optr++; /* kludge for C compiler */ |
eval(); |
dist = Result - (Pc+3); |
emit(opcode); |
eword(dist); |
return; |
case NOIMM: |
if( amode == IMMED ){ |
error("Immediate Addressing Illegal"); |
return; |
} |
do_gen(opcode,amode); |
return; |
case P2GEN: |
emit(PAGE2); |
if( amode == IMMED ){ |
emit(opcode); |
Optr++; |
eval(); |
eword(Result); |
return; |
} |
do_gen(opcode,amode); |
return; |
case P3GEN: |
emit(PAGE3); |
if( amode == IMMED ){ |
emit(opcode); |
Optr++; |
eval(); |
eword(Result); |
return; |
} |
do_gen(opcode,amode); |
return; |
case RTOR: /* tfr and exg */ |
emit(opcode); |
src = regnum(); |
while(alpha(*Optr))Optr++; |
if(src==ERR){ |
error("Register Name Required"); |
emit(0); |
return; |
} |
if(*Optr++ != ','){ |
error("Missing ,"); |
emit(0); |
return; |
} |
dst = regnum(); |
while(alpha(*Optr))Optr++; |
if(dst==ERR){ |
error("Register Name Required"); |
emit(0); |
return; |
} |
if( src==RPCR || dst==RPCR){ |
error("PCR illegal here"); |
emit(0); |
return; |
} |
if( (src <=5 && dst >=8) || |
(src >=8 && dst <=5)){ |
error("Register Size Mismatch"); |
emit(0); |
return; |
} |
emit( (src<<4)+dst ); |
return; |
case INDEXED: /* indexed addressing only */ |
if( *Optr == '#'){ |
Optr++; /* kludge city */ |
amode = IND; |
} |
if( amode != IND ){ |
error("Indexed Addressing Required"); |
return; |
} |
do_indexed(opcode); |
return; |
case RLIST: /* pushes and pulls */ |
if(*Operand == EOS){ |
error("Register List Required"); |
return; |
} |
emit(opcode); |
pbyte = 0; |
do{ |
j = regnum(); |
if( j == ERR || j==RPCR) |
error("Illegal Register Name"); |
else if(j==RS && (opcode==52)) |
error("Can't Push S on S"); |
else if(j==RU && (opcode==54)) |
error("Can't Push U on U"); |
else if(j==RS && (opcode==53)) |
error("Can't Pull S from S"); |
else if(j==RU && (opcode==55)) |
error("Can't Pull U from U"); |
else{ |
pbyte |= regs[j]; |
Cycles += rcycl[j]; |
} |
while(*Optr != EOS && alpha(*Optr))Optr++; |
}while( *Optr++ == ',' ); |
emit(lobyte(pbyte)); |
return; |
case P2NOIMM: |
if( amode == IMMED ) |
error("Immediate Addressing Illegal"); |
else{ |
emit(PAGE2); |
do_gen(opcode,amode); |
} |
return; |
case P2INH: /* Page 2 inherent */ |
emit(PAGE2); |
emit(opcode); |
return; |
case P3INH: /* Page 3 inherent */ |
emit(PAGE3); |
emit(opcode); |
return; |
case LONGIMM: |
if( amode == IMMED ){ |
emit(opcode); |
Optr++; |
eval(); |
eword(Result); |
} |
else |
do_gen(opcode,amode); |
return; |
case GRP2: |
if( amode == IND ){ |
do_indexed(opcode+0x60); |
return; |
} |
else if( amode == INDIR){ |
Optr++; |
emit(opcode + 0x60); |
emit(IPBYTE); |
eval(); |
eword(Result); |
Cycles += 7; |
if(*Optr == ']'){ |
Optr++; |
return; |
} |
error("Missing ']'"); |
return; |
} |
eval(); |
if(Force_word){ |
emit(opcode+0x70); |
eword(Result); |
Cycles += 3; |
return; |
} |
if(Force_byte){ |
emit(opcode); |
emit(lobyte(Result)); |
Cycles += 2; |
return; |
} |
if(Result>=0 && Result <=0xFF){ |
emit(opcode); |
emit(lobyte(Result)); |
Cycles += 2; |
return; |
} |
else { |
emit(opcode+0x70); |
eword(Result); |
Cycles += 3; |
return; |
} |
case SYS: /* system call */ |
emit(SWI); |
eval(); |
emit(lobyte(Result)); |
return; |
default: |
fatal("Error in Mnemonic table"); |
} |
} |
|
|
/* |
* do_gen --- process general addressing mode stuff |
*/ |
do_gen(op,mode) |
int op; |
int mode; |
{ |
if( mode == IMMED){ |
Optr++; |
emit(op); |
eval(); |
emit(lobyte(Result)); |
return(0); |
} |
else if( mode == IND ){ |
do_indexed(op+0x20); |
return(0); |
} |
else if( mode == INDIR){ |
Optr++; |
emit(op+0x20); |
emit(IPBYTE); |
eval(); |
eword(Result); |
Cycles += 7; |
if(*Optr == ']'){ |
Optr++; |
return(0); |
} |
error("Missing ']'"); |
return(0); |
} |
else if( mode == OTHER){ |
eval(); |
if(Force_word){ |
emit(op+0x30); |
eword(Result); |
Cycles += 3; |
return(0); |
} |
if(Force_byte){ |
emit(op+0x10); |
emit(lobyte(Result)); |
Cycles += 2; |
return(0); |
} |
if(Result>=0 && Result <=0xFF){ |
emit(op+0x10); |
emit(lobyte(Result)); |
Cycles += 2; |
return(0); |
} |
else { |
emit(op+0x30); |
eword(Result); |
Cycles += 3; |
return(0); |
} |
} |
else { |
error("Unknown Addressing Mode"); |
return(0); |
} |
} |
|
/* |
* do_indexed --- handle all wierd stuff for indexed addressing |
*/ |
do_indexed(op) |
int op; |
{ |
int pbyte; |
int j,k; |
int predec,pstinc; |
|
Cycles += 2; /* indexed is always 2+ base cycle count */ |
predec=0; |
pstinc=0; |
pbyte=128; |
emit(op); |
if(*Optr=='['){ |
pbyte |= 0x10; /* set indirect bit */ |
Optr++; |
if( !any((char)']',Optr)) |
error("Missing ']'"); |
Cycles += 3; /* indirection takes this much longer */ |
} |
j=regnum(); |
if(j==RA){ |
Cycles++; |
abd_index(pbyte+6); |
return(0); |
} |
if(j==RB){ |
Cycles++; |
abd_index(pbyte+5); |
return(0); |
} |
if(j==RD){ |
Cycles += 4; |
abd_index(pbyte+11); |
return(0); |
} |
eval(); |
Optr++; |
while(*Optr=='-'){ |
predec++; |
Optr++; |
} |
j=regnum(); |
while( alpha(*Optr) )Optr++; |
while(*Optr=='+'){ |
pstinc++; |
Optr++; |
} |
if(j==RPC || j==RPCR){ |
if( pstinc || predec ){ |
error("Auto Inc/Dec Illegal on PC"); |
return(0); |
} |
if(j==RPC){ |
if(Force_word){ |
emit(pbyte+13); |
eword(Result); |
Cycles += 5; |
return(0); |
} |
if(Force_byte){ |
emit(pbyte+12); |
emit(lobyte(Result)); |
Cycles++; |
return(0); |
} |
if(Result>=-128 && Result <=127){ |
emit(pbyte+12); |
emit(lobyte(Result)); |
Cycles++; |
return(0); |
} |
else { |
emit(pbyte+13); |
eword(Result); |
Cycles += 5; |
return(0); |
} |
} |
/* PCR addressing */ |
if(Force_word){ |
emit(pbyte+13); |
eword(Result-(Pc+2)); |
Cycles += 5; |
return(0); |
} |
if(Force_byte){ |
emit(pbyte+12); |
emit(lobyte(Result-(Pc+1))); |
Cycles++; |
return(0); |
} |
k=Result-(Pc+2); |
if( k >= -128 && k <= 127){ |
emit(pbyte+12); |
emit(lobyte(Result-(Pc+1))); |
Cycles++; |
return(0); |
} |
else{ |
emit(pbyte+13); |
eword(Result-(Pc+2)); |
Cycles += 5; |
return(0); |
} |
} |
if(predec || pstinc){ |
if(Result != 0){ |
error("Offset must be Zero"); |
return(0); |
} |
if(predec>2 || pstinc>2){ |
error("Auto Inc/Dec by 1 or 2 only"); |
return(0); |
} |
if((predec==1 && (pbyte&0x10) != 0) || |
(pstinc==1 && (pbyte&0x10) != 0)){ |
error("No Auto Inc/Dec by 1 for Indirect"); |
return(0); |
} |
if(predec && pstinc){ |
error("Can't do both!"); |
return(0); |
} |
if(predec) |
pbyte += predec+1; |
if(pstinc) |
pbyte += pstinc-1; |
pbyte += rtype(j); |
emit(pbyte); |
Cycles += 1 + predec + pstinc; |
return(0); |
} |
pbyte += rtype(j); |
if(Force_word){ |
emit(pbyte+0x09); |
eword(Result); |
Cycles += 4; |
return(0); |
} |
if(Force_byte){ |
emit(pbyte+0x08); |
emit(lobyte(Result)); |
Cycles++; |
return(0); |
} |
if(Result==0){ |
emit(pbyte+0x04); |
return(0); |
} |
if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){ |
pbyte &= 127; |
pbyte += Result&31; |
emit(pbyte); |
Cycles++; |
return(0); |
} |
if(Result >= -128 && Result <= 127){ |
emit(pbyte+0x08); |
emit(lobyte(Result)); |
Cycles++; |
return(0); |
} |
emit(pbyte+0x09); |
eword(Result); |
Cycles += 4; |
return(0); |
} |
|
|
/* |
* abd_index --- a,b or d indexed |
*/ |
|
abd_index(pbyte) |
int pbyte; |
{ |
int k; |
|
Optr += 2; |
k=regnum(); |
pbyte += rtype(k); |
emit(pbyte); |
return(0); |
} |
|
/* |
* rtype --- return register type in post-byte format |
*/ |
rtype(r) |
int r; |
{ |
switch(r){ |
case RX: return(0x00); |
case RY: return(0x20); |
case RU: return(0x40); |
case RS: return(0x60); |
} |
error("Illegal Register for Indexed"); |
return(0); |
} |
|
/* |
* set_mode --- determine addressing mode from operand field |
*/ |
set_mode() |
{ |
register char *p; |
|
if( *Operand == '#' ) |
return(IMMED); /* immediate addressing */ |
p = Operand; |
while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */ |
if( *p == ',') |
return(IND); /* indexed addressing */ |
p++; |
} |
if( *Operand == '[') |
return(INDIR); /* indirect addressing */ |
return(OTHER); /* NOTA */ |
} |
|
/* |
* regnum --- return register number of *Optr |
*/ |
regnum() |
{ |
if( head(Optr,"D" ))return(RD); |
if( head(Optr,"d" ))return(RD); |
if( head(Optr,"X" ))return(RX); |
if( head(Optr,"x" ))return(RX); |
if( head(Optr,"Y" ))return(RY); |
if( head(Optr,"y" ))return(RY); |
if( head(Optr,"U" ))return(RU); |
if( head(Optr,"u" ))return(RU); |
if( head(Optr,"S" ))return(RS); |
if( head(Optr,"s" ))return(RS); |
if( head(Optr,"PC" ))return(RPC); |
if( head(Optr,"pc" ))return(RPC); |
if( head(Optr,"PCR" ))return(RPCR); |
if( head(Optr,"pcr" ))return(RPCR); |
if( head(Optr,"A" ))return(RA); |
if( head(Optr,"a" ))return(RA); |
if( head(Optr,"B" ))return(RB); |
if( head(Optr,"b" ))return(RB); |
if( head(Optr,"CC" ))return(RCC); |
if( head(Optr,"cc" ))return(RCC); |
if( head(Optr,"DP" ))return(RDP); |
if( head(Optr,"dp" ))return(RDP); |
return(ERR); |
} |
|
|
/as09.c
0,0 → 1,15
//#include "stdafx.h" |
#include <stdio.h> |
#include <fcntl.h> |
#include "as.h" |
#include "table09.h" |
#include "as.c" |
#include "do09.c" |
#include "pseudo.c" |
#include "ifd.c" /* ver TER_2.0 2 Jul 89 */ |
#include "eval.c" |
#include "symtab.c" |
#include "util.c" |
#include "ffwd.c" |
#include "output.c" |
|
/util.c
0,0 → 1,391
/* |
* fatal --- fatal error handler |
*/ |
fatal(str) |
char *str; |
{ |
pouterror(); /* added ver TER_2.0 4 Jul 89 */ |
printf("%s\n",str); |
|
#ifdef IBM /* changed ver TER_2.0 */ |
exit(-1); |
#else |
exit(10); /* Amiga & UNIX prefer positive numbers for error |
minimal error is 10 (no system prob) */ |
#endif |
} |
|
/* |
* error --- error in a line |
* print line number and error |
*/ |
error(str) |
char *str; |
{ |
/* if(N_files > 1) commented out test for N_files in rel TER_2.0 |
because a single command line source file |
(which is what N_files counts) can have multiple |
include source files. */ |
pouterror(); |
printf("%s\n",str); |
} |
/* |
* warn --- trivial error in a line |
* print line number and error |
*/ |
warn(str) |
char *str; |
{ |
/* if(N_files > 1) commented out in rel TER_2.0 same reason as above */ |
printf("%s, line no.",Argv[Cfn]); /* current file name */ |
printf("%d: ",Line_num); /* current line number */ |
printf("Warning --- %s\n",str); |
Page_lines++; |
} |
|
|
/* |
* delim --- check if character is a delimiter |
*/ |
delim(c) |
char c; |
{ |
if( any(c," \t\n")) |
return(YES); |
return(NO); |
} |
|
/* |
* skip_white --- move pointer to next non-whitespace char |
*/ |
char *skip_white(ptr) |
char *ptr; |
{ |
while(*ptr==BLANK || *ptr==TAB) |
ptr++; |
return(ptr); |
} |
|
/* |
* eword --- emit a word to code file |
*/ |
eword(wd) |
int wd; |
{ |
emit(hibyte(wd)); |
emit(lobyte(wd)); |
} |
|
/* |
* emit --- emit a byte to code file |
*/ |
emit(byte) |
{ |
#ifdef DEBUG |
printf("%2x @ %4x\n",byte,Pc); |
#endif |
if(Pass==1){ |
Pc++; |
return(YES); |
} |
if(P_total < P_LIMIT) |
P_bytes[P_total++] = byte; |
E_bytes[E_total++] = byte; |
Pc++; |
if(E_total == E_LIMIT) |
f_record(); |
} |
|
/* |
* f_record --- flush record out in `S1' format |
*/ |
void f_record() /* made void for ANSI C compat ver TER_2.0 6/18/89 */ |
{ |
int i; |
int chksum; |
|
if(Pass == 1) |
return; |
if(E_total==0){ |
E_pc = Pc; |
return; |
} |
F_total += E_total; /* total bytes in file ver (TER)2.01 19 Jun 89 */ |
chksum = E_total+3; /* total bytes in this record */ |
chksum += lobyte(E_pc); |
chksum += E_pc>>8; |
fprintf(Objfil,"S1"); /* record header preamble */ |
hexout(E_total+3); /* byte count +3 */ |
hexout(E_pc>>8); /* high byte of PC */ |
hexout(lobyte(E_pc)); /* low byte of PC */ |
for(i=0;i<E_total;i++){ |
chksum += lobyte(E_bytes[i]); |
hexout(lobyte(E_bytes[i])); /* data byte */ |
} |
chksum =~ chksum; /* one's complement */ |
hexout(lobyte(chksum)); /* checksum */ |
if (CRflag == 1) /* test for CRflag added ver TER_1.1 */ |
fprintf(Objfil,"%c\n",CR); /* print in IBM format for some PROM boxes */ |
else |
fprintf(Objfil,"\n"); /* this is original statement */ |
E_pc = Pc; |
E_total = 0; |
} |
|
char *hexstr = { "0123456789ABCDEF" } ; |
|
hexout(byte) |
int byte; |
{ |
|
byte = lobyte(byte); |
fprintf(Objfil,"%c%c",hexstr[byte>>4],hexstr[byte&017]); |
} |
|
/* |
* print_line --- pretty print input line |
*/ |
print_line() |
{ |
int i; |
register char *ptr; |
|
printf ("%04d ",Line_num); |
if(P_total || P_force) |
printf("%04X",Old_pc); |
else |
printf(" "); |
|
for(i=0;i<P_total && i<6;i++) |
printf(" %02X",lobyte(P_bytes[i])); |
for(;i<6;i++) |
printf(" "); |
printf(" "); |
|
if(Cflag){ |
if(Cycles) |
printf("[%2d ] ",Cycles); |
else |
printf(" "); |
} |
ptr = Line; |
while( *ptr != '\n' ) /* just echo the line back out */ |
putchar(*ptr++); |
for(;i<P_total;i++){ |
if( i%6 == 0 ) |
printf("\n "); /* force data alignment DWC 1-5-92 */ |
printf(" %02X",lobyte(P_bytes[i])); |
} |
if (Pflag50 && (++Page_lines>=50)) /* form feed if flag set */ |
NewPage(); /* ver (TER) 2.02 19 Jun 89 */ |
|
if (Pflag75 && (++Page_lines>=75)) /* form feed if flag set */ |
NewPage(); /* ver (DWC) 2.10 8 Oct 2001 */ |
|
|
printf("\n"); |
} |
|
/* |
* any --- does str contain c? |
*/ |
any(c,str) |
char c; |
char *str; |
{ |
while(*str != EOS) |
if(*str++ == c) |
return(YES); |
return(NO); |
} |
|
/* |
* mapdn --- convert A-Z to a-z |
*/ |
char mapdn(c) |
char c; |
{ |
if( c >= 'A' && c <= 'Z') |
return((char)(c+040)); /* cast value to char for ANSI C, ver TER_2.0 */ |
return(c); |
} |
|
/* |
* lobyte --- return low byte of an int |
*/ |
lobyte(i) |
int i; |
{ |
return(i&0xFF); |
} |
/* |
* hibyte --- return high byte of an int |
*/ |
hibyte(i) |
int i; |
{ |
return((i>>8)&0xFF); |
} |
|
/* |
* head --- is str2 the head of str1? |
*/ |
head(str1,str2) |
char *str1,*str2; |
{ |
while( *str1 != EOS && *str2 != EOS){ |
if( *str1 != *str2 )break; |
str1++; |
str2++; |
} |
if(*str1 == *str2)return(YES); |
if(*str2==EOS) |
if( any(*str1," \t\n,+-];*") )return(YES); |
return(NO); |
} |
|
/* |
* alpha --- is character a legal letter |
*/ |
alpha(c) |
char c; |
{ |
if( c<= 'z' && c>= 'a' )return(YES); |
if( c<= 'Z' && c>= 'A' )return(YES); |
if( c== '_' )return(YES); |
if( c== '.' )return(YES); |
return(NO); |
} |
/* |
* alphan --- is character a legal letter or digit |
*/ |
alphan(c) |
char c; |
{ |
if( alpha(c) )return(YES); |
if( c<= '9' && c>= '0' )return(YES); |
if( c == '$' )return(YES); /* allow imbedded $ */ |
if( c == '@' )return(YES); /* allow imbedded @, added ver TER_2.0 |
added to permit redefinable variables */ |
return(NO); |
} |
|
/* |
* white --- is character whitespace? |
*/ |
white(c) |
char c; |
{ |
if( c == TAB || c == BLANK || c == '\n' )return(YES); |
return(NO); |
} |
|
/* |
* alloc --- allocate memory |
*/ |
char * |
alloc(nbytes) |
int nbytes; |
{ |
char *malloc(); |
|
return(malloc(nbytes)); |
} |
|
/* |
* FNameGet --- Find a file name <file> or "file" in the Operand string |
added ver TER_2.0 6/17/89 |
note: this routine will return a file name with white |
space if between delimeters. This is permitted in |
AmigaDOS. Other DOS may hiccup or just use name up to white space |
*/ |
|
int |
FNameGet(NameString) |
char *NameString; /* pointer to output string */ |
{ |
char *frompoint; /* pointers to input string, don't bash Operand */ |
char *topoint; /* pointer to output string, don't bash NameString */ |
|
frompoint=Operand; /* include file name is in parsed string Operand */ |
topoint=NameString; /* copy of pointer to increment in copying */ |
if (*frompoint != '<' && *frompoint != '"') return(0); /* bad syntax */ |
frompoint++; /* skip < or " */ |
|
while (*frompoint != '>' && *frompoint != '"') /* look for delimeter */ |
{ |
if (*frompoint == EOS) return(0); /* missing delimeter */ |
*topoint++ = *frompoint++; /* copy path & file name for DOS */ |
} |
|
*topoint=EOS; /* terminate file name */ |
#ifdef DEBUG2 |
printf("FNameGet: file name=%s\n",NameString); |
#endif |
return(1); /* proper syntax anyway */ |
} |
|
/* |
* --- strsave() find a place to save a string & return pointer to it |
added ver TER_2.0 6/18/89 function taken from |
Kernighan & Ritchie 78 |
*/ |
char *strsave(s) |
char *s; |
{ |
char *p; |
|
if ((p = alloc(strlen(s)+1)) != NULL) |
strcpy(p,s); |
return(p); |
} |
|
/* |
* pouterror() ---- print out standard error header |
added rel TER_2.0 6/18/89 |
*/ |
|
void pouterror() |
{ |
printf("%s, line no. ",Argv[Cfn]); /* current file name */ |
printf("%d: ",Line_num); /* current line number */ |
/* NOTE: THERE IS NO \n ! Calling procedure supplies suffixing |
error message and \n. viz. file pseudo.c procedure do_pseudo |
in case INCLUDE. Note also that error count is incremented. */ |
Err_count++; |
Page_lines++; /* increment lines per page */ |
} |
|
/* |
* New Page() --- form feed a new page, print heading & inc page number |
Moved here from do_pseudo (pseudo.c) in ver (TER) 2.02 |
19 Jun 89 so that can call from print_line() as well |
for p50 option. |
*/ |
|
void NewPage() |
{ |
Page_lines = 0; /* ver TER_2.08 so that OPT PAGE works */ |
printf ("\n\f\n"); |
printf ("%-10s",Argv[Cfn]); |
printf (" "); |
printf (" "); |
printf ("page %3d\n",Page_num++); |
} |
|
|
/* |
* LastChar() ----- return a pointer to the last character in a string |
Exception: will return garbage if NULL string |
*/ |
|
char *LastChar(strpt) |
char *strpt; /* pointer to string to be examined */ |
{ |
char *c; |
|
c=strpt; /* don't zap original */ |
while (*c != EOS) /* search for end */ |
c++; |
return(--c); /* back up one to last character */ |
} |