/*
|
/*
|
* pseudo --- pseudo op processing
|
* pseudo --- pseudo op processing
|
*/
|
*/
|
|
|
#define RMB 0 /* Reserve Memory Bytes */
|
#define RMB 0 /* Reserve Memory Bytes */
|
#define FCB 1 /* Form Constant Bytes */
|
#define FCB 1 /* Form Constant Bytes */
|
#define FDB 2 /* Form Double Bytes (words) */
|
#define FDB 2 /* Form Double Bytes (words) */
|
#define FCC 3 /* Form Constant Characters */
|
#define FCC 3 /* Form Constant Characters */
|
#define ORG 4 /* Origin */
|
#define ORG 4 /* Origin */
|
#define EQU 5 /* Equate */
|
#define EQU 5 /* Equate */
|
#define ZMB 6 /* Zero memory bytes */
|
#define ZMB 6 /* Zero memory bytes */
|
#define FILL 7 /* block fill constant bytes */
|
#define FILL 7 /* block fill constant bytes */
|
#define OPT 8 /* assembler option */
|
#define OPT 8 /* assembler option */
|
#define NULL_OP 9 /* null pseudo op */
|
#define NULL_OP 9 /* null pseudo op */
|
#define PAGE 10 /* new page */
|
#define PAGE 10 /* new page */
|
#define INCLUDE 11 /* include <file> or "file" ver TER_2.0 */
|
#define INCLUDE 11 /* include <file> or "file" ver TER_2.0 */
|
#define END 12 /* include <file> terminator 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 IFD 13 /* if define <symbol> ver TER_2.0 */
|
#define IFND 14 /* if not 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 ELSE 15 /* else (for IF statements) ver TER_2.0 */
|
#define ENDIF 16 /* endif (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 BSS 17 /* block storage segment (RAM) ver TER_2.09 */
|
#define CODE 18 /* code segment ver TER_2.09 25 Jul 89 */
|
#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 DATA 19 /* data segment ver TER_2.09 25 Jul 89 */
|
#define AUTO 20 /* data segment ver TER_2.09 25 Jul 89 */
|
#define AUTO 20 /* data segment ver TER_2.09 25 Jul 89 */
|
|
|
struct oper pseudo[] = {
|
struct oper pseudo[] = {
|
"=", PSEUDO, EQU, 0, /* ver TER_2.09 25 Jul 89 */
|
"=", PSEUDO, EQU, 0, /* ver TER_2.09 25 Jul 89 */
|
"auto", PSEUDO, AUTO, 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 */
|
"bss", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
|
"bsz", PSEUDO, ZMB, 0,
|
"bsz", PSEUDO, ZMB, 0,
|
"code", PSEUDO, CODE, 0, /* ver TER_2.09 25 Jul 89 */
|
"code", PSEUDO, CODE, 0, /* ver TER_2.09 25 Jul 89 */
|
"data", PSEUDO, DATA, 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 */
|
"else", PSEUDO, ELSE, 0, /* ver TER_2.0 6/17/89 */
|
"end", PSEUDO, END, 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 */
|
"endif",PSEUDO, ENDIF, 0, /* ver TER_2.0 6/17/89 */
|
"equ", PSEUDO, EQU, 0,
|
"equ", PSEUDO, EQU, 0,
|
"fcb", PSEUDO, FCB, 0,
|
"fcb", PSEUDO, FCB, 0,
|
"fcc", PSEUDO, FCC, 0,
|
"fcc", PSEUDO, FCC, 0,
|
"fdb", PSEUDO, FDB, 0,
|
"fdb", PSEUDO, FDB, 0,
|
"fill", PSEUDO, FILL, 0,
|
"fill", PSEUDO, FILL, 0,
|
"ifd", PSEUDO, IFD, 0, /* ver TER_2.0 6/17/89 */
|
"ifd", PSEUDO, IFD, 0, /* ver TER_2.0 6/17/89 */
|
"ifnd", PSEUDO, IFND, 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 */
|
"include", PSEUDO, INCLUDE, 0, /* ver TER_2.0 6/17/89 */
|
"nam", PSEUDO, NULL_OP,0,
|
"nam", PSEUDO, NULL_OP,0,
|
"name", PSEUDO, NULL_OP,0,
|
"name", PSEUDO, NULL_OP,0,
|
"opt", PSEUDO, OPT, 0,
|
"opt", PSEUDO, OPT, 0,
|
"org", PSEUDO, ORG, 0,
|
"org", PSEUDO, ORG, 0,
|
"pag", PSEUDO, PAGE, 0,
|
"pag", PSEUDO, PAGE, 0,
|
"page", PSEUDO, PAGE, 0,
|
"page", PSEUDO, PAGE, 0,
|
"ram", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
|
"ram", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
|
"rmb", PSEUDO, RMB, 0,
|
"rmb", PSEUDO, RMB, 0,
|
"spc", PSEUDO, NULL_OP,0,
|
"spc", PSEUDO, NULL_OP,0,
|
"ttl", PSEUDO, NULL_OP,0,
|
"ttl", PSEUDO, NULL_OP,0,
|
"zmb", PSEUDO, ZMB, 0
|
"zmb", PSEUDO, ZMB, 0
|
};
|
};
|
|
|
/*
|
/*
|
* do_pseudo --- do pseudo op processing
|
* do_pseudo --- do pseudo op processing
|
*/
|
*/
|
do_pseudo(op)
|
do_pseudo(op)
|
int op; /* which op */
|
int op; /* which op */
|
{
|
{
|
char fccdelim, *strsave();
|
char fccdelim, *strsave();
|
int fill;
|
int fill;
|
int c; /*test variable ver TER_2.0 6/18/89 */
|
int c; /*test variable ver TER_2.0 6/18/89 */
|
char *skip_white(), *savept; /* savept is pointer to string save */
|
char *skip_white(), *savept; /* savept is pointer to string save */
|
FILE *FdTemp, *fopen(); /* ver TER_2.0 6/17/89 */
|
FILE *FdTemp, *fopen(); /* ver TER_2.0 6/17/89 */
|
void pouterror(), NewPage(), IfMachine(); /* rel TER_2.0 6/18/89 */
|
void IfMachine(); /* rel TER_2.0 6/18/89 */
|
void PC_Exchange(); /* ver TER_2.09 25 Jul 89 */
|
void PC_Exchange(); /* ver TER_2.09 25 Jul 89 */
|
|
|
if( op != EQU && *Label )
|
if( op != EQU && *Label )
|
install(Label,Pc);
|
install(Label,Pc);
|
|
|
P_force++;
|
P_force++;
|
|
|
#ifdef DEBUG3
|
#ifdef DEBUG3
|
printf("%s, line no. ",Argv[Cfn]); /* current file name */
|
printf("%s, line no. ",Argv[Cfn]); /* current file name */
|
printf("%d: ",Line_num); /* current line number */
|
printf("%d: ",Line_num); /* current line number */
|
printf(" Pseudo Op=%u\n",op);
|
printf(" Pseudo Op=%u\n",op);
|
#endif
|
#endif
|
|
|
switch(op){
|
switch(op){
|
case RMB: /* reserve memory bytes */
|
case RMB: /* reserve memory bytes */
|
if( eval() ){
|
if( eval() ){
|
Pc += Result;
|
Pc += Result;
|
f_record(); /* flush out bytes */
|
f_record(); /* flush out bytes */
|
}
|
}
|
else
|
else
|
error("Undefined Operand during Pass One");
|
error("Undefined Operand during Pass One");
|
break;
|
break;
|
case ZMB: /* zero memory bytes */
|
case ZMB: /* zero memory bytes */
|
if( eval() )
|
if( eval() )
|
while( Result-- )
|
while( Result-- )
|
emit(0);
|
emit(0);
|
else
|
else
|
error("Undefined Operand during Pass One");
|
error("Undefined Operand during Pass One");
|
break;
|
break;
|
case FILL: /* fill memory with constant */
|
case FILL: /* fill memory with constant */
|
eval();
|
eval();
|
fill = Result;
|
fill = Result;
|
if( *Optr++ != ',' )
|
if( *Optr++ != ',' )
|
error("Bad fill");
|
error("Bad fill");
|
else{
|
else{
|
Optr = skip_white(Optr);
|
Optr = skip_white(Optr);
|
eval();
|
eval();
|
while( Result-- )
|
while( Result-- )
|
emit(fill);
|
emit(fill);
|
}
|
}
|
break;
|
break;
|
case FCB: /* form constant byte(s) */
|
case FCB: /* form constant byte(s) */
|
do{
|
do{
|
Optr = skip_white(Optr);
|
Optr = skip_white(Optr);
|
eval();
|
eval();
|
if( Result > 0xFF ){
|
if( Result > 0xFF ){
|
if(!Force_byte)
|
if(!Force_byte)
|
warn("Value truncated");
|
warn("Value truncated");
|
Result = lobyte(Result);
|
Result = lobyte(Result);
|
}
|
}
|
emit(Result);
|
emit(Result);
|
}while( *Optr++ == ',' );
|
}while( *Optr++ == ',' );
|
break;
|
break;
|
case FDB: /* form double byte(s) */
|
case FDB: /* form double byte(s) */
|
do{
|
do{
|
Optr = skip_white(Optr);
|
Optr = skip_white(Optr);
|
eval();
|
eval();
|
eword(Result);
|
eword(Result);
|
}while( *Optr++ == ',' );
|
}while( *Optr++ == ',' );
|
break;
|
break;
|
case FCC: /* form constant characters */
|
case FCC: /* form constant characters */
|
if(*Operand==EOS)
|
if(*Operand==EOS)
|
break;
|
break;
|
fccdelim = *Optr++;
|
fccdelim = *Optr++;
|
while( *Optr != EOS && *Optr != fccdelim)
|
while( *Optr != EOS && *Optr != fccdelim)
|
emit(*Optr++);
|
emit(*Optr++);
|
if(*Optr == fccdelim)
|
if(*Optr == fccdelim)
|
Optr++;
|
Optr++;
|
else
|
else
|
error("Missing Delimiter");
|
error("Missing Delimiter");
|
break;
|
break;
|
case ORG: /* origin */
|
case ORG: /* origin */
|
if( eval() ){
|
if( eval() ){
|
Old_pc = Pc = Result;
|
Old_pc = Pc = Result;
|
f_record(); /* flush out any bytes */
|
f_record(); /* flush out any bytes */
|
}
|
}
|
else
|
else
|
error("Undefined Operand during Pass One");
|
error("Undefined Operand during Pass One");
|
break;
|
break;
|
case EQU: /* equate */
|
case EQU: /* equate */
|
if(*Label==EOS){
|
if(*Label==EOS){
|
error("EQU requires label");
|
error("EQU requires label");
|
break;
|
break;
|
}
|
}
|
if( eval() ){
|
if( eval() ){
|
install(Label,Result);
|
install(Label,Result);
|
Old_pc = Result; /* override normal */
|
Old_pc = Result; /* override normal */
|
}
|
}
|
else
|
else
|
error("Undefined Operand during Pass One");
|
error("Undefined Operand during Pass One");
|
break;
|
break;
|
case OPT: /* assembler option */
|
case OPT: /* assembler option */
|
P_force=0;
|
P_force=0;
|
if( head(Operand,"l") )
|
if( head(Operand,"l") )
|
Lflag=1;
|
Lflag=1;
|
else if (head(Operand,"nol"))
|
else if (head(Operand,"nol"))
|
Lflag=0;
|
Lflag=0;
|
else if (head(Operand,"c")){
|
else if (head(Operand,"c")){
|
Cflag=1;
|
Cflag=1;
|
Ctotal=0;
|
Ctotal=0;
|
}
|
}
|
else if (head(Operand,"noc"))
|
else if (head(Operand,"noc"))
|
Cflag=0;
|
Cflag=0;
|
else if (head(Operand,"contc")){
|
else if (head(Operand,"contc")){
|
Cflag=1;
|
Cflag=1;
|
}
|
}
|
else if (head(Operand,"s"))
|
else if (head(Operand,"s"))
|
Sflag = 1;
|
Sflag = 1;
|
else if (head(Operand,"cre"))
|
else if (head(Operand,"cre"))
|
CREflag = 1;
|
CREflag = 1;
|
else if (head(Operand,"p50")){ /* turn on 50 lines/page flag */
|
else if (head(Operand,"p50")){ /* turn on 50 lines/page flag */
|
Pflag50 = 1;
|
Pflag50 = 1;
|
Pflag75 = 0;
|
Pflag75 = 0;
|
} /* separately. ver TER_2.0 6/17/89 */
|
} /* separately. ver TER_2.0 6/17/89 */
|
else if (head(Operand,"p75")){ /* turn on 75 lines/page flag */
|
else if (head(Operand,"p75")){ /* turn on 75 lines/page flag */
|
Pflag50 = 0;
|
Pflag50 = 0;
|
Pflag75 = 1;
|
Pflag75 = 1;
|
} /* separately. ver TER_2.0 6/17/89 */
|
} /* separately. ver TER_2.0 6/17/89 */
|
else if (head(Operand,"crlf")) /* add <CR> <LF> to */
|
else if (head(Operand,"crlf")) /* add <CR> <LF> to */
|
CRflag = 1; /* S record ver TER_2.08 */
|
CRflag = 1; /* S record ver TER_2.08 */
|
else if (head(Operand,"nnf")) /* no extra line no. */
|
else if (head(Operand,"nnf")) /* no extra line no. */
|
nfFlag = 0; /* w include files ver TER_2.08 */
|
nfFlag = 0; /* w include files ver TER_2.08 */
|
else
|
else
|
error("Unrecognized OPT");
|
error("Unrecognized OPT");
|
break;
|
break;
|
case PAGE: /* go to a new page */
|
case PAGE: /* go to a new page */
|
P_force=0;
|
P_force=0;
|
N_page = 1;
|
N_page = 1;
|
if (Pass == 2 )
|
if (Pass == 2 )
|
if (Lflag) NewPage();
|
if (Lflag) NewPage();
|
break;
|
break;
|
case NULL_OP: /* ignored psuedo ops */
|
case NULL_OP: /* ignored psuedo ops */
|
P_force=0;
|
P_force=0;
|
break;
|
break;
|
case INCLUDE: /* case INCLUDE added ver TER_2.0 6/17/89 */
|
case INCLUDE: /* case INCLUDE added ver TER_2.0 6/17/89 */
|
P_force=0; /* no PC in printed output */
|
P_force=0; /* no PC in printed output */
|
if ((c=FNameGet(InclFName))==0)
|
if ((c=FNameGet(InclFName))==0)
|
error("Improper INCLUDE statement");
|
error("Improper INCLUDE statement");
|
else
|
else
|
{
|
{
|
if (FdCount > MAXINCFILES)
|
if (FdCount > MAXINCFILES)
|
error("too many INCLUDE files");
|
error("too many INCLUDE files");
|
else
|
else
|
{
|
{
|
if ((FdTemp = fopen(InclFName,"r"))==0)
|
if ((FdTemp = fopen(InclFName,"r"))==0)
|
{
|
{
|
printf("%s, line no. ",Argv[Cfn]);
|
printf("%s, line no. ",Argv[Cfn]);
|
/* current file name */
|
/* current file name */
|
printf("%d: ",Line_num); /* current line number */
|
printf("%d: ",Line_num); /* current line number */
|
Page_lines++; /* increment lines per page */
|
Page_lines++; /* increment lines per page */
|
printf("warning:can't open INCLUDE file %s\n",InclFName);
|
printf("warning:can't open INCLUDE file %s\n",InclFName);
|
}
|
}
|
else
|
else
|
{
|
{
|
if ((savept=strsave(InclFName))==0)
|
if ((savept=strsave(InclFName))==0)
|
error("out of memory for INCLUDE file name");
|
error("out of memory for INCLUDE file name");
|
else
|
else
|
{
|
{
|
InclFiles[FdCount].fp=Fd; /* save current fp */
|
InclFiles[FdCount].fp=Fd; /* save current fp */
|
if (nfFlag)
|
if (nfFlag)
|
{
|
{
|
InclFiles[FdCount].line_num=Line_num;
|
InclFiles[FdCount].line_num=Line_num;
|
/* save current line count */
|
/* save current line count */
|
Line_num=0; /* reset for new file */
|
Line_num=0; /* reset for new file */
|
}
|
}
|
InclFiles[FdCount].name=Argv[Cfn];
|
InclFiles[FdCount].name=Argv[Cfn];
|
/* save pointer to current name */
|
/* save pointer to current name */
|
Argv[Cfn]=savept;
|
Argv[Cfn]=savept;
|
/* now replace pointer to current name with
|
/* now replace pointer to current name with
|
pointer to name of Include file */
|
pointer to name of Include file */
|
Fd=FdTemp; /* now replace current file with
|
Fd=FdTemp; /* now replace current file with
|
INCLUDE fp */
|
INCLUDE fp */
|
FdCount++; /* and increment "stack" */
|
FdCount++; /* and increment "stack" */
|
#ifdef DEBUG2
|
#ifdef DEBUG2
|
printf("pseudo INCLUDE: FdCount=%d\n",FdCount);
|
printf("pseudo INCLUDE: FdCount=%d\n",FdCount);
|
printf(" new input file pointer=%d\n",Fd);
|
printf(" new input file pointer=%d\n",Fd);
|
printf(" new file name=%s\n",Argv[Cfn]);
|
printf(" new file name=%s\n",Argv[Cfn]);
|
#endif
|
#endif
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
break;
|
break;
|
case END:
|
case END:
|
P_force=0;
|
P_force=0;
|
if (FdCount>0) /* skip END statements in files
|
if (FdCount>0) /* skip END statements in files
|
received from CLI arguments */
|
received from CLI arguments */
|
{
|
{
|
fclose(Fd); /* close file from this level nest */
|
fclose(Fd); /* close file from this level nest */
|
FdCount--; /* "pop stack" */
|
FdCount--; /* "pop stack" */
|
Fd=InclFiles[FdCount].fp; /* restore fp from
|
Fd=InclFiles[FdCount].fp; /* restore fp from
|
nested stack */
|
nested stack */
|
if(nfFlag) Line_num=InclFiles[FdCount].line_num;
|
if(nfFlag) Line_num=InclFiles[FdCount].line_num;
|
Argv[Cfn]=InclFiles[FdCount].name;
|
Argv[Cfn]=InclFiles[FdCount].name;
|
/* restore file name pointer */
|
/* restore file name pointer */
|
#ifdef DEBUG2
|
#ifdef DEBUG2
|
printf("pseudo END: FdCount=%d\n",FdCount);
|
printf("pseudo END: FdCount=%d\n",FdCount);
|
printf(" new input file pointer=%d\n",Fd);
|
printf(" new input file pointer=%d\n",Fd);
|
printf(" new file name=%s\n",Argv[Cfn]);
|
printf(" new file name=%s\n",Argv[Cfn]);
|
#endif
|
#endif
|
}
|
}
|
break;
|
break;
|
case IFD:
|
case IFD:
|
#ifdef DEBUG3
|
#ifdef DEBUG3
|
printf("case IFD: in pseudo\n");
|
printf("case IFD: in pseudo\n");
|
#endif
|
#endif
|
P_force=0;
|
P_force=0;
|
c=eval_ifd();
|
c=eval_ifd();
|
IfMachine(c);
|
IfMachine(c);
|
break;
|
break;
|
case IFND:
|
case IFND:
|
P_force=0;
|
P_force=0;
|
c=eval_ifnd();
|
c=eval_ifnd();
|
IfMachine(c);
|
IfMachine(c);
|
break;
|
break;
|
case ELSE:
|
case ELSE:
|
P_force=0;
|
P_force=0;
|
IfMachine(IF_ELSE);
|
IfMachine(IF_ELSE);
|
break;
|
break;
|
case ENDIF:
|
case ENDIF:
|
P_force=0;
|
P_force=0;
|
IfMachine(IF_ENDIF);
|
IfMachine(IF_ENDIF);
|
break;
|
break;
|
case CODE: /* CODE,DATA,BSS,AUTO ver TER_2.09 */
|
case CODE: /* CODE,DATA,BSS,AUTO ver TER_2.09 */
|
PC_Exchange(0);
|
PC_Exchange(0);
|
break;
|
break;
|
case DATA:
|
case DATA:
|
PC_Exchange(1);
|
PC_Exchange(1);
|
break;
|
break;
|
case BSS:
|
case BSS:
|
PC_Exchange(2);
|
PC_Exchange(2);
|
break;
|
break;
|
case AUTO:
|
case AUTO:
|
PC_Exchange(3);
|
PC_Exchange(3);
|
break;
|
break;
|
default:
|
default:
|
fatal("Pseudo error");
|
fatal("Pseudo error");
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* PC_Exchange --- Save current PC and recover requested one
|
* PC_Exchange --- Save current PC and recover requested one
|
added ver TER_2.09
|
added ver TER_2.09
|
*/
|
*/
|
void PC_Exchange(PC_ptr_new)
|
void PC_Exchange(PC_ptr_new)
|
int PC_ptr_new; /* request 0=CODE,1=DATA,2=BSS */
|
int PC_ptr_new; /* request 0=CODE,1=DATA,2=BSS */
|
{
|
{
|
P_force = 0; /* no PC in output cuz wrong first time (?) */
|
P_force = 0; /* no PC in output cuz wrong first time (?) */
|
PC_Save[PC_ptr] = Pc; /* save current PC */
|
PC_Save[PC_ptr] = Pc; /* save current PC */
|
PC_ptr = PC_ptr_new; /* remember which one we're using */
|
PC_ptr = PC_ptr_new; /* remember which one we're using */
|
Old_pc = Pc = PC_Save[PC_ptr]; /* recover the one requested */
|
Old_pc = Pc = PC_Save[PC_ptr]; /* recover the one requested */
|
f_record(); /* flush out any bytes, this is really an ORG */
|
f_record(); /* flush out any bytes, this is really an ORG */
|
}
|
}
|
|
|