comparison a09.c @ 0:9a224bd9b45f

os9 emulation
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 02 Jul 2018 02:12:31 +0900
parents
children 3c736a81b886
comparison
equal deleted inserted replaced
-1:000000000000 0:9a224bd9b45f
1 /* A09, 6809 Assembler.
2
3 created 1993,1994 by L.C. Benschop.
4 copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details.
5 license: GNU General Public License version 2, see LICENSE for more details.
6 THERE IS NO WARRANTY ON THIS PROGRAM.
7
8 Generates binary image file from the lowest to
9 the highest address with actually assembled data.
10
11 Machine dependencies:
12 char is 8 bits.
13 short is 16 bits.
14 integer arithmetic is twos complement.
15
16 syntax a09 [-o filename] [-l filename] sourcefile.
17
18 Options
19 -o filename name of the output file (default name minus a09 suffix)
20 -s filename name of the s-record output file (default its a binary file)
21 -l filename list file name (default no listing)
22 -d enable debugging
23
24 recognized pseudoops:
25 extern public
26 macro endm if else endif
27 org equ set setdp
28 fcb fcw fdb fcc rmb
29 end include title
30
31 Not all of these are actually IMPLEMENTED!!!!!!
32
33 Revisions:
34 1993-11-03 v0.1
35 Initial version.
36 1994/03/21 v0.2
37 Fixed PC relative addressing bug
38 Added SET, SETDP, INCLUDE. IF/ELSE/ENDIF
39 No macros yet, and no separate linkable modules.
40 2012-06-04 j at klasek at
41 New: debugging parameter/option.
42 Fixed additional possible issue PC relative addressing.
43 Compatibility: Octal number prefix "&".
44 2014-07-15 j at klasek at
45 Fixed usage message.
46 */
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <ctype.h>
52
53 #define NLABELS 2048
54 #define MAXIDLEN 16
55 #define MAXLISTBYTES 8
56 #define FNLEN 30
57 #define LINELEN 128
58
59 static int debug=0;
60
61 struct oprecord{char * name;
62 unsigned char cat;
63 unsigned short code;};
64
65 /* Instruction categories:
66 0 one byte oprcodes NOP
67 1 two byte opcodes SWI2
68 2 opcodes w. imm byte ANDCC
69 3 LEAX etc.
70 4 short branches. BGE
71 5 long branches 2byte opc LBGE
72 6 long branches 1byte opc LBRA
73 7 accumulator instr. ADDA
74 8 double reg instr 1byte opc LDX
75 9 double reg instr 2 byte opc LDY
76 10 single address instrs NEG
77 11 TFR, EXG
78 12 push,pull
79 13 pseudoops
80 */
81
82 struct oprecord optable[]={
83 {"ABX",0,0x3a},{"ADCA",7,0x89},{"ADCB",7,0xc9},
84 {"ADDA",7,0x8b},{"ADDB",7,0xcb},{"ADDD",8,0xc3},
85 {"ANDA",7,0X84},{"ANDB",7,0xc4},{"ANDCC",2,0x1c},
86 {"ASL",10,0x08},{"ASLA",0,0x48},{"ASLB",0,0x58},
87 {"ASR",10,0x07},{"ASRA",0,0x47},{"ASRB",0,0x57},
88 {"BCC",4,0x24},{"BCS",4,0x25},{"BEQ",4,0x27},
89 {"BGE",4,0x2c},{"BGT",4,0x2e},{"BHI",4,0x22},
90 {"BHS",4,0x24},{"BITA",7,0x85},{"BITB",7,0xc5},
91 {"BLE",4,0x2f},{"BLO",4,0x25},{"BLS",4,0x23},
92 {"BLT",4,0x2d},{"BMI",4,0x2b},{"BNE",4,0x26},
93 {"BPL",4,0x2a},{"BRA",4,0x20},{"BRN",4,0x21},
94 {"BSR",4,0x8d},
95 {"BVC",4,0x28},{"BVS",4,0x29},
96 {"CLC",1,0x1cfe},{"CLF",1,0x1cbf},{"CLI",1,0x1cef},
97 {"CLIF",1,0x1caf},
98 {"CLR",10,0x0f},{"CLRA",0,0x4f},{"CLRB",0,0x5f},
99 {"CLV",1,0x1cfd},
100 {"CMPA",7,0x81},{"CMPB",7,0xc1},{"CMPD",9,0x1083},
101 {"CMPS",9,0x118c},{"CMPU",9,0x1183},{"CMPX",8,0x8c},
102 {"CMPY",9,0x108c},
103 {"COM",10,0x03},{"COMA",0,0x43},{"COMB",0,0x53},
104 {"CWAI",2,0x3c},{"DAA",0,0x19},
105 {"DEC",10,0x0a},{"DECA",0,0x4a},{"DECB",0,0x5a},
106 {"DES",1,0x327f},{"DEU",1,0x335f},{"DEX",1,0x301f},
107 {"DEY",1,0x313f},
108 {"ELSE",13,1},
109 {"EMOD",13,25},
110 {"END",13,2},
111 {"ENDC",13,3},
112 {"ENDIF",13,3},
113 {"ENDM",13,4},
114 {"EORA",7,0x88},{"EORB",7,0xc8},
115 {"EQU",13,5},{"EXG",11,0x1e},{"EXTERN",13,6},
116 {"FCB",13,7},{"FCC",13,8},
117 {"FCS",13,23},
118 {"FCW",13,9},
119 {"FDB",13,9},
120 {"IF",13,10},
121 {"IFEQ",13,29},
122 {"IFGT",13,30},
123 {"IFNE",13,28},
124 {"IFP1",13,21},
125 {"INC",10,0x0c},{"INCA",0,0x4c},{"INCB",0,0x5c},
126 {"INCLUDE",13,16},
127 {"INS",1,0x3261},{"INU",1,0x3341},{"INX",1,0x3001},
128 {"INY",1,0x3121},{"JMP",10,0x0e},{"JSR",8,0x8d},
129 {"LBCC",5,0x1024},{"LBCS",5,0x1025},{"LBEQ",5,0x1027},
130 {"LBGE",5,0x102c},{"LBGT",5,0x102e},{"LBHI",5,0x1022},
131 {"LBHS",5,0x1024},
132 {"LBLE",5,0x102f},{"LBLO",5,0x1025},{"LBLS",5,0x1023},
133 {"LBLT",5,0x102d},{"LBMI",5,0x102b},{"LBNE",5,0x1026},
134 {"LBPL",5,0x102a},{"LBRA",6,0x16},{"LBRN",5,0x1021},
135 {"LBSR",6,0x17},
136 {"LBVC",5,0x1028},{"LBVS",5,0x1029},
137 {"LDA",7,0x86},{"LDB",7,0xc6},{"LDD",8,0xcc},
138 {"LDS",9,0x10ce},{"LDU",8,0xce},{"LDX",8,0x8e},
139 {"LDY",9,0x108e},{"LEAS",3,0x32},
140 {"LEAU",3,0x33},{"LEAX",3,0x30},{"LEAY",3,0x31},
141 {"LSL",10,0x08},{"LSLA",0,0x48},{"LSLB",0,0x58},
142 {"LSR",10,0x04},{"LSRA",0,0x44},{"LSRB",0,0x54},
143 {"MACRO",13,11},
144 {"MOD",13,24},
145 {"MUL",0,0x3d},
146 {"NAM",13,26},
147 {"NEG",10,0x00},{"NEGA",0,0x40},{"NEGB",0,0x50},
148 {"NOP",0,0x12},
149 {"OPT",13,19},
150 {"ORA",7,0x8a},{"ORB",7,0xca},{"ORCC",2,0x1a},
151 {"ORG",13,12},
152 {"OS9",13,32},
153 {"PAG",13,20}, {"PAGE",13,20},
154 {"PSHS",12,0x34},{"PSHU",12,0x36},{"PUBLIC",13,13},
155 {"PULS",12,0x35},{"PULU",12,0x37},{"RMB",13,0},
156 {"ROL",10,0x09},{"ROLA",0,0x49},{"ROLB",0,0x59},
157 {"ROR",10,0x06},{"RORA",0,0x46},{"RORB",0,0x56},
158 {"RTI",0,0x3b},{"RTS",0,0x39},
159 {"SBCA",7,0x82},{"SBCB",7,0xc2},
160 {"SEC",1,0x1a01},{"SEF",1,0x1a40},{"SEI",1,0x1a10},
161 {"SEIF",1,0x1a50},{"SET",13,15},
162 {"SETDP",13,14},{"SEV",1,0x1a02},{"SEX",0,0x1d},
163 {"STA",7,0x87},{"STB",7,0xc7},{"STD",8,0xcd},
164 {"STS",9,0x10cf},{"STU",8,0xcf},{"STX",8,0x8f},
165 {"STY",9,0x108f},
166 {"SUBA",7,0x80},{"SUBB",7,0xc0},{"SUBD",8,0x83},
167 {"SWI",0,0x3f},{"SWI2",1,0x103f},{"SWI3",1,0x113f},
168 {"SYNC",0,0x13},{"TFR",11,0x1f},
169 {"TITLE",13,18},
170 {"TST",10,0x0d},{"TSTA",0,0x4d},{"TSTB",0,0x5d},
171 {"TTL",13,18},
172 {"USE",13,27},
173 };
174
175 struct symrecord{char name[MAXIDLEN+1];
176 char cat;
177 unsigned short value;
178 };
179
180 int symcounter=0;
181
182 /* Symbol categories.
183 0 Constant value (from equ).
184 1 Variable value (from set)
185 2 Address within program module (label).
186 3 Variable containing address.
187 4 Adress in other program module (extern)
188 5 Variable containing external address.
189 6 Unresolved address.
190 7 Variable containing unresolved address.
191 8 Public label.
192 9 Macro definition.
193 10 Public label (yet undefined).
194 11 parameter name.
195 12 local label.
196 13 empty.
197 */
198
199 struct symrecord symtable[NLABELS];
200
201 void processfile(char *name);
202
203 struct oprecord * findop(char * nm)
204 /* Find operation (mnemonic) in table using binary search */
205 {
206 int lo,hi,i,s;
207 lo=0;hi=sizeof(optable)/sizeof(optable[0])-1;
208 do {
209 i=(lo+hi)/2;
210 s=strcmp(optable[i].name,nm);
211 if(s<0) lo=i+1;
212 else if(s>0) hi=i-1;
213 else break;
214 } while(hi>=lo);
215 if (s) return NULL;
216 return optable+i;
217 }
218
219 struct symrecord * findsym(char * nm)
220 /* finds symbol table record; inserts if not found
221 uses binary search, maintains sorted table */
222 {
223 int lo,hi,i,j,s;
224 lo=0;hi=symcounter-1;
225 s=1;i=0;
226 while (hi>=lo) {
227 i=(lo+hi)/2;
228 s=strcmp(symtable[i].name,nm);
229 if(s<0) lo=i+1;
230 else if(s>0) hi=i-1;
231 else break;
232 }
233 if(s) {
234 i=(s<0?i+1:i);
235 if(symcounter==NLABELS) {
236 fprintf(stderr,"Sorry, no storage for symbols!!!");
237 exit(4);
238 }
239 for(j=symcounter;j>i;j--) symtable[j]=symtable[j-1];
240 symcounter++;
241 strcpy(symtable[i].name,nm);
242 symtable[i].cat=13;
243 }
244 return symtable+i;
245 }
246
247 FILE *listfile,*objfile;
248 char *listname,*objname,*srcname,*curname;
249 int lineno;
250
251 void
252 outsymtable()
253 {
254 int i,j=0;
255 fprintf(listfile,"\nSYMBOL TABLE");
256 for(i=0;i<symcounter;i++)
257 if(symtable[i].cat!=13) {
258 if(j%4==0)fprintf(listfile,"\n");
259 fprintf(listfile,"%10s %02d %04x",symtable[i].name,symtable[i].cat,
260 symtable[i].value);
261 j++;
262 }
263 fprintf(listfile,"\n");
264 }
265
266 struct regrecord{char *name;unsigned char tfr,psh;};
267 struct regrecord regtable[]=
268 {{"D",0x00,0x06},{"X",0x01,0x10},{"Y",0x02,0x20},
269 {"U",0x03,0x40},{"S",0x04,0x40},{"PC",0x05,0x80},
270 {"A",0x08,0x02},{"B",0x09,0x04},{"CC",0x0a,0x01},
271 {"CCR",0x0a,0x01},{"DP",0x0b,0x08},{"DPR",0x0b,0x08}};
272
273 struct regrecord * findreg(char *nm)
274 {
275 int i;
276 for(i=0;i<12;i++) {
277 if(strcmp(regtable[i].name,nm)==0) return regtable+i;
278 }
279 return 0;
280 }
281
282
283 char pass; /* Assembler pass=1 or 2 */
284 char listing; /* flag to indicate listing */
285 char relocatable; /* flag to indicate relocatable object. */
286 char terminate; /* flag to indicate termination. */
287 char generating; /* flag to indicate that we generate code */
288 unsigned short loccounter,oldlc; /* Location counter */
289
290 char inpline[128]; /* Current input line (not expanded)*/
291 char srcline[128]; /* Current source line */
292 char * srcptr; /* Pointer to line being parsed */
293
294 char unknown; /* flag to indicate value unknown */
295 char certain; /* flag to indicate value is certain at pass 1*/
296 int error; /* flags indicating errors in current line. */
297 int errors; /* number of errors */
298 char exprcat; /* category of expression being parsed, eg.
299 label or constant, this is important when
300 generating relocatable object code. */
301
302
303 char namebuf[MAXIDLEN+1];
304
305 void
306 err(int er) {
307 error |= er ;
308 }
309
310 void
311 scanname()
312 {
313 int i=0;
314 char c;
315 while(1) {
316 c=*srcptr++;
317 if(c>='a'&&c<='z')c-=32;
318 if(c!='.'&&c!='$'&&(c<'0'||c>'9')&&(c<'A'||c>'Z'))break;
319 if(i<MAXIDLEN)namebuf[i++]=c;
320 }
321 namebuf[i]=0;
322 srcptr--;
323 }
324
325 void
326 skipspace()
327 {
328 char c;
329 do {
330 c=*srcptr++;
331 } while(c==' '||c=='\t');
332 srcptr--;
333 }
334
335 short scanexpr(int);
336
337 short scandecimal()
338 {
339 char c;
340 short t=0;
341 c=*srcptr++;
342 while(isdigit(c)) {
343 t=t*10+c-'0';
344 c=*srcptr++;
345 }
346 srcptr--;
347 return t;
348 }
349
350 short scanhex()
351 {
352 short t=0,i=0;
353 srcptr++;
354 scanname();
355 while(namebuf[i]>='0'&&namebuf[i]<='F') {
356 t=t*16+namebuf[i]-'0';
357 if(namebuf[i]>'9')t-=7;
358 i++;
359 }
360 if(i==0)error|=1;
361 return t;
362 }
363
364 short scanchar()
365 {
366 short t;
367 srcptr++;
368 t=*srcptr;
369 if(t)srcptr++;
370 if (*srcptr=='\'')srcptr++;
371 return t;
372 }
373
374 short scanbin()
375 {
376 char c;
377 short t=0;
378 srcptr++;
379 c=*srcptr++;
380 while(c=='0'||c=='1') {
381 t=t*2+c-'0';
382 c=*srcptr++;
383 }
384 srcptr--;
385 return t;
386 }
387
388 short scanoct()
389 {
390 char c;
391 short t=0;
392 srcptr++;
393 c=*srcptr++;
394 while(c>='0'&&c<='7') {
395 t=t*8+c-'0';
396 c=*srcptr++;
397 }
398 srcptr--;
399 return t;
400 }
401
402
403 short scanlabel()
404 {
405 struct symrecord * p;
406 scanname();
407 p=findsym(namebuf);
408 if(p->cat==13) {
409 p->cat=6;
410 p->value=0;
411 }
412 if(p->cat==9||p->cat==11)error|=1;
413 exprcat=p->cat&14;
414 if(exprcat==6||exprcat==10)unknown=1;
415 if(((exprcat==2||exprcat==8)
416 && (unsigned short)(p->value)>(unsigned short)loccounter)||
417 exprcat==4)
418 certain=0;
419 if(exprcat==8||exprcat==6||exprcat==10)exprcat=2;
420 return p->value;
421 }
422
423 /* expression categories...
424 all zeros is ordinary constant.
425 bit 1 indicates address within module.
426 bit 2 indicates external address.
427 bit 4 indicates this can't be relocated if it's an address.
428 bit 5 indicates address (if any) is negative.
429 */
430
431
432
433 short scanfactor()
434 {
435 char c;
436 short t;
437 skipspace();
438 c=*srcptr;
439 if(isalpha(c))return scanlabel();
440 else if(isdigit(c))return scandecimal();
441 else switch(c) {
442 case '.' :
443 case '*' : srcptr++;exprcat|=2;return loccounter;
444 case '$' : return scanhex();
445 case '%' : return scanbin();
446 case '&' : /* compatibility */
447 case '@' : return scanoct();
448 case '\'' : return scanchar();
449 case '(' : srcptr++;t=scanexpr(0);skipspace();
450 if(*srcptr==')')srcptr++;else error|=1;
451 return t;
452 case '-' : srcptr++;exprcat^=32;return -scanfactor();
453 case '+' : srcptr++;return scanfactor();
454 case '!' : srcptr++;exprcat|=16;return !scanfactor();
455 case '^' :
456 case '~' : srcptr++;exprcat|=16;return ~scanfactor();
457 }
458 error|=1;
459 return 0;
460 }
461
462 #define EXITEVAL {srcptr--;return t;}
463
464 #define RESOLVECAT if((oldcat&15)==0)oldcat=0;\
465 if((exprcat&15)==0)exprcat=0;\
466 if((exprcat==2&&oldcat==34)||(exprcat==34&&oldcat==2)) {\
467 exprcat=0;\
468 oldcat=0;}\
469 exprcat|=oldcat;\
470 /* resolve such cases as constant added to address or difference between
471 two addresses in same module */
472
473
474 short scanexpr(int level) /* This is what you call _recursive_ descent!!!*/
475 {
476 short t,u;
477 char oldcat,c;
478 exprcat=0;
479 if(level==10)return scanfactor();
480 t=scanexpr(level+1);
481 while(1) {
482 skipspace();
483 c=*srcptr++;
484 switch(c) {
485 case '*':oldcat=exprcat;
486 t*=scanexpr(10);
487 exprcat|=oldcat|16;
488 break;
489 case '/':oldcat=exprcat;
490 u=scanexpr(10);
491 if(u)t/=u;else error|=1;
492 exprcat|=oldcat|16;
493 break;
494 case '%':oldcat=exprcat;
495 u=scanexpr(10);
496 if(u)t%=u;else error|=1;
497 exprcat|=oldcat|16;
498 break;
499 case '+':if(level==9)EXITEVAL
500 oldcat=exprcat;
501 t+=scanexpr(9);
502 RESOLVECAT
503 break;
504 case '-':if(level==9)EXITEVAL
505 oldcat=exprcat;
506 t-=scanexpr(9);
507 exprcat^=32;
508 RESOLVECAT
509 break;
510 case '<':if(*(srcptr)=='<') {
511 if(level>=8)EXITEVAL
512 srcptr++;
513 oldcat=exprcat;
514 t<<=scanexpr(8);
515 exprcat|=oldcat|16;
516 break;
517 } else if(*(srcptr)=='=') {
518 if(level>=7)EXITEVAL
519 srcptr++;
520 oldcat=exprcat;
521 t=t<=scanexpr(7);
522 exprcat|=oldcat|16;
523 break;
524 } else {
525 if(level>=7)EXITEVAL
526 oldcat=exprcat;
527 t=t<scanexpr(7);
528 exprcat|=oldcat|16;
529 break;
530 }
531 case '>':if(*(srcptr)=='>') {
532 if(level>=8)EXITEVAL
533 srcptr++;
534 oldcat=exprcat;
535 t>>=scanexpr(8);
536 exprcat|=oldcat|16;
537 break;
538 } else if(*(srcptr)=='=') {
539 if(level>=7)EXITEVAL
540 srcptr++;
541 oldcat=exprcat;
542 t=t>=scanexpr(7);
543 exprcat|=oldcat|16;
544 break;
545 } else {
546 if(level>=7)EXITEVAL
547 oldcat=exprcat;
548 t=t>scanexpr(7);
549 exprcat|=oldcat|16;
550 break;
551 }
552 case '!':if(level>=6||*srcptr!='=')EXITEVAL
553 srcptr++;
554 oldcat=exprcat;
555 t=t!=scanexpr(6);
556 exprcat|=oldcat|16;
557 break;
558 case '=':if(level>=6)EXITEVAL
559 if(*srcptr=='=')srcptr++;
560 oldcat=exprcat;
561 t=t==scanexpr(6);
562 exprcat|=oldcat|16;
563 break;
564 case '&':if(level>=5)EXITEVAL
565 oldcat=exprcat;
566 t&=scanexpr(5);
567 exprcat|=oldcat|16;
568 break;
569 case '^':if(level>=4)EXITEVAL
570 oldcat=exprcat;
571 t^=scanexpr(4);
572 exprcat|=oldcat|16;
573 break;
574 case '|':if(level>=3)EXITEVAL
575 oldcat=exprcat;
576 t|=scanexpr(3);
577 exprcat|=oldcat|16;
578 default: EXITEVAL
579 }
580 }
581 }
582
583 char mode; /* addressing mode 0=immediate,1=direct,2=extended,3=postbyte
584 4=pcrelative(with postbyte) 5=indirect 6=pcrel&indirect*/
585 char opsize; /*desired operand size 0=dunno,1=5,2=8,3=16*/
586 short operand;
587 unsigned char postbyte;
588
589 int dpsetting;
590
591
592 int scanindexreg()
593 {
594 char c;
595 c=*srcptr;
596 if(islower(c))c-=32;
597 if (debug) fprintf(stderr,"DEBUG: scanindexreg: indexreg=%d, mode=%d, opsize=%d, error=%d, postbyte=%02X\n",c,mode,opsize,error,postbyte);
598 switch(c) {
599 case 'X':return 1;
600 case 'Y':postbyte|=0x20;return 1;
601 case 'U':postbyte|=0x40;return 1;
602 case 'S':postbyte|=0x60;return 1;
603 default: return 0;
604 }
605 }
606
607 void
608 set3()
609 {
610 if(mode<3)mode=3;
611 }
612
613 void
614 scanspecial()
615 {
616 set3();
617 skipspace();
618 if(*srcptr=='-') {
619 srcptr++;
620 if(*srcptr=='-') {
621 srcptr++;
622 postbyte=0x83;
623 } else postbyte=0x82;
624 if(!scanindexreg())error|=2;else srcptr++;
625 } else {
626 postbyte=0x80;
627 if(!scanindexreg())error|=2;else srcptr++;
628 if(*srcptr=='+') {
629 srcptr++;
630 if(*srcptr=='+') {
631 srcptr++;
632 postbyte+=1;
633 }
634 } else postbyte+=4;
635 }
636 }
637
638 void
639 scanindexed()
640 {
641 set3();
642 postbyte=0;
643 if(scanindexreg()) {
644 srcptr++;
645 if(opsize==0) {
646 if(unknown||!certain)opsize=3;
647 else if(operand>=-16&&operand<16&&mode==3)opsize=1;
648 else if(operand>=-128&&operand<128)opsize=2;
649 else opsize=3;
650 }
651 switch(opsize) {
652 case 1:postbyte+=(operand&31);opsize=0;break;
653 case 2:postbyte+=0x88;break;
654 case 3:postbyte+=0x89;break;
655 }
656 } else { /*pc relative*/
657 if(toupper(*srcptr)!='P')error|=2;
658 else {
659 srcptr++;
660 if(toupper(*srcptr)!='C')error|=2;
661 else {
662 srcptr++;
663 if(toupper(*srcptr)=='R')srcptr++;
664 }
665 }
666 mode++;postbyte+=0x8c;
667 if(opsize==1)opsize=2;
668 }
669 }
670
671 #define RESTORE {srcptr=oldsrcptr;c=*srcptr;goto dodefault;}
672
673 void
674 scanoperands()
675 {
676 char c,d,*oldsrcptr;
677 unknown=0;
678 opsize=0;
679 certain=1;
680 skipspace();
681 c=*srcptr;
682 mode=0;
683 if(c=='[') {
684 srcptr++;
685 c=*srcptr;
686 mode=5;
687 }
688 if (debug) fprintf(stderr,"DEBUG: scanoperands: c=%c (%02X)\n",c,c);
689 switch(c) {
690 case 'D': case 'd':
691 oldsrcptr=srcptr;
692 srcptr++;
693 skipspace();
694 if(*srcptr!=',')RESTORE else {
695 postbyte=0x8b;
696 srcptr++;
697 if(!scanindexreg())RESTORE else {srcptr++;set3();}
698 }
699 break;
700 case 'A': case 'a':
701 oldsrcptr=srcptr;
702 srcptr++;
703 skipspace();
704 if(*srcptr!=',')RESTORE else {
705 postbyte=0x86;
706 srcptr++;
707 if(!scanindexreg())RESTORE else {srcptr++;set3();}
708 }
709 break;
710 case 'B': case 'b':
711 oldsrcptr=srcptr;
712 srcptr++;
713 skipspace();
714 if(*srcptr!=',')RESTORE else {
715 postbyte=0x85;
716 srcptr++;
717 if (debug) fprintf(stderr,"DEBUG: scanoperands: breg preindex: c=%c (%02X)\n",*srcptr,*srcptr);
718 if(!scanindexreg())RESTORE else {srcptr++;set3();}
719 if (debug) fprintf(stderr,"DEBUG: scanoperands: breg: postindex c=%c (%02X)\n",*srcptr,*srcptr);
720 }
721 break;
722 case ',':
723 srcptr++;
724 scanspecial();
725 break;
726 case '#':
727 if(mode==5)error|=2;else mode=0;
728 srcptr++;
729 operand=scanexpr(0);
730 break;
731 case '<':
732 srcptr++;
733 if(*srcptr=='<') {
734 srcptr++;
735 opsize=1;
736 } else opsize=2;
737 goto dodefault;
738 case '>':
739 srcptr++;
740 opsize=3;
741 default: dodefault:
742 operand=scanexpr(0);
743 skipspace();
744 if(*srcptr==',') {
745 srcptr++;
746 scanindexed();
747 } else {
748 if(opsize==0) {
749 if(unknown||!certain||dpsetting==-1||
750 (unsigned short)(operand-dpsetting*256)>=256)
751 opsize=3; else opsize=2;
752 }
753 if(opsize==1)opsize=2;
754 if(mode==5){
755 postbyte=0x8f;
756 opsize=3;
757 } else mode=opsize-1;
758 }
759 }
760 if (debug) fprintf(stderr,"DEBUG: scanoperands: mode=%d, error=%d, postbyte=%02X\n",mode,error,postbyte);
761 if(mode>=5) {
762 skipspace();
763 postbyte|=0x10;
764 if(*srcptr!=']')error|=2;else srcptr++;
765 }
766 if(pass==2&&unknown)error|=4;
767 }
768
769 unsigned char codebuf[128];
770 int codeptr; /* byte offset within instruction */
771 int suppress; /* 0=no suppress 1=until ENDIF 2=until ELSE 3=until ENDM */
772 int ifcount; /* count of nested IFs within suppressed text */
773
774 unsigned char outmode; /* 0 is binary, 1 is s-records */
775
776 unsigned short hexaddr;
777 int hexcount;
778 unsigned char hexbuffer[16];
779 unsigned int chksum;
780
781 extern int os9crc(unsigned char c, int crcp);
782 int crc;
783
784 void
785 reset_crc()
786 {
787 crc = -1;
788 }
789
790
791 void
792 flushhex()
793 {
794 int i;
795 if(hexcount){
796 fprintf(objfile,"S1%02X%04X",(hexcount+3)&0xff,hexaddr&0xffff);
797 for(i=0;i<hexcount;i++)fprintf(objfile,"%02X",hexbuffer[i]);
798 chksum+=(hexaddr&0xff)+((hexaddr>>8)&0xff)+hexcount+3;
799 fprintf(objfile,"%02X\n",0xff-(chksum&0xff));
800 hexaddr+=hexcount;
801 hexcount=0;
802 chksum=0;
803 }
804 }
805
806 void
807 outhex(unsigned char x)
808 {
809 if(hexcount==16)flushhex();
810 hexbuffer[hexcount++]=x;
811 chksum+=x;
812 }
813
814 void
815 outbuffer()
816 {
817 int i;
818 for(i=0;i<codeptr;i++) {
819 crc = os9crc(codebuf[i],crc);
820 if(!outmode)fputc(codebuf[i],objfile);else outhex(codebuf[i]);
821 }
822 }
823
824 char *errormsg[]={"Error in expression",
825 "Illegal addressing mode",
826 "Undefined label",
827 "Multiple definitions of label",
828 "Relative branch out of range",
829 "Missing label",
830 "","","","","","","","","",
831 "Illegal mnemonic"
832 };
833
834 void
835 report()
836 {
837 int i;
838 fprintf(stderr,"File %s, line %d:%s\n",curname,lineno,srcline);
839 for(i=0;i<16;i++) {
840 if(error&1) {
841 fprintf(stderr,"%s\n",errormsg[i]);
842 if(pass==2&&listing)fprintf(listfile,"**** %s\n",errormsg[i]);
843 }
844 error>>=1;
845 }
846 errors++;
847 }
848
849 void
850 outlist()
851 {
852 int i;
853 fprintf(listfile,"%04X: ",oldlc);
854 for(i=0;i<codeptr&&i<MAXLISTBYTES;i++)
855 fprintf(listfile,"%02X",codebuf[i]);
856 for(;i<=MAXLISTBYTES;i++)
857 fprintf(listfile," ");
858 fprintf(listfile,"%s\n",srcline);
859 while(i<codeptr) {
860 fprintf(listfile,"%04X: ",oldlc + i);
861 for(int j=0;i<codeptr&&j<MAXLISTBYTES;j++) {
862 fprintf(listfile,"%02X",codebuf[i]); i++;
863 }
864 fprintf(listfile,"\n");
865 }
866 }
867
868 void
869 setlabel(struct symrecord * lp)
870 {
871 if(lp) {
872 if(lp->cat!=13&&lp->cat!=6) {
873 if(lp->cat!=2||lp->value!=loccounter)
874 error|=8;
875 } else {
876 lp->cat=2;
877 lp->value=loccounter;
878 }
879 }
880 }
881
882 void
883 putbyte(unsigned char b)
884 {
885 codebuf[codeptr++]=b;
886 }
887
888 void
889 putword(unsigned short w)
890 {
891 codebuf[codeptr++]=w>>8;
892 codebuf[codeptr++]=w&0x0ff;
893 }
894
895 void
896 doaddress() /* assemble the right addressing bytes for an instruction */
897 {
898 int offs;
899 switch(mode) {
900 case 0: if(opsize==2)putbyte(operand);else putword(operand);break;
901 case 1: putbyte(operand);break;
902 case 2: putword(operand);break;
903 case 3: case 5: putbyte(postbyte);
904 switch(opsize) {
905 case 2: putbyte(operand);break;
906 case 3: putword(operand);
907 }
908 break;
909 case 4: case 6: offs=(unsigned short)operand-loccounter-codeptr-2;
910 if(offs<-128||offs>=128||opsize==3||unknown||!certain) {
911 if((!unknown)&&opsize==2&&(offs<-128||offs>=128) )
912 error|=16;
913 offs--;
914 opsize=3;
915 postbyte++;
916 }
917 putbyte(postbyte);
918 if (debug) fprintf(stderr,"DEBUG: doaddress: mode=%d, opsize=%d, error=%d, postbyte=%02X, operand=%04X offs=%d\n",mode,opsize,error,postbyte,operand,offs);
919 if(opsize==3)putword(offs);
920 else putbyte(offs);
921 }
922 }
923
924 void
925 onebyte(int co)
926 {
927 putbyte(co);
928 }
929
930 void
931 twobyte(int co)
932 {
933 putword(co);
934 }
935
936 void
937 oneimm(int co)
938 {
939 scanoperands();
940 if(mode>=3)error|=2;
941 putbyte(co);
942 putbyte(operand);
943 }
944
945 void
946 lea(int co)
947 {
948 putbyte(co);
949 scanoperands();
950 if(mode==0) error|=2;
951 if(mode<3) {
952 opsize=3;
953 postbyte=0x8f;
954 mode=3;
955 }
956 if (debug) fprintf(stderr,"DEBUG: lea: mode=%d, opsize=%d, error=%d, postbyte=%02X, *src=%c\n",mode,opsize,error,postbyte,*srcptr);
957 doaddress();
958 }
959
960 void
961 sbranch(int co)
962 {
963 int offs;
964 scanoperands();
965 if(mode!=1&&mode!=2)error|=2;
966 offs=(unsigned short)operand-loccounter-2;
967 if(!unknown&&(offs<-128||offs>=128))error|=16;
968 if(pass==2&&unknown)error|=4;
969 putbyte(co);
970 putbyte(offs);
971 }
972
973 void
974 lbra(int co)
975 {
976 scanoperands();
977 if(mode!=1&&mode!=2)error|=2;
978 putbyte(co);
979 putword(operand-loccounter-3);
980 }
981
982 void
983 lbranch(int co)
984 {
985 scanoperands();
986 if(mode!=1&&mode!=2)error|=2;
987 putword(co);
988 putword(operand-loccounter-4);
989 }
990
991 void
992 arith(int co)
993 {
994 scanoperands();
995 switch(mode) {
996 case 0:opsize=2;putbyte(co);break;
997 case 1:putbyte(co+0x010);break;
998 case 2:putbyte(co+0x030);break;
999 default:putbyte(co+0x020);
1000 }
1001 doaddress();
1002 }
1003
1004 void
1005 darith(int co)
1006 {
1007 scanoperands();
1008 switch(mode) {
1009 case 0:opsize=3;putbyte(co);break;
1010 case 1:putbyte(co+0x010);break;
1011 case 2:putbyte(co+0x030);break;
1012 default:putbyte(co+0x020);
1013 }
1014 doaddress();
1015 }
1016
1017 void
1018 d2arith(int co)
1019 {
1020 scanoperands();
1021 switch(mode) {
1022 case 0:opsize=3;putword(co);break;
1023 case 1:putword(co+0x010);break;
1024 case 2:putword(co+0x030);break;
1025 default:putword(co+0x020);
1026 }
1027 doaddress();
1028 }
1029
1030 void
1031 oneaddr(int co)
1032 {
1033 scanoperands();
1034 switch(mode) {
1035 case 0: error|=2;break;
1036 case 1: putbyte(co);break;
1037 case 2: putbyte(co+0x70);break;
1038 default: putbyte(co+0x60);break;
1039 }
1040 doaddress();
1041 }
1042
1043 void
1044 tfrexg(int co)
1045 {
1046 struct regrecord * p;
1047 putbyte(co);
1048 skipspace();
1049 scanname();
1050 if((p=findreg(namebuf))==0)error|=2;
1051 else postbyte=(p->tfr)<<4;
1052 skipspace();
1053 if(*srcptr==',')srcptr++;else error|=2;
1054 skipspace();
1055 scanname();
1056 if((p=findreg(namebuf))==0)error|=2;
1057 else postbyte|=p->tfr;
1058 putbyte(postbyte);
1059 }
1060
1061 void
1062 pshpul(int co)
1063 {
1064 struct regrecord *p;
1065 putbyte(co);
1066 postbyte=0;
1067 do {
1068 if(*srcptr==',')srcptr++;
1069 skipspace();
1070 scanname();
1071 if((p=findreg(namebuf))==0)error|=2;
1072 else postbyte|=p->psh;
1073 skipspace();
1074 }while (*srcptr==',');
1075 putbyte(postbyte);
1076 }
1077
1078 void
1079 skipComma()
1080 {
1081 while(*srcptr && *srcptr!='\n' && *srcptr!=',')srcptr++;
1082 if (*srcptr==',') {
1083 srcptr++;
1084 } else {
1085 error|=1;
1086 }
1087 }
1088
1089 int modStart;
1090
1091 void os9begin()
1092 {
1093 generating=1;
1094 modStart = loccounter;
1095 reset_crc();
1096 putword(0x87cd);
1097 putword(scanexpr(0)-loccounter); // module size
1098 skipComma();
1099 putword(scanexpr(0)-loccounter); // offset to module name
1100 skipComma();
1101 putbyte(scanexpr(0)); // type / language
1102 skipComma();
1103 putbyte(scanexpr(0)); // attribute
1104 int parity=0;
1105 for(int i=0; i< 8; i++) parity^=codebuf[i];
1106 putbyte(parity^0xff); // header parity
1107 skipspace();
1108 while (*srcptr==',') { // there are some more
1109 srcptr++;
1110 putword(scanexpr(0));
1111 skipspace();
1112 }
1113 }
1114
1115 void os9end()
1116 {
1117 crc = crc ^ 0xffffff;
1118
1119 putbyte((crc>>16)&0xff);
1120 putbyte((crc>>8)&0xff);
1121 putbyte(crc&0xff);
1122 }
1123
1124
1125 void
1126 pseudoop(int co,struct symrecord * lp)
1127 {
1128 int i;
1129 char c;
1130 char *fname;
1131 int locsave;
1132
1133 switch(co) {
1134 case 0:/* RMB */
1135 setlabel(lp);
1136 operand=scanexpr(0);
1137 if(unknown)error|=4;
1138 loccounter+=operand;
1139 if(generating&&pass==2) {
1140 if(!outmode)for(i=0;i<operand;i++)fputc(0,objfile);
1141 else flushhex();
1142 }
1143 hexaddr=loccounter;
1144 break;
1145 case 5:/* EQU */
1146 operand=scanexpr(0);
1147 if(!lp)error|=32;
1148 else {
1149 if(lp->cat==13||lp->cat==6||
1150 (lp->value==(unsigned short)operand&&pass==2)) {
1151 if(exprcat==2)lp->cat=2;
1152 else lp->cat=0;
1153 lp->value=operand;
1154 } else error|=8;
1155 }
1156 break;
1157 case 7:/* FCB */
1158 setlabel(lp);
1159 generating=1;
1160 do {
1161 if(*srcptr==',')srcptr++;
1162 skipspace();
1163 if(*srcptr=='\"') {
1164 srcptr++;
1165 while(*srcptr!='\"'&&*srcptr)
1166 putbyte(*srcptr++);
1167 if(*srcptr=='\"')srcptr++;
1168 } else {
1169 putbyte(scanexpr(0));
1170 if(unknown&&pass==2)error|=4;
1171 }
1172 skipspace();
1173 } while(*srcptr==',');
1174 break;
1175 case 8:/* FCC */
1176 setlabel(lp);
1177 skipspace();
1178 c=*srcptr++;
1179 while(*srcptr!=c&&*srcptr)
1180 putbyte(*srcptr++);
1181 if(*srcptr==c)srcptr++;
1182 break;
1183 case 9:/* FDB */
1184 setlabel(lp);
1185 generating=1;
1186 do {
1187 if(*srcptr==',')srcptr++;
1188 skipspace();
1189 putword(scanexpr(0));
1190 if(unknown&&pass==2)error|=4;
1191 skipspace();
1192 } while(*srcptr==',');
1193 break;
1194 case 23 :/* FCS */
1195 setlabel(lp);
1196 generating=1;
1197 skipspace();
1198 int sep = *srcptr;
1199 if(sep=='\"' || sep=='/') {
1200 srcptr++;
1201 while(*srcptr!=sep&&*srcptr)
1202 putbyte(*srcptr++);
1203 if(*srcptr==sep)srcptr++;
1204 codebuf[codeptr-1] |= 0x80; // os9 string termination
1205 }
1206 break;
1207 case 1: /* ELSE */
1208 suppress=1;
1209 break;
1210 case 21: /* IFP1 */
1211 if(pass==2)suppress=2;
1212 break;
1213 case 29: /* IFGT */
1214 operand=scanexpr(0);
1215 if(unknown)error|=4;
1216 if(operand>0)suppress=2;
1217 break;
1218 case 31: /* IFLT */
1219 operand=scanexpr(0);
1220 if(unknown)error|=4;
1221 if(operand<0)suppress=2;
1222 break;
1223 case 28: /* IFNE */
1224 operand=scanexpr(0);
1225 if(unknown)error|=4;
1226 if(operand==0)suppress=2;
1227 break;
1228 case 30: /* IFEQ */
1229 case 10: /* IF */
1230 operand=scanexpr(0);
1231 if(unknown)error|=4;
1232 if(!operand)suppress=2;
1233 break;
1234 case 12: /* ORG */
1235 operand=scanexpr(0);
1236 if(unknown)error|=4;
1237 if(generating&&pass==2) {
1238 for(i=0;i<(unsigned short)operand-loccounter;i++)
1239 if(!outmode)fputc(0,objfile);else flushhex();
1240 }
1241 loccounter=operand;
1242 hexaddr=loccounter;
1243 break;
1244 case 14: /* SETDP */
1245 operand=scanexpr(0);
1246 if(unknown)error|=4;
1247 if(!(operand&255))operand=(unsigned short)operand>>8;
1248 if((unsigned)operand>255)operand=-1;
1249 dpsetting=operand;
1250 break;
1251 case 15: /* SET */
1252 operand=scanexpr(0);
1253 if(!lp)error|=32;
1254 else {
1255 if(lp->cat&1||lp->cat==6) {
1256 if(exprcat==2)lp->cat=3;
1257 else lp->cat=1;
1258 lp->value=operand;
1259 } else error|=8;
1260 }
1261 break;
1262 case 2: /* END */
1263 terminate=1;
1264 break;
1265 case 27: /* USE */
1266 locsave = loccounter ;
1267 case 16: /* INCLUDE */
1268 skipspace();
1269 if(*srcptr=='"')srcptr++;
1270 i = 0;
1271 for(i=0; !(srcptr[i]==0||srcptr[i]=='"'); i++);
1272 int len = i;
1273 fname = calloc(1,len);
1274 for(i=0;i<len;i++) {
1275 if(*srcptr==0||*srcptr=='"')break;
1276 fname[i]=*srcptr++;
1277 }
1278 fname[i]=0;
1279 processfile(fname);
1280 codeptr=0;
1281 srcline[0]=0;
1282 if (co==27) loccounter = locsave;
1283 break;
1284 case 24: /* MOD */
1285 loccounter = 0;
1286 setlabel(lp);
1287 os9begin();
1288 break;
1289 case 25: /* EMOD */
1290 os9end();
1291 break;
1292 case 32: /* OS9 */
1293 setlabel(lp);
1294 putword(0x103f); // SWI2
1295 putbyte(scanexpr(0));
1296 break;
1297 case 18: /* TTL */
1298 break;
1299 case 19: /* OPT */
1300 case 26: /* NAM */
1301 case 20: /* PAG */
1302 case 3: /* ENDIF/ENDC */
1303 break;
1304 }
1305 }
1306
1307
1308 void
1309 processline()
1310 {
1311 struct symrecord * lp;
1312 struct oprecord * op;
1313 int co;
1314 char c;
1315 srcptr=srcline;
1316 oldlc=loccounter;
1317 error=0;
1318 unknown=0;certain=1;
1319 lp=0;
1320 codeptr=0;
1321 if(isalnum(*srcptr)) {
1322 scanname();lp=findsym(namebuf);
1323 if(*srcptr==':') srcptr++;
1324 }
1325 skipspace();
1326 if(isalnum(*srcptr)) {
1327 scanname();
1328 op=findop(namebuf);
1329 if(op) {
1330 if(op->cat!=13){
1331 setlabel(lp);
1332 generating=1;
1333 }
1334 co=op->code;
1335 switch(op->cat) {
1336 case 0:onebyte(co);break;
1337 case 1:twobyte(co);break;
1338 case 2:oneimm(co);break;
1339 case 3:lea(co);break;
1340 case 4:sbranch(co);break;
1341 case 5:lbranch(co);break;
1342 case 6:lbra(co);break;
1343 case 7:arith(co);break;
1344 case 8:darith(co);break;
1345 case 9:d2arith(co);break;
1346 case 10:oneaddr(co);break;
1347 case 11:tfrexg(co);break;
1348 case 12:pshpul(co);break;
1349 case 13:pseudoop(co,lp);
1350 }
1351 c=*srcptr;
1352 if (debug) fprintf(stderr,"DEBUG: processline: mode=%d, opsize=%d, error=%d, postbyte=%02X c=%c\n",mode,opsize,error,postbyte,c);
1353 if(c!=' '&&*(srcptr-1)!=' '&&c!=0&&c!=';')error|=2;
1354 }
1355 else error|=0x8000;
1356 }else setlabel(lp);
1357 if(pass==2) {
1358 outbuffer();
1359 if(listing)outlist();
1360 }
1361 if(error)report();
1362 loccounter+=codeptr;
1363 }
1364
1365 void
1366 suppressline()
1367 {
1368 struct oprecord * op;
1369 srcptr=srcline;
1370 oldlc=loccounter;
1371 codeptr=0;
1372 if(isalnum(*srcptr)) {
1373 scanname();
1374 if(*srcptr==':')srcptr++;
1375 }
1376 skipspace();
1377 scanname();op=findop(namebuf);
1378 if(op && op->cat==13) {
1379 if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30) ifcount++;
1380 else if(op->code==3) {
1381 if(ifcount>0)ifcount--;else if(suppress==1|suppress==2)suppress=0;
1382 } else if(op->code==1) {
1383 if(ifcount==0 && suppress==2)suppress=0;
1384 }
1385 }
1386 if(pass==2&&listing)outlist();
1387 }
1388
1389 void
1390 usage(char*nm)
1391 {
1392 fprintf(stderr,"Usage: %s [-o objname] [-l listname] [-s srecord-file] srcname\n",nm);
1393 exit(2);
1394 }
1395
1396 char *
1397 strconcat(char *s,int spos,char *d)
1398 {
1399 int slen = strlen(s);
1400 int dlen = strlen(d);
1401 if ( spos == 0) spos = slen;
1402 char *out = calloc(1,spos+dlen+1);
1403 int i = 0;
1404 for(; i< spos; i++ ) out[i] = s[i];
1405 for(; i< spos+dlen+1; i++ ) out[i] = *d++;
1406 return out;
1407 }
1408
1409
1410 void
1411 getoptions(int c,char*v[])
1412 {
1413 int i=0;
1414 if(c==1)usage(v[0]);
1415 if(strcmp(v[1],"-d")==0) {
1416 debug=1;
1417 i++;
1418 }
1419 if(strcmp(v[1],"-o")==0) {
1420 if(c<4)usage(v[0]);
1421 objname = v[2];
1422 i+=2;
1423 }
1424 if(strcmp(v[i+1],"-s")==0) {
1425 if(c<4+i)usage(v[0]);
1426 objname=v[i+2];
1427 outmode=1;
1428 i+=2;
1429 }
1430 if(strcmp(v[i+1],"-l")==0) {
1431 if(c<4+i)usage(v[0]);
1432 listname=v[2+i];
1433 i+=2;
1434 }
1435 srcname=v[1+i];
1436 if(objname==0) {
1437 for(i=0;srcname[i]!='.' && srcname[i]!=0 ;i++) ;
1438 objname = strconcat(srcname,i,".b");
1439 }
1440 listing=(listname!=0);
1441 }
1442
1443 void
1444 expandline()
1445 {
1446 int i=0,j=0,k,j1;
1447 for(i=0;i<128&&j<128;i++)
1448 {
1449 if(inpline[i]=='\n') {
1450 srcline[j]=0;break;
1451 }
1452 if(inpline[i]=='\t') {
1453 j1=j;
1454 for(k=0;k<8-j1%8 && j<128;k++)srcline[j++]=' ';
1455 }else srcline[j++]=inpline[i];
1456 }
1457 srcline[127]=0;
1458 }
1459
1460
1461 void
1462 processfile(char *name)
1463 {
1464 char *oldname;
1465 int oldno;
1466 FILE *srcfile;
1467 oldname=curname;
1468 curname=name;
1469 oldno=lineno;
1470 lineno=0;
1471 if((srcfile=fopen(name,"r"))==0) {
1472 int i = strlen(oldname);
1473 while(i>0 && oldname[i]!='/') i--;
1474 if (i>0) {
1475 char *next = strconcat(oldname,i+1,name);
1476 if((srcfile=fopen(next,"r"))==0) {
1477 fprintf(stderr,"Cannot open source file %s\n",next);
1478 exit(4);
1479 }
1480 curname = next;
1481 } else {
1482 fprintf(stderr,"Cannot open source file %s\n",name);
1483 exit(4);
1484 }
1485 }
1486 while(!terminate&&fgets(inpline,128,srcfile)) {
1487 expandline();
1488 lineno++;
1489 srcptr=srcline;
1490 if(suppress)suppressline(); else processline();
1491 }
1492 fclose(srcfile);
1493 if(suppress) {
1494 fprintf(stderr,"improperly nested IF statements in %s",curname);
1495 errors++;
1496 suppress=0;
1497 }
1498 lineno=oldno;
1499 curname=oldname;
1500 }
1501
1502 int
1503 main(int argc,char *argv[])
1504 {
1505 char c;
1506 getoptions(argc,argv);
1507 pass=1;
1508 errors=0;
1509 generating=0;
1510 terminate=0;
1511 processfile(srcname);
1512 if(errors) {
1513 fprintf(stderr,"%d Pass 1 Errors, Continue?",errors);
1514 c=getchar();
1515 if(c=='n'||c=='N') exit(3);
1516 }
1517 pass=2;
1518 loccounter=0;
1519 errors=0;
1520 generating=0;
1521 terminate=0;
1522 if(listing&&((listfile=fopen(listname,"w"))==0)) {
1523 fprintf(stderr,"Cannot open list file");
1524 exit(4);
1525 }
1526 if((objfile=fopen(objname,outmode?"w":"wb"))==0) {
1527 fprintf(stderr,"Cannot write object file\n");
1528 exit(4);
1529 }
1530 processfile(srcname);
1531 fprintf(stderr,"%d Pass 2 errors.\n",errors);
1532 if(listing) {
1533 fprintf(listfile,"%d Pass 2 errors.\n",errors);
1534 outsymtable();
1535 fclose(listfile);
1536 }
1537 if(outmode){
1538 flushhex();
1539 fprintf(objfile,"S9030000FC\n");
1540 }
1541 fclose(objfile);
1542 return 0;
1543 }
1544