| 1 |
74 |
davidgb |
/*
|
| 2 |
|
|
* pseudo --- pseudo op processing
|
| 3 |
|
|
*/
|
| 4 |
|
|
|
| 5 |
|
|
#define RMB 0 /* Reserve Memory Bytes */
|
| 6 |
|
|
#define FCB 1 /* Form Constant Bytes */
|
| 7 |
|
|
#define FDB 2 /* Form Double Bytes (words) */
|
| 8 |
|
|
#define FCC 3 /* Form Constant Characters */
|
| 9 |
|
|
#define ORG 4 /* Origin */
|
| 10 |
|
|
#define EQU 5 /* Equate */
|
| 11 |
|
|
#define ZMB 6 /* Zero memory bytes */
|
| 12 |
|
|
#define FILL 7 /* block fill constant bytes */
|
| 13 |
|
|
#define OPT 8 /* assembler option */
|
| 14 |
|
|
#define NULL_OP 9 /* null pseudo op */
|
| 15 |
|
|
#define PAGE 10 /* new page */
|
| 16 |
|
|
#define INCLUDE 11 /* include <file> or "file" ver TER_2.0 */
|
| 17 |
|
|
#define END 12 /* include <file> terminator ver TER_2.0 */
|
| 18 |
|
|
#define IFD 13 /* if define <symbol> ver TER_2.0 */
|
| 19 |
|
|
#define IFND 14 /* if not define <symbol> ver TER_2.0 */
|
| 20 |
|
|
#define ELSE 15 /* else (for IF statements) ver TER_2.0 */
|
| 21 |
|
|
#define ENDIF 16 /* endif (for IF statements) ver TER_2.0 */
|
| 22 |
|
|
#define BSS 17 /* block storage segment (RAM) ver TER_2.09 */
|
| 23 |
|
|
#define CODE 18 /* code segment ver TER_2.09 25 Jul 89 */
|
| 24 |
|
|
#define DATA 19 /* data segment ver TER_2.09 25 Jul 89 */
|
| 25 |
|
|
#define AUTO 20 /* data segment ver TER_2.09 25 Jul 89 */
|
| 26 |
|
|
|
| 27 |
|
|
struct oper pseudo[] = {
|
| 28 |
|
|
"=", PSEUDO, EQU, 0, /* ver TER_2.09 25 Jul 89 */
|
| 29 |
|
|
"auto", PSEUDO, AUTO, 0, /* ver TER_2.09 25 Jul 89 */
|
| 30 |
|
|
"bss", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
|
| 31 |
|
|
"bsz", PSEUDO, ZMB, 0,
|
| 32 |
|
|
"code", PSEUDO, CODE, 0, /* ver TER_2.09 25 Jul 89 */
|
| 33 |
|
|
"data", PSEUDO, DATA, 0, /* ver TER_2.09 25 Jul 89 */
|
| 34 |
|
|
"else", PSEUDO, ELSE, 0, /* ver TER_2.0 6/17/89 */
|
| 35 |
|
|
"end", PSEUDO, END, 0, /* ver TER_2.0 6/17/89 */
|
| 36 |
|
|
"endif",PSEUDO, ENDIF, 0, /* ver TER_2.0 6/17/89 */
|
| 37 |
|
|
"equ", PSEUDO, EQU, 0,
|
| 38 |
|
|
"fcb", PSEUDO, FCB, 0,
|
| 39 |
|
|
"fcc", PSEUDO, FCC, 0,
|
| 40 |
|
|
"fdb", PSEUDO, FDB, 0,
|
| 41 |
|
|
"fill", PSEUDO, FILL, 0,
|
| 42 |
|
|
"ifd", PSEUDO, IFD, 0, /* ver TER_2.0 6/17/89 */
|
| 43 |
|
|
"ifnd", PSEUDO, IFND, 0, /* ver TER_2.0 6/17/89 */
|
| 44 |
|
|
"include", PSEUDO, INCLUDE, 0, /* ver TER_2.0 6/17/89 */
|
| 45 |
|
|
"nam", PSEUDO, NULL_OP,0,
|
| 46 |
|
|
"name", PSEUDO, NULL_OP,0,
|
| 47 |
|
|
"opt", PSEUDO, OPT, 0,
|
| 48 |
|
|
"org", PSEUDO, ORG, 0,
|
| 49 |
|
|
"pag", PSEUDO, PAGE, 0,
|
| 50 |
|
|
"page", PSEUDO, PAGE, 0,
|
| 51 |
|
|
"ram", PSEUDO, BSS, 0, /* ver TER_2.09 25 Jul 89 */
|
| 52 |
|
|
"rmb", PSEUDO, RMB, 0,
|
| 53 |
|
|
"spc", PSEUDO, NULL_OP,0,
|
| 54 |
|
|
"ttl", PSEUDO, NULL_OP,0,
|
| 55 |
|
|
"zmb", PSEUDO, ZMB, 0
|
| 56 |
|
|
};
|
| 57 |
|
|
|
| 58 |
|
|
/*
|
| 59 |
|
|
* do_pseudo --- do pseudo op processing
|
| 60 |
|
|
*/
|
| 61 |
|
|
do_pseudo(op)
|
| 62 |
|
|
int op; /* which op */
|
| 63 |
|
|
{
|
| 64 |
|
|
char fccdelim, *strsave();
|
| 65 |
|
|
int fill;
|
| 66 |
|
|
int c; /*test variable ver TER_2.0 6/18/89 */
|
| 67 |
|
|
char *skip_white(), *savept; /* savept is pointer to string save */
|
| 68 |
|
|
FILE *FdTemp, *fopen(); /* ver TER_2.0 6/17/89 */
|
| 69 |
|
|
void pouterror(), NewPage(), IfMachine(); /* rel TER_2.0 6/18/89 */
|
| 70 |
|
|
void PC_Exchange(); /* ver TER_2.09 25 Jul 89 */
|
| 71 |
|
|
|
| 72 |
|
|
if( op != EQU && *Label )
|
| 73 |
|
|
install(Label,Pc);
|
| 74 |
|
|
|
| 75 |
|
|
P_force++;
|
| 76 |
|
|
|
| 77 |
|
|
#ifdef DEBUG3
|
| 78 |
|
|
printf("%s, line no. ",Argv[Cfn]); /* current file name */
|
| 79 |
|
|
printf("%d: ",Line_num); /* current line number */
|
| 80 |
|
|
printf(" Pseudo Op=%u\n",op);
|
| 81 |
|
|
#endif
|
| 82 |
|
|
|
| 83 |
|
|
switch(op){
|
| 84 |
|
|
case RMB: /* reserve memory bytes */
|
| 85 |
|
|
if( eval() ){
|
| 86 |
|
|
Pc += Result;
|
| 87 |
|
|
f_record(); /* flush out bytes */
|
| 88 |
|
|
}
|
| 89 |
|
|
else
|
| 90 |
|
|
error("Undefined Operand during Pass One");
|
| 91 |
|
|
break;
|
| 92 |
|
|
case ZMB: /* zero memory bytes */
|
| 93 |
|
|
if( eval() )
|
| 94 |
|
|
while( Result-- )
|
| 95 |
|
|
emit(0);
|
| 96 |
|
|
else
|
| 97 |
|
|
error("Undefined Operand during Pass One");
|
| 98 |
|
|
break;
|
| 99 |
|
|
case FILL: /* fill memory with constant */
|
| 100 |
|
|
eval();
|
| 101 |
|
|
fill = Result;
|
| 102 |
|
|
if( *Optr++ != ',' )
|
| 103 |
|
|
error("Bad fill");
|
| 104 |
|
|
else{
|
| 105 |
|
|
Optr = skip_white(Optr);
|
| 106 |
|
|
eval();
|
| 107 |
|
|
while( Result-- )
|
| 108 |
|
|
emit(fill);
|
| 109 |
|
|
}
|
| 110 |
|
|
break;
|
| 111 |
|
|
case FCB: /* form constant byte(s) */
|
| 112 |
|
|
do{
|
| 113 |
|
|
Optr = skip_white(Optr);
|
| 114 |
|
|
eval();
|
| 115 |
|
|
if( Result > 0xFF ){
|
| 116 |
|
|
if(!Force_byte)
|
| 117 |
|
|
warn("Value truncated");
|
| 118 |
|
|
Result = lobyte(Result);
|
| 119 |
|
|
}
|
| 120 |
|
|
emit(Result);
|
| 121 |
|
|
}while( *Optr++ == ',' );
|
| 122 |
|
|
break;
|
| 123 |
|
|
case FDB: /* form double byte(s) */
|
| 124 |
|
|
do{
|
| 125 |
|
|
Optr = skip_white(Optr);
|
| 126 |
|
|
eval();
|
| 127 |
|
|
eword(Result);
|
| 128 |
|
|
}while( *Optr++ == ',' );
|
| 129 |
|
|
break;
|
| 130 |
|
|
case FCC: /* form constant characters */
|
| 131 |
|
|
if(*Operand==EOS)
|
| 132 |
|
|
break;
|
| 133 |
|
|
fccdelim = *Optr++;
|
| 134 |
|
|
while( *Optr != EOS && *Optr != fccdelim)
|
| 135 |
|
|
emit(*Optr++);
|
| 136 |
|
|
if(*Optr == fccdelim)
|
| 137 |
|
|
Optr++;
|
| 138 |
|
|
else
|
| 139 |
|
|
error("Missing Delimiter");
|
| 140 |
|
|
break;
|
| 141 |
|
|
case ORG: /* origin */
|
| 142 |
|
|
if( eval() ){
|
| 143 |
|
|
Old_pc = Pc = Result;
|
| 144 |
|
|
f_record(); /* flush out any bytes */
|
| 145 |
|
|
}
|
| 146 |
|
|
else
|
| 147 |
|
|
error("Undefined Operand during Pass One");
|
| 148 |
|
|
break;
|
| 149 |
|
|
case EQU: /* equate */
|
| 150 |
|
|
if(*Label==EOS){
|
| 151 |
|
|
error("EQU requires label");
|
| 152 |
|
|
break;
|
| 153 |
|
|
}
|
| 154 |
|
|
if( eval() ){
|
| 155 |
|
|
install(Label,Result);
|
| 156 |
|
|
Old_pc = Result; /* override normal */
|
| 157 |
|
|
}
|
| 158 |
|
|
else
|
| 159 |
|
|
error("Undefined Operand during Pass One");
|
| 160 |
|
|
break;
|
| 161 |
|
|
case OPT: /* assembler option */
|
| 162 |
|
|
P_force=0;
|
| 163 |
|
|
if( head(Operand,"l") )
|
| 164 |
|
|
Lflag=1;
|
| 165 |
|
|
else if (head(Operand,"nol"))
|
| 166 |
|
|
Lflag=0;
|
| 167 |
|
|
else if (head(Operand,"c")){
|
| 168 |
|
|
Cflag=1;
|
| 169 |
|
|
Ctotal=0;
|
| 170 |
|
|
}
|
| 171 |
|
|
else if (head(Operand,"noc"))
|
| 172 |
|
|
Cflag=0;
|
| 173 |
|
|
else if (head(Operand,"contc")){
|
| 174 |
|
|
Cflag=1;
|
| 175 |
|
|
}
|
| 176 |
|
|
else if (head(Operand,"s"))
|
| 177 |
|
|
Sflag = 1;
|
| 178 |
|
|
else if (head(Operand,"cre"))
|
| 179 |
|
|
CREflag = 1;
|
| 180 |
|
|
else if (head(Operand,"p50")){ /* turn on 50 lines/page flag */
|
| 181 |
|
|
Pflag50 = 1;
|
| 182 |
|
|
Pflag75 = 0;
|
| 183 |
|
|
} /* separately. ver TER_2.0 6/17/89 */
|
| 184 |
|
|
else if (head(Operand,"p75")){ /* turn on 75 lines/page flag */
|
| 185 |
|
|
Pflag50 = 0;
|
| 186 |
|
|
Pflag75 = 1;
|
| 187 |
|
|
} /* separately. ver TER_2.0 6/17/89 */
|
| 188 |
|
|
else if (head(Operand,"crlf")) /* add <CR> <LF> to */
|
| 189 |
|
|
CRflag = 1; /* S record ver TER_2.08 */
|
| 190 |
|
|
else if (head(Operand,"nnf")) /* no extra line no. */
|
| 191 |
|
|
nfFlag = 0; /* w include files ver TER_2.08 */
|
| 192 |
|
|
else
|
| 193 |
|
|
error("Unrecognized OPT");
|
| 194 |
|
|
break;
|
| 195 |
|
|
case PAGE: /* go to a new page */
|
| 196 |
|
|
P_force=0;
|
| 197 |
|
|
N_page = 1;
|
| 198 |
|
|
if (Pass == 2 )
|
| 199 |
|
|
if (Lflag) NewPage();
|
| 200 |
|
|
break;
|
| 201 |
|
|
case NULL_OP: /* ignored psuedo ops */
|
| 202 |
|
|
P_force=0;
|
| 203 |
|
|
break;
|
| 204 |
|
|
case INCLUDE: /* case INCLUDE added ver TER_2.0 6/17/89 */
|
| 205 |
|
|
P_force=0; /* no PC in printed output */
|
| 206 |
|
|
if ((c=FNameGet(InclFName))==0)
|
| 207 |
|
|
error("Improper INCLUDE statement");
|
| 208 |
|
|
else
|
| 209 |
|
|
{
|
| 210 |
|
|
if (FdCount > MAXINCFILES)
|
| 211 |
|
|
error("too many INCLUDE files");
|
| 212 |
|
|
else
|
| 213 |
|
|
{
|
| 214 |
|
|
if ((FdTemp = fopen(InclFName,"r"))==0)
|
| 215 |
|
|
{
|
| 216 |
|
|
printf("%s, line no. ",Argv[Cfn]);
|
| 217 |
|
|
/* current file name */
|
| 218 |
|
|
printf("%d: ",Line_num); /* current line number */
|
| 219 |
|
|
Page_lines++; /* increment lines per page */
|
| 220 |
|
|
printf("warning:can't open INCLUDE file %s\n",InclFName);
|
| 221 |
|
|
}
|
| 222 |
|
|
else
|
| 223 |
|
|
{
|
| 224 |
|
|
if ((savept=strsave(InclFName))==0)
|
| 225 |
|
|
error("out of memory for INCLUDE file name");
|
| 226 |
|
|
else
|
| 227 |
|
|
{
|
| 228 |
|
|
InclFiles[FdCount].fp=Fd; /* save current fp */
|
| 229 |
|
|
if (nfFlag)
|
| 230 |
|
|
{
|
| 231 |
|
|
InclFiles[FdCount].line_num=Line_num;
|
| 232 |
|
|
/* save current line count */
|
| 233 |
|
|
Line_num=0; /* reset for new file */
|
| 234 |
|
|
}
|
| 235 |
|
|
InclFiles[FdCount].name=Argv[Cfn];
|
| 236 |
|
|
/* save pointer to current name */
|
| 237 |
|
|
Argv[Cfn]=savept;
|
| 238 |
|
|
/* now replace pointer to current name with
|
| 239 |
|
|
pointer to name of Include file */
|
| 240 |
|
|
Fd=FdTemp; /* now replace current file with
|
| 241 |
|
|
INCLUDE fp */
|
| 242 |
|
|
FdCount++; /* and increment "stack" */
|
| 243 |
|
|
#ifdef DEBUG2
|
| 244 |
|
|
printf("pseudo INCLUDE: FdCount=%d\n",FdCount);
|
| 245 |
|
|
printf(" new input file pointer=%d\n",Fd);
|
| 246 |
|
|
printf(" new file name=%s\n",Argv[Cfn]);
|
| 247 |
|
|
#endif
|
| 248 |
|
|
}
|
| 249 |
|
|
}
|
| 250 |
|
|
}
|
| 251 |
|
|
}
|
| 252 |
|
|
break;
|
| 253 |
|
|
case END:
|
| 254 |
|
|
P_force=0;
|
| 255 |
|
|
if (FdCount>0) /* skip END statements in files
|
| 256 |
|
|
received from CLI arguments */
|
| 257 |
|
|
{
|
| 258 |
|
|
fclose(Fd); /* close file from this level nest */
|
| 259 |
|
|
FdCount--; /* "pop stack" */
|
| 260 |
|
|
Fd=InclFiles[FdCount].fp; /* restore fp from
|
| 261 |
|
|
nested stack */
|
| 262 |
|
|
if(nfFlag) Line_num=InclFiles[FdCount].line_num;
|
| 263 |
|
|
Argv[Cfn]=InclFiles[FdCount].name;
|
| 264 |
|
|
/* restore file name pointer */
|
| 265 |
|
|
#ifdef DEBUG2
|
| 266 |
|
|
printf("pseudo END: FdCount=%d\n",FdCount);
|
| 267 |
|
|
printf(" new input file pointer=%d\n",Fd);
|
| 268 |
|
|
printf(" new file name=%s\n",Argv[Cfn]);
|
| 269 |
|
|
#endif
|
| 270 |
|
|
}
|
| 271 |
|
|
break;
|
| 272 |
|
|
case IFD:
|
| 273 |
|
|
#ifdef DEBUG3
|
| 274 |
|
|
printf("case IFD: in pseudo\n");
|
| 275 |
|
|
#endif
|
| 276 |
|
|
P_force=0;
|
| 277 |
|
|
c=eval_ifd();
|
| 278 |
|
|
IfMachine(c);
|
| 279 |
|
|
break;
|
| 280 |
|
|
case IFND:
|
| 281 |
|
|
P_force=0;
|
| 282 |
|
|
c=eval_ifnd();
|
| 283 |
|
|
IfMachine(c);
|
| 284 |
|
|
break;
|
| 285 |
|
|
case ELSE:
|
| 286 |
|
|
P_force=0;
|
| 287 |
|
|
IfMachine(IF_ELSE);
|
| 288 |
|
|
break;
|
| 289 |
|
|
case ENDIF:
|
| 290 |
|
|
P_force=0;
|
| 291 |
|
|
IfMachine(IF_ENDIF);
|
| 292 |
|
|
break;
|
| 293 |
|
|
case CODE: /* CODE,DATA,BSS,AUTO ver TER_2.09 */
|
| 294 |
|
|
PC_Exchange(0);
|
| 295 |
|
|
break;
|
| 296 |
|
|
case DATA:
|
| 297 |
|
|
PC_Exchange(1);
|
| 298 |
|
|
break;
|
| 299 |
|
|
case BSS:
|
| 300 |
|
|
PC_Exchange(2);
|
| 301 |
|
|
break;
|
| 302 |
|
|
case AUTO:
|
| 303 |
|
|
PC_Exchange(3);
|
| 304 |
|
|
break;
|
| 305 |
|
|
default:
|
| 306 |
|
|
fatal("Pseudo error");
|
| 307 |
|
|
break;
|
| 308 |
|
|
}
|
| 309 |
|
|
}
|
| 310 |
|
|
|
| 311 |
|
|
|
| 312 |
|
|
/*
|
| 313 |
|
|
* PC_Exchange --- Save current PC and recover requested one
|
| 314 |
|
|
added ver TER_2.09
|
| 315 |
|
|
*/
|
| 316 |
|
|
void PC_Exchange(PC_ptr_new)
|
| 317 |
|
|
int PC_ptr_new; /* request 0=CODE,1=DATA,2=BSS */
|
| 318 |
|
|
{
|
| 319 |
|
|
P_force = 0; /* no PC in output cuz wrong first time (?) */
|
| 320 |
|
|
PC_Save[PC_ptr] = Pc; /* save current PC */
|
| 321 |
|
|
PC_ptr = PC_ptr_new; /* remember which one we're using */
|
| 322 |
|
|
Old_pc = Pc = PC_Save[PC_ptr]; /* recover the one requested */
|
| 323 |
|
|
f_record(); /* flush out any bytes, this is really an ORG */
|
| 324 |
|
|
}
|