0
|
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
|
5
|
11 Machin edependencies:
|
0
|
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;
|
3
|
181 int os9 = 0; // os9 flag
|
0
|
182
|
|
183 /* Symbol categories.
|
|
184 0 Constant value (from equ).
|
|
185 1 Variable value (from set)
|
|
186 2 Address within program module (label).
|
|
187 3 Variable containing address.
|
|
188 4 Adress in other program module (extern)
|
|
189 5 Variable containing external address.
|
|
190 6 Unresolved address.
|
|
191 7 Variable containing unresolved address.
|
|
192 8 Public label.
|
|
193 9 Macro definition.
|
|
194 10 Public label (yet undefined).
|
|
195 11 parameter name.
|
|
196 12 local label.
|
|
197 13 empty.
|
|
198 */
|
|
199
|
|
200 struct symrecord symtable[NLABELS];
|
|
201
|
|
202 void processfile(char *name);
|
|
203
|
|
204 struct oprecord * findop(char * nm)
|
|
205 /* Find operation (mnemonic) in table using binary search */
|
|
206 {
|
|
207 int lo,hi,i,s;
|
|
208 lo=0;hi=sizeof(optable)/sizeof(optable[0])-1;
|
|
209 do {
|
|
210 i=(lo+hi)/2;
|
|
211 s=strcmp(optable[i].name,nm);
|
|
212 if(s<0) lo=i+1;
|
|
213 else if(s>0) hi=i-1;
|
|
214 else break;
|
|
215 } while(hi>=lo);
|
|
216 if (s) return NULL;
|
|
217 return optable+i;
|
|
218 }
|
|
219
|
|
220 struct symrecord * findsym(char * nm)
|
|
221 /* finds symbol table record; inserts if not found
|
|
222 uses binary search, maintains sorted table */
|
|
223 {
|
|
224 int lo,hi,i,j,s;
|
|
225 lo=0;hi=symcounter-1;
|
|
226 s=1;i=0;
|
|
227 while (hi>=lo) {
|
|
228 i=(lo+hi)/2;
|
|
229 s=strcmp(symtable[i].name,nm);
|
|
230 if(s<0) lo=i+1;
|
|
231 else if(s>0) hi=i-1;
|
|
232 else break;
|
|
233 }
|
|
234 if(s) {
|
|
235 i=(s<0?i+1:i);
|
|
236 if(symcounter==NLABELS) {
|
|
237 fprintf(stderr,"Sorry, no storage for symbols!!!");
|
|
238 exit(4);
|
|
239 }
|
|
240 for(j=symcounter;j>i;j--) symtable[j]=symtable[j-1];
|
|
241 symcounter++;
|
|
242 strcpy(symtable[i].name,nm);
|
|
243 symtable[i].cat=13;
|
|
244 }
|
|
245 return symtable+i;
|
|
246 }
|
|
247
|
|
248 FILE *listfile,*objfile;
|
|
249 char *listname,*objname,*srcname,*curname;
|
|
250 int lineno;
|
|
251
|
|
252 void
|
|
253 outsymtable()
|
|
254 {
|
|
255 int i,j=0;
|
|
256 fprintf(listfile,"\nSYMBOL TABLE");
|
|
257 for(i=0;i<symcounter;i++)
|
|
258 if(symtable[i].cat!=13) {
|
|
259 if(j%4==0)fprintf(listfile,"\n");
|
|
260 fprintf(listfile,"%10s %02d %04x",symtable[i].name,symtable[i].cat,
|
|
261 symtable[i].value);
|
|
262 j++;
|
|
263 }
|
|
264 fprintf(listfile,"\n");
|
|
265 }
|
|
266
|
|
267 struct regrecord{char *name;unsigned char tfr,psh;};
|
|
268 struct regrecord regtable[]=
|
|
269 {{"D",0x00,0x06},{"X",0x01,0x10},{"Y",0x02,0x20},
|
|
270 {"U",0x03,0x40},{"S",0x04,0x40},{"PC",0x05,0x80},
|
|
271 {"A",0x08,0x02},{"B",0x09,0x04},{"CC",0x0a,0x01},
|
|
272 {"CCR",0x0a,0x01},{"DP",0x0b,0x08},{"DPR",0x0b,0x08}};
|
|
273
|
|
274 struct regrecord * findreg(char *nm)
|
|
275 {
|
|
276 int i;
|
|
277 for(i=0;i<12;i++) {
|
|
278 if(strcmp(regtable[i].name,nm)==0) return regtable+i;
|
|
279 }
|
|
280 return 0;
|
|
281 }
|
|
282
|
|
283
|
|
284 char pass; /* Assembler pass=1 or 2 */
|
|
285 char listing; /* flag to indicate listing */
|
|
286 char relocatable; /* flag to indicate relocatable object. */
|
|
287 char terminate; /* flag to indicate termination. */
|
|
288 char generating; /* flag to indicate that we generate code */
|
|
289 unsigned short loccounter,oldlc; /* Location counter */
|
|
290
|
|
291 char inpline[128]; /* Current input line (not expanded)*/
|
|
292 char srcline[128]; /* Current source line */
|
|
293 char * srcptr; /* Pointer to line being parsed */
|
|
294
|
|
295 char unknown; /* flag to indicate value unknown */
|
|
296 char certain; /* flag to indicate value is certain at pass 1*/
|
|
297 int error; /* flags indicating errors in current line. */
|
|
298 int errors; /* number of errors */
|
|
299 char exprcat; /* category of expression being parsed, eg.
|
|
300 label or constant, this is important when
|
|
301 generating relocatable object code. */
|
|
302
|
|
303
|
|
304 char namebuf[MAXIDLEN+1];
|
|
305
|
|
306 void
|
|
307 err(int er) {
|
|
308 error |= er ;
|
|
309 }
|
|
310
|
|
311 void
|
|
312 scanname()
|
|
313 {
|
|
314 int i=0;
|
|
315 char c;
|
|
316 while(1) {
|
|
317 c=*srcptr++;
|
|
318 if(c>='a'&&c<='z')c-=32;
|
|
319 if(c!='.'&&c!='$'&&(c<'0'||c>'9')&&(c<'A'||c>'Z'))break;
|
|
320 if(i<MAXIDLEN)namebuf[i++]=c;
|
|
321 }
|
|
322 namebuf[i]=0;
|
|
323 srcptr--;
|
|
324 }
|
|
325
|
|
326 void
|
|
327 skipspace()
|
|
328 {
|
|
329 char c;
|
|
330 do {
|
|
331 c=*srcptr++;
|
|
332 } while(c==' '||c=='\t');
|
|
333 srcptr--;
|
|
334 }
|
|
335
|
|
336 short scanexpr(int);
|
|
337
|
|
338 short scandecimal()
|
|
339 {
|
|
340 char c;
|
|
341 short t=0;
|
|
342 c=*srcptr++;
|
|
343 while(isdigit(c)) {
|
|
344 t=t*10+c-'0';
|
|
345 c=*srcptr++;
|
|
346 }
|
|
347 srcptr--;
|
|
348 return t;
|
|
349 }
|
|
350
|
|
351 short scanhex()
|
|
352 {
|
|
353 short t=0,i=0;
|
|
354 srcptr++;
|
|
355 scanname();
|
|
356 while(namebuf[i]>='0'&&namebuf[i]<='F') {
|
|
357 t=t*16+namebuf[i]-'0';
|
|
358 if(namebuf[i]>'9')t-=7;
|
|
359 i++;
|
|
360 }
|
|
361 if(i==0)error|=1;
|
|
362 return t;
|
|
363 }
|
|
364
|
|
365 short scanchar()
|
|
366 {
|
|
367 short t;
|
|
368 srcptr++;
|
|
369 t=*srcptr;
|
|
370 if(t)srcptr++;
|
|
371 if (*srcptr=='\'')srcptr++;
|
|
372 return t;
|
|
373 }
|
|
374
|
|
375 short scanbin()
|
|
376 {
|
|
377 char c;
|
|
378 short t=0;
|
|
379 srcptr++;
|
|
380 c=*srcptr++;
|
|
381 while(c=='0'||c=='1') {
|
|
382 t=t*2+c-'0';
|
|
383 c=*srcptr++;
|
|
384 }
|
|
385 srcptr--;
|
|
386 return t;
|
|
387 }
|
|
388
|
|
389 short scanoct()
|
|
390 {
|
|
391 char c;
|
|
392 short t=0;
|
|
393 srcptr++;
|
|
394 c=*srcptr++;
|
|
395 while(c>='0'&&c<='7') {
|
|
396 t=t*8+c-'0';
|
|
397 c=*srcptr++;
|
|
398 }
|
|
399 srcptr--;
|
|
400 return t;
|
|
401 }
|
|
402
|
|
403
|
|
404 short scanlabel()
|
|
405 {
|
|
406 struct symrecord * p;
|
|
407 scanname();
|
|
408 p=findsym(namebuf);
|
|
409 if(p->cat==13) {
|
|
410 p->cat=6;
|
|
411 p->value=0;
|
|
412 }
|
|
413 if(p->cat==9||p->cat==11)error|=1;
|
|
414 exprcat=p->cat&14;
|
|
415 if(exprcat==6||exprcat==10)unknown=1;
|
|
416 if(((exprcat==2||exprcat==8)
|
|
417 && (unsigned short)(p->value)>(unsigned short)loccounter)||
|
|
418 exprcat==4)
|
|
419 certain=0;
|
|
420 if(exprcat==8||exprcat==6||exprcat==10)exprcat=2;
|
|
421 return p->value;
|
|
422 }
|
|
423
|
|
424 /* expression categories...
|
|
425 all zeros is ordinary constant.
|
|
426 bit 1 indicates address within module.
|
|
427 bit 2 indicates external address.
|
|
428 bit 4 indicates this can't be relocated if it's an address.
|
|
429 bit 5 indicates address (if any) is negative.
|
|
430 */
|
|
431
|
|
432
|
|
433
|
|
434 short scanfactor()
|
|
435 {
|
|
436 char c;
|
|
437 short t;
|
|
438 skipspace();
|
|
439 c=*srcptr;
|
|
440 if(isalpha(c))return scanlabel();
|
|
441 else if(isdigit(c))return scandecimal();
|
|
442 else switch(c) {
|
|
443 case '.' :
|
|
444 case '*' : srcptr++;exprcat|=2;return loccounter;
|
|
445 case '$' : return scanhex();
|
|
446 case '%' : return scanbin();
|
|
447 case '&' : /* compatibility */
|
|
448 case '@' : return scanoct();
|
|
449 case '\'' : return scanchar();
|
|
450 case '(' : srcptr++;t=scanexpr(0);skipspace();
|
|
451 if(*srcptr==')')srcptr++;else error|=1;
|
|
452 return t;
|
|
453 case '-' : srcptr++;exprcat^=32;return -scanfactor();
|
|
454 case '+' : srcptr++;return scanfactor();
|
|
455 case '!' : srcptr++;exprcat|=16;return !scanfactor();
|
|
456 case '^' :
|
|
457 case '~' : srcptr++;exprcat|=16;return ~scanfactor();
|
|
458 }
|
|
459 error|=1;
|
|
460 return 0;
|
|
461 }
|
|
462
|
|
463 #define EXITEVAL {srcptr--;return t;}
|
|
464
|
|
465 #define RESOLVECAT if((oldcat&15)==0)oldcat=0;\
|
|
466 if((exprcat&15)==0)exprcat=0;\
|
|
467 if((exprcat==2&&oldcat==34)||(exprcat==34&&oldcat==2)) {\
|
|
468 exprcat=0;\
|
|
469 oldcat=0;}\
|
|
470 exprcat|=oldcat;\
|
|
471 /* resolve such cases as constant added to address or difference between
|
|
472 two addresses in same module */
|
|
473
|
|
474
|
|
475 short scanexpr(int level) /* This is what you call _recursive_ descent!!!*/
|
|
476 {
|
|
477 short t,u;
|
|
478 char oldcat,c;
|
|
479 exprcat=0;
|
|
480 if(level==10)return scanfactor();
|
|
481 t=scanexpr(level+1);
|
|
482 while(1) {
|
5
|
483 // skipspace();
|
0
|
484 c=*srcptr++;
|
|
485 switch(c) {
|
|
486 case '*':oldcat=exprcat;
|
|
487 t*=scanexpr(10);
|
|
488 exprcat|=oldcat|16;
|
|
489 break;
|
|
490 case '/':oldcat=exprcat;
|
|
491 u=scanexpr(10);
|
|
492 if(u)t/=u;else error|=1;
|
|
493 exprcat|=oldcat|16;
|
|
494 break;
|
|
495 case '%':oldcat=exprcat;
|
|
496 u=scanexpr(10);
|
|
497 if(u)t%=u;else error|=1;
|
|
498 exprcat|=oldcat|16;
|
|
499 break;
|
|
500 case '+':if(level==9)EXITEVAL
|
|
501 oldcat=exprcat;
|
|
502 t+=scanexpr(9);
|
|
503 RESOLVECAT
|
|
504 break;
|
|
505 case '-':if(level==9)EXITEVAL
|
|
506 oldcat=exprcat;
|
|
507 t-=scanexpr(9);
|
|
508 exprcat^=32;
|
|
509 RESOLVECAT
|
|
510 break;
|
|
511 case '<':if(*(srcptr)=='<') {
|
|
512 if(level>=8)EXITEVAL
|
|
513 srcptr++;
|
|
514 oldcat=exprcat;
|
|
515 t<<=scanexpr(8);
|
|
516 exprcat|=oldcat|16;
|
|
517 break;
|
|
518 } else if(*(srcptr)=='=') {
|
|
519 if(level>=7)EXITEVAL
|
|
520 srcptr++;
|
|
521 oldcat=exprcat;
|
|
522 t=t<=scanexpr(7);
|
|
523 exprcat|=oldcat|16;
|
|
524 break;
|
|
525 } else {
|
|
526 if(level>=7)EXITEVAL
|
|
527 oldcat=exprcat;
|
|
528 t=t<scanexpr(7);
|
|
529 exprcat|=oldcat|16;
|
|
530 break;
|
|
531 }
|
|
532 case '>':if(*(srcptr)=='>') {
|
|
533 if(level>=8)EXITEVAL
|
|
534 srcptr++;
|
|
535 oldcat=exprcat;
|
|
536 t>>=scanexpr(8);
|
|
537 exprcat|=oldcat|16;
|
|
538 break;
|
|
539 } else if(*(srcptr)=='=') {
|
|
540 if(level>=7)EXITEVAL
|
|
541 srcptr++;
|
|
542 oldcat=exprcat;
|
|
543 t=t>=scanexpr(7);
|
|
544 exprcat|=oldcat|16;
|
|
545 break;
|
|
546 } else {
|
|
547 if(level>=7)EXITEVAL
|
|
548 oldcat=exprcat;
|
|
549 t=t>scanexpr(7);
|
|
550 exprcat|=oldcat|16;
|
|
551 break;
|
|
552 }
|
5
|
553 case '!':if(level>=6) {
|
|
554 if (*srcptr=='=') {
|
|
555 srcptr++;
|
|
556 oldcat=exprcat;
|
|
557 t=t!=scanexpr(6);
|
|
558 exprcat|=oldcat|16;
|
|
559 } else {
|
|
560 oldcat=exprcat;
|
|
561 t|=scanexpr(6);
|
|
562 exprcat|=oldcat|16;
|
|
563 }
|
|
564 }
|
0
|
565 break;
|
|
566 case '=':if(level>=6)EXITEVAL
|
|
567 if(*srcptr=='=')srcptr++;
|
|
568 oldcat=exprcat;
|
|
569 t=t==scanexpr(6);
|
|
570 exprcat|=oldcat|16;
|
|
571 break;
|
|
572 case '&':if(level>=5)EXITEVAL
|
|
573 oldcat=exprcat;
|
|
574 t&=scanexpr(5);
|
|
575 exprcat|=oldcat|16;
|
|
576 break;
|
|
577 case '^':if(level>=4)EXITEVAL
|
|
578 oldcat=exprcat;
|
|
579 t^=scanexpr(4);
|
|
580 exprcat|=oldcat|16;
|
|
581 break;
|
|
582 case '|':if(level>=3)EXITEVAL
|
|
583 oldcat=exprcat;
|
|
584 t|=scanexpr(3);
|
|
585 exprcat|=oldcat|16;
|
|
586 default: EXITEVAL
|
|
587 }
|
|
588 }
|
|
589 }
|
|
590
|
|
591 char mode; /* addressing mode 0=immediate,1=direct,2=extended,3=postbyte
|
|
592 4=pcrelative(with postbyte) 5=indirect 6=pcrel&indirect*/
|
|
593 char opsize; /*desired operand size 0=dunno,1=5,2=8,3=16*/
|
|
594 short operand;
|
|
595 unsigned char postbyte;
|
|
596
|
|
597 int dpsetting;
|
|
598
|
|
599
|
|
600 int scanindexreg()
|
|
601 {
|
|
602 char c;
|
|
603 c=*srcptr;
|
|
604 if(islower(c))c-=32;
|
|
605 if (debug) fprintf(stderr,"DEBUG: scanindexreg: indexreg=%d, mode=%d, opsize=%d, error=%d, postbyte=%02X\n",c,mode,opsize,error,postbyte);
|
|
606 switch(c) {
|
|
607 case 'X':return 1;
|
|
608 case 'Y':postbyte|=0x20;return 1;
|
|
609 case 'U':postbyte|=0x40;return 1;
|
|
610 case 'S':postbyte|=0x60;return 1;
|
|
611 default: return 0;
|
|
612 }
|
|
613 }
|
|
614
|
|
615 void
|
|
616 set3()
|
|
617 {
|
|
618 if(mode<3)mode=3;
|
|
619 }
|
|
620
|
|
621 void
|
|
622 scanspecial()
|
|
623 {
|
|
624 set3();
|
|
625 skipspace();
|
|
626 if(*srcptr=='-') {
|
|
627 srcptr++;
|
|
628 if(*srcptr=='-') {
|
|
629 srcptr++;
|
|
630 postbyte=0x83;
|
|
631 } else postbyte=0x82;
|
|
632 if(!scanindexreg())error|=2;else srcptr++;
|
|
633 } else {
|
|
634 postbyte=0x80;
|
|
635 if(!scanindexreg())error|=2;else srcptr++;
|
|
636 if(*srcptr=='+') {
|
|
637 srcptr++;
|
|
638 if(*srcptr=='+') {
|
|
639 srcptr++;
|
|
640 postbyte+=1;
|
|
641 }
|
|
642 } else postbyte+=4;
|
|
643 }
|
|
644 }
|
|
645
|
|
646 void
|
|
647 scanindexed()
|
|
648 {
|
|
649 set3();
|
|
650 postbyte=0;
|
|
651 if(scanindexreg()) {
|
|
652 srcptr++;
|
|
653 if(opsize==0) {
|
|
654 if(unknown||!certain)opsize=3;
|
|
655 else if(operand>=-16&&operand<16&&mode==3)opsize=1;
|
|
656 else if(operand>=-128&&operand<128)opsize=2;
|
|
657 else opsize=3;
|
|
658 }
|
|
659 switch(opsize) {
|
|
660 case 1:postbyte+=(operand&31);opsize=0;break;
|
|
661 case 2:postbyte+=0x88;break;
|
|
662 case 3:postbyte+=0x89;break;
|
|
663 }
|
|
664 } else { /*pc relative*/
|
|
665 if(toupper(*srcptr)!='P')error|=2;
|
|
666 else {
|
|
667 srcptr++;
|
|
668 if(toupper(*srcptr)!='C')error|=2;
|
|
669 else {
|
|
670 srcptr++;
|
|
671 if(toupper(*srcptr)=='R')srcptr++;
|
|
672 }
|
|
673 }
|
|
674 mode++;postbyte+=0x8c;
|
|
675 if(opsize==1)opsize=2;
|
|
676 }
|
|
677 }
|
|
678
|
|
679 #define RESTORE {srcptr=oldsrcptr;c=*srcptr;goto dodefault;}
|
|
680
|
|
681 void
|
|
682 scanoperands()
|
|
683 {
|
|
684 char c,d,*oldsrcptr;
|
|
685 unknown=0;
|
|
686 opsize=0;
|
|
687 certain=1;
|
|
688 skipspace();
|
|
689 c=*srcptr;
|
|
690 mode=0;
|
|
691 if(c=='[') {
|
|
692 srcptr++;
|
|
693 c=*srcptr;
|
|
694 mode=5;
|
|
695 }
|
|
696 if (debug) fprintf(stderr,"DEBUG: scanoperands: c=%c (%02X)\n",c,c);
|
|
697 switch(c) {
|
|
698 case 'D': case 'd':
|
|
699 oldsrcptr=srcptr;
|
|
700 srcptr++;
|
|
701 skipspace();
|
|
702 if(*srcptr!=',')RESTORE else {
|
|
703 postbyte=0x8b;
|
|
704 srcptr++;
|
|
705 if(!scanindexreg())RESTORE else {srcptr++;set3();}
|
|
706 }
|
|
707 break;
|
|
708 case 'A': case 'a':
|
|
709 oldsrcptr=srcptr;
|
|
710 srcptr++;
|
|
711 skipspace();
|
|
712 if(*srcptr!=',')RESTORE else {
|
|
713 postbyte=0x86;
|
|
714 srcptr++;
|
|
715 if(!scanindexreg())RESTORE else {srcptr++;set3();}
|
|
716 }
|
|
717 break;
|
|
718 case 'B': case 'b':
|
|
719 oldsrcptr=srcptr;
|
|
720 srcptr++;
|
|
721 skipspace();
|
|
722 if(*srcptr!=',')RESTORE else {
|
|
723 postbyte=0x85;
|
|
724 srcptr++;
|
|
725 if (debug) fprintf(stderr,"DEBUG: scanoperands: breg preindex: c=%c (%02X)\n",*srcptr,*srcptr);
|
|
726 if(!scanindexreg())RESTORE else {srcptr++;set3();}
|
|
727 if (debug) fprintf(stderr,"DEBUG: scanoperands: breg: postindex c=%c (%02X)\n",*srcptr,*srcptr);
|
|
728 }
|
|
729 break;
|
|
730 case ',':
|
|
731 srcptr++;
|
|
732 scanspecial();
|
|
733 break;
|
|
734 case '#':
|
|
735 if(mode==5)error|=2;else mode=0;
|
|
736 srcptr++;
|
5
|
737 if (*srcptr=='"') {
|
|
738 operand = (srcptr[1]<<8) + srcptr[2] ;
|
|
739 srcptr += 3;
|
|
740 break;
|
|
741 }
|
0
|
742 operand=scanexpr(0);
|
|
743 break;
|
|
744 case '<':
|
|
745 srcptr++;
|
|
746 if(*srcptr=='<') {
|
|
747 srcptr++;
|
|
748 opsize=1;
|
|
749 } else opsize=2;
|
|
750 goto dodefault;
|
|
751 case '>':
|
|
752 srcptr++;
|
|
753 opsize=3;
|
|
754 default: dodefault:
|
|
755 operand=scanexpr(0);
|
|
756 skipspace();
|
|
757 if(*srcptr==',') {
|
|
758 srcptr++;
|
|
759 scanindexed();
|
|
760 } else {
|
|
761 if(opsize==0) {
|
|
762 if(unknown||!certain||dpsetting==-1||
|
|
763 (unsigned short)(operand-dpsetting*256)>=256)
|
|
764 opsize=3; else opsize=2;
|
|
765 }
|
|
766 if(opsize==1)opsize=2;
|
|
767 if(mode==5){
|
|
768 postbyte=0x8f;
|
|
769 opsize=3;
|
|
770 } else mode=opsize-1;
|
|
771 }
|
|
772 }
|
|
773 if (debug) fprintf(stderr,"DEBUG: scanoperands: mode=%d, error=%d, postbyte=%02X\n",mode,error,postbyte);
|
|
774 if(mode>=5) {
|
|
775 skipspace();
|
|
776 postbyte|=0x10;
|
|
777 if(*srcptr!=']')error|=2;else srcptr++;
|
|
778 }
|
|
779 if(pass==2&&unknown)error|=4;
|
|
780 }
|
|
781
|
|
782 unsigned char codebuf[128];
|
|
783 int codeptr; /* byte offset within instruction */
|
|
784 int suppress; /* 0=no suppress 1=until ENDIF 2=until ELSE 3=until ENDM */
|
|
785 int ifcount; /* count of nested IFs within suppressed text */
|
|
786
|
|
787 unsigned char outmode; /* 0 is binary, 1 is s-records */
|
|
788
|
|
789 unsigned short hexaddr;
|
|
790 int hexcount;
|
|
791 unsigned char hexbuffer[16];
|
|
792 unsigned int chksum;
|
|
793
|
|
794 extern int os9crc(unsigned char c, int crcp);
|
|
795 int crc;
|
|
796
|
|
797 void
|
|
798 reset_crc()
|
|
799 {
|
|
800 crc = -1;
|
|
801 }
|
|
802
|
|
803
|
|
804 void
|
|
805 flushhex()
|
|
806 {
|
|
807 int i;
|
|
808 if(hexcount){
|
|
809 fprintf(objfile,"S1%02X%04X",(hexcount+3)&0xff,hexaddr&0xffff);
|
|
810 for(i=0;i<hexcount;i++)fprintf(objfile,"%02X",hexbuffer[i]);
|
|
811 chksum+=(hexaddr&0xff)+((hexaddr>>8)&0xff)+hexcount+3;
|
|
812 fprintf(objfile,"%02X\n",0xff-(chksum&0xff));
|
|
813 hexaddr+=hexcount;
|
|
814 hexcount=0;
|
|
815 chksum=0;
|
|
816 }
|
|
817 }
|
|
818
|
|
819 void
|
|
820 outhex(unsigned char x)
|
|
821 {
|
|
822 if(hexcount==16)flushhex();
|
|
823 hexbuffer[hexcount++]=x;
|
|
824 chksum+=x;
|
|
825 }
|
|
826
|
|
827 void
|
|
828 outbuffer()
|
|
829 {
|
|
830 int i;
|
|
831 for(i=0;i<codeptr;i++) {
|
|
832 crc = os9crc(codebuf[i],crc);
|
|
833 if(!outmode)fputc(codebuf[i],objfile);else outhex(codebuf[i]);
|
|
834 }
|
|
835 }
|
|
836
|
|
837 char *errormsg[]={"Error in expression",
|
|
838 "Illegal addressing mode",
|
|
839 "Undefined label",
|
|
840 "Multiple definitions of label",
|
|
841 "Relative branch out of range",
|
|
842 "Missing label",
|
|
843 "","","","","","","","","",
|
|
844 "Illegal mnemonic"
|
|
845 };
|
|
846
|
|
847 void
|
|
848 report()
|
|
849 {
|
|
850 int i;
|
|
851 fprintf(stderr,"File %s, line %d:%s\n",curname,lineno,srcline);
|
|
852 for(i=0;i<16;i++) {
|
|
853 if(error&1) {
|
|
854 fprintf(stderr,"%s\n",errormsg[i]);
|
|
855 if(pass==2&&listing)fprintf(listfile,"**** %s\n",errormsg[i]);
|
|
856 }
|
|
857 error>>=1;
|
|
858 }
|
5
|
859 error = 0;
|
0
|
860 errors++;
|
|
861 }
|
|
862
|
|
863 void
|
|
864 outlist()
|
|
865 {
|
|
866 int i;
|
|
867 fprintf(listfile,"%04X: ",oldlc);
|
|
868 for(i=0;i<codeptr&&i<MAXLISTBYTES;i++)
|
|
869 fprintf(listfile,"%02X",codebuf[i]);
|
|
870 for(;i<=MAXLISTBYTES;i++)
|
|
871 fprintf(listfile," ");
|
|
872 fprintf(listfile,"%s\n",srcline);
|
|
873 while(i<codeptr) {
|
|
874 fprintf(listfile,"%04X: ",oldlc + i);
|
|
875 for(int j=0;i<codeptr&&j<MAXLISTBYTES;j++) {
|
|
876 fprintf(listfile,"%02X",codebuf[i]); i++;
|
|
877 }
|
|
878 fprintf(listfile,"\n");
|
|
879 }
|
|
880 }
|
|
881
|
|
882 void
|
|
883 setlabel(struct symrecord * lp)
|
|
884 {
|
|
885 if(lp) {
|
|
886 if(lp->cat!=13&&lp->cat!=6) {
|
|
887 if(lp->cat!=2||lp->value!=loccounter)
|
|
888 error|=8;
|
|
889 } else {
|
|
890 lp->cat=2;
|
|
891 lp->value=loccounter;
|
|
892 }
|
|
893 }
|
|
894 }
|
|
895
|
|
896 void
|
|
897 putbyte(unsigned char b)
|
|
898 {
|
|
899 codebuf[codeptr++]=b;
|
|
900 }
|
|
901
|
|
902 void
|
|
903 putword(unsigned short w)
|
|
904 {
|
|
905 codebuf[codeptr++]=w>>8;
|
|
906 codebuf[codeptr++]=w&0x0ff;
|
|
907 }
|
|
908
|
|
909 void
|
|
910 doaddress() /* assemble the right addressing bytes for an instruction */
|
|
911 {
|
|
912 int offs;
|
|
913 switch(mode) {
|
|
914 case 0: if(opsize==2)putbyte(operand);else putword(operand);break;
|
|
915 case 1: putbyte(operand);break;
|
|
916 case 2: putword(operand);break;
|
|
917 case 3: case 5: putbyte(postbyte);
|
|
918 switch(opsize) {
|
|
919 case 2: putbyte(operand);break;
|
|
920 case 3: putword(operand);
|
|
921 }
|
|
922 break;
|
|
923 case 4: case 6: offs=(unsigned short)operand-loccounter-codeptr-2;
|
|
924 if(offs<-128||offs>=128||opsize==3||unknown||!certain) {
|
|
925 if((!unknown)&&opsize==2&&(offs<-128||offs>=128) )
|
|
926 error|=16;
|
|
927 offs--;
|
|
928 opsize=3;
|
|
929 postbyte++;
|
|
930 }
|
|
931 putbyte(postbyte);
|
|
932 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);
|
|
933 if(opsize==3)putword(offs);
|
|
934 else putbyte(offs);
|
|
935 }
|
|
936 }
|
|
937
|
|
938 void
|
|
939 onebyte(int co)
|
|
940 {
|
|
941 putbyte(co);
|
|
942 }
|
|
943
|
|
944 void
|
|
945 twobyte(int co)
|
|
946 {
|
|
947 putword(co);
|
|
948 }
|
|
949
|
|
950 void
|
|
951 oneimm(int co)
|
|
952 {
|
|
953 scanoperands();
|
5
|
954 if(mode>=3)
|
|
955 error|=2;
|
0
|
956 putbyte(co);
|
|
957 putbyte(operand);
|
|
958 }
|
|
959
|
|
960 void
|
|
961 lea(int co)
|
|
962 {
|
|
963 putbyte(co);
|
|
964 scanoperands();
|
|
965 if(mode==0) error|=2;
|
|
966 if(mode<3) {
|
|
967 opsize=3;
|
|
968 postbyte=0x8f;
|
|
969 mode=3;
|
|
970 }
|
|
971 if (debug) fprintf(stderr,"DEBUG: lea: mode=%d, opsize=%d, error=%d, postbyte=%02X, *src=%c\n",mode,opsize,error,postbyte,*srcptr);
|
|
972 doaddress();
|
|
973 }
|
|
974
|
|
975 void
|
|
976 sbranch(int co)
|
|
977 {
|
|
978 int offs;
|
|
979 scanoperands();
|
|
980 if(mode!=1&&mode!=2)error|=2;
|
|
981 offs=(unsigned short)operand-loccounter-2;
|
|
982 if(!unknown&&(offs<-128||offs>=128))error|=16;
|
|
983 if(pass==2&&unknown)error|=4;
|
|
984 putbyte(co);
|
|
985 putbyte(offs);
|
|
986 }
|
|
987
|
|
988 void
|
|
989 lbra(int co)
|
|
990 {
|
|
991 scanoperands();
|
|
992 if(mode!=1&&mode!=2)error|=2;
|
|
993 putbyte(co);
|
|
994 putword(operand-loccounter-3);
|
|
995 }
|
|
996
|
|
997 void
|
|
998 lbranch(int co)
|
|
999 {
|
|
1000 scanoperands();
|
|
1001 if(mode!=1&&mode!=2)error|=2;
|
|
1002 putword(co);
|
|
1003 putword(operand-loccounter-4);
|
|
1004 }
|
|
1005
|
|
1006 void
|
|
1007 arith(int co)
|
|
1008 {
|
|
1009 scanoperands();
|
|
1010 switch(mode) {
|
|
1011 case 0:opsize=2;putbyte(co);break;
|
|
1012 case 1:putbyte(co+0x010);break;
|
|
1013 case 2:putbyte(co+0x030);break;
|
|
1014 default:putbyte(co+0x020);
|
|
1015 }
|
|
1016 doaddress();
|
|
1017 }
|
|
1018
|
|
1019 void
|
|
1020 darith(int co)
|
|
1021 {
|
|
1022 scanoperands();
|
|
1023 switch(mode) {
|
|
1024 case 0:opsize=3;putbyte(co);break;
|
|
1025 case 1:putbyte(co+0x010);break;
|
|
1026 case 2:putbyte(co+0x030);break;
|
|
1027 default:putbyte(co+0x020);
|
|
1028 }
|
|
1029 doaddress();
|
|
1030 }
|
|
1031
|
|
1032 void
|
|
1033 d2arith(int co)
|
|
1034 {
|
|
1035 scanoperands();
|
|
1036 switch(mode) {
|
|
1037 case 0:opsize=3;putword(co);break;
|
|
1038 case 1:putword(co+0x010);break;
|
|
1039 case 2:putword(co+0x030);break;
|
|
1040 default:putword(co+0x020);
|
|
1041 }
|
|
1042 doaddress();
|
|
1043 }
|
|
1044
|
|
1045 void
|
|
1046 oneaddr(int co)
|
|
1047 {
|
|
1048 scanoperands();
|
|
1049 switch(mode) {
|
|
1050 case 0: error|=2;break;
|
|
1051 case 1: putbyte(co);break;
|
|
1052 case 2: putbyte(co+0x70);break;
|
|
1053 default: putbyte(co+0x60);break;
|
|
1054 }
|
|
1055 doaddress();
|
|
1056 }
|
|
1057
|
|
1058 void
|
|
1059 tfrexg(int co)
|
|
1060 {
|
|
1061 struct regrecord * p;
|
|
1062 putbyte(co);
|
|
1063 skipspace();
|
|
1064 scanname();
|
|
1065 if((p=findreg(namebuf))==0)error|=2;
|
|
1066 else postbyte=(p->tfr)<<4;
|
|
1067 skipspace();
|
|
1068 if(*srcptr==',')srcptr++;else error|=2;
|
|
1069 skipspace();
|
|
1070 scanname();
|
|
1071 if((p=findreg(namebuf))==0)error|=2;
|
|
1072 else postbyte|=p->tfr;
|
|
1073 putbyte(postbyte);
|
|
1074 }
|
|
1075
|
|
1076 void
|
|
1077 pshpul(int co)
|
|
1078 {
|
|
1079 struct regrecord *p;
|
|
1080 putbyte(co);
|
|
1081 postbyte=0;
|
|
1082 do {
|
|
1083 if(*srcptr==',')srcptr++;
|
|
1084 skipspace();
|
|
1085 scanname();
|
|
1086 if((p=findreg(namebuf))==0)error|=2;
|
|
1087 else postbyte|=p->psh;
|
|
1088 skipspace();
|
|
1089 }while (*srcptr==',');
|
|
1090 putbyte(postbyte);
|
|
1091 }
|
|
1092
|
|
1093 void
|
|
1094 skipComma()
|
|
1095 {
|
|
1096 while(*srcptr && *srcptr!='\n' && *srcptr!=',')srcptr++;
|
|
1097 if (*srcptr==',') {
|
|
1098 srcptr++;
|
|
1099 } else {
|
|
1100 error|=1;
|
|
1101 }
|
|
1102 }
|
|
1103
|
|
1104 int modStart;
|
|
1105
|
|
1106 void os9begin()
|
|
1107 {
|
|
1108 generating=1;
|
3
|
1109 os9=1; // contiguous code generation ( i.e. ignore org nor rmb )
|
0
|
1110 modStart = loccounter;
|
|
1111 reset_crc();
|
|
1112 putword(0x87cd);
|
|
1113 putword(scanexpr(0)-loccounter); // module size
|
|
1114 skipComma();
|
|
1115 putword(scanexpr(0)-loccounter); // offset to module name
|
|
1116 skipComma();
|
|
1117 putbyte(scanexpr(0)); // type / language
|
|
1118 skipComma();
|
|
1119 putbyte(scanexpr(0)); // attribute
|
|
1120 int parity=0;
|
|
1121 for(int i=0; i< 8; i++) parity^=codebuf[i];
|
|
1122 putbyte(parity^0xff); // header parity
|
|
1123 skipspace();
|
|
1124 while (*srcptr==',') { // there are some more
|
|
1125 srcptr++;
|
|
1126 putword(scanexpr(0));
|
|
1127 skipspace();
|
|
1128 }
|
|
1129 }
|
|
1130
|
|
1131 void os9end()
|
|
1132 {
|
|
1133 crc = crc ^ 0xffffff;
|
|
1134
|
|
1135 putbyte((crc>>16)&0xff);
|
|
1136 putbyte((crc>>8)&0xff);
|
|
1137 putbyte(crc&0xff);
|
|
1138 }
|
|
1139
|
|
1140
|
|
1141 void
|
|
1142 pseudoop(int co,struct symrecord * lp)
|
|
1143 {
|
|
1144 int i;
|
|
1145 char c;
|
|
1146 char *fname;
|
|
1147 int locsave;
|
|
1148
|
|
1149 switch(co) {
|
|
1150 case 0:/* RMB */
|
3
|
1151 // in OS9 mode, this generates no data
|
|
1152 // loccounter will be reset after any code to the current code generation
|
0
|
1153 setlabel(lp);
|
|
1154 operand=scanexpr(0);
|
|
1155 if(unknown)error|=4;
|
|
1156 loccounter+=operand;
|
|
1157 if(generating&&pass==2) {
|
3
|
1158 if(!outmode || os9 )for(i=0;i<operand;i++) {
|
1
|
1159 fputc(0,objfile);
|
|
1160 } else flushhex();
|
0
|
1161 }
|
|
1162 hexaddr=loccounter;
|
|
1163 break;
|
|
1164 case 5:/* EQU */
|
|
1165 operand=scanexpr(0);
|
|
1166 if(!lp)error|=32;
|
|
1167 else {
|
|
1168 if(lp->cat==13||lp->cat==6||
|
|
1169 (lp->value==(unsigned short)operand&&pass==2)) {
|
|
1170 if(exprcat==2)lp->cat=2;
|
|
1171 else lp->cat=0;
|
|
1172 lp->value=operand;
|
|
1173 } else error|=8;
|
|
1174 }
|
|
1175 break;
|
|
1176 case 7:/* FCB */
|
|
1177 setlabel(lp);
|
|
1178 generating=1;
|
|
1179 do {
|
|
1180 if(*srcptr==',')srcptr++;
|
|
1181 skipspace();
|
|
1182 if(*srcptr=='\"') {
|
|
1183 srcptr++;
|
|
1184 while(*srcptr!='\"'&&*srcptr)
|
|
1185 putbyte(*srcptr++);
|
|
1186 if(*srcptr=='\"')srcptr++;
|
|
1187 } else {
|
|
1188 putbyte(scanexpr(0));
|
|
1189 if(unknown&&pass==2)error|=4;
|
|
1190 }
|
|
1191 skipspace();
|
|
1192 } while(*srcptr==',');
|
|
1193 break;
|
|
1194 case 8:/* FCC */
|
3
|
1195 generating=1;
|
0
|
1196 setlabel(lp);
|
|
1197 skipspace();
|
|
1198 c=*srcptr++;
|
|
1199 while(*srcptr!=c&&*srcptr)
|
|
1200 putbyte(*srcptr++);
|
|
1201 if(*srcptr==c)srcptr++;
|
|
1202 break;
|
|
1203 case 9:/* FDB */
|
3
|
1204 generating=1;
|
0
|
1205 setlabel(lp);
|
|
1206 do {
|
|
1207 if(*srcptr==',')srcptr++;
|
|
1208 skipspace();
|
|
1209 putword(scanexpr(0));
|
|
1210 if(unknown&&pass==2)error|=4;
|
|
1211 skipspace();
|
|
1212 } while(*srcptr==',');
|
|
1213 break;
|
|
1214 case 23 :/* FCS */
|
3
|
1215 generating=1;
|
0
|
1216 setlabel(lp);
|
|
1217 skipspace();
|
|
1218 int sep = *srcptr;
|
|
1219 if(sep=='\"' || sep=='/') {
|
|
1220 srcptr++;
|
|
1221 while(*srcptr!=sep&&*srcptr)
|
|
1222 putbyte(*srcptr++);
|
|
1223 if(*srcptr==sep)srcptr++;
|
|
1224 codebuf[codeptr-1] |= 0x80; // os9 string termination
|
|
1225 }
|
|
1226 break;
|
|
1227 case 1: /* ELSE */
|
|
1228 suppress=1;
|
|
1229 break;
|
|
1230 case 21: /* IFP1 */
|
|
1231 if(pass==2)suppress=2;
|
|
1232 break;
|
|
1233 case 29: /* IFGT */
|
|
1234 operand=scanexpr(0);
|
|
1235 if(unknown)error|=4;
|
|
1236 if(operand>0)suppress=2;
|
|
1237 break;
|
|
1238 case 31: /* IFLT */
|
|
1239 operand=scanexpr(0);
|
|
1240 if(unknown)error|=4;
|
|
1241 if(operand<0)suppress=2;
|
|
1242 break;
|
3
|
1243 case 30: /* IFEQ */
|
0
|
1244 operand=scanexpr(0);
|
|
1245 if(unknown)error|=4;
|
|
1246 if(operand==0)suppress=2;
|
|
1247 break;
|
3
|
1248 case 28: /* IFNE */
|
0
|
1249 case 10: /* IF */
|
|
1250 operand=scanexpr(0);
|
|
1251 if(unknown)error|=4;
|
|
1252 if(!operand)suppress=2;
|
|
1253 break;
|
|
1254 case 12: /* ORG */
|
|
1255 operand=scanexpr(0);
|
|
1256 if(unknown)error|=4;
|
3
|
1257 if(generating&&pass==2&&!outmode&&!os9) {
|
0
|
1258 for(i=0;i<(unsigned short)operand-loccounter;i++)
|
3
|
1259 fputc(0,objfile);
|
|
1260 } else flushhex();
|
0
|
1261 loccounter=operand;
|
|
1262 hexaddr=loccounter;
|
|
1263 break;
|
|
1264 case 14: /* SETDP */
|
|
1265 operand=scanexpr(0);
|
|
1266 if(unknown)error|=4;
|
|
1267 if(!(operand&255))operand=(unsigned short)operand>>8;
|
|
1268 if((unsigned)operand>255)operand=-1;
|
|
1269 dpsetting=operand;
|
|
1270 break;
|
|
1271 case 15: /* SET */
|
|
1272 operand=scanexpr(0);
|
|
1273 if(!lp)error|=32;
|
|
1274 else {
|
|
1275 if(lp->cat&1||lp->cat==6) {
|
|
1276 if(exprcat==2)lp->cat=3;
|
|
1277 else lp->cat=1;
|
|
1278 lp->value=operand;
|
|
1279 } else error|=8;
|
|
1280 }
|
|
1281 break;
|
|
1282 case 2: /* END */
|
|
1283 terminate=1;
|
|
1284 break;
|
|
1285 case 27: /* USE */
|
|
1286 locsave = loccounter ;
|
|
1287 case 16: /* INCLUDE */
|
|
1288 skipspace();
|
|
1289 if(*srcptr=='"')srcptr++;
|
|
1290 i = 0;
|
|
1291 for(i=0; !(srcptr[i]==0||srcptr[i]=='"'); i++);
|
|
1292 int len = i;
|
|
1293 fname = calloc(1,len);
|
|
1294 for(i=0;i<len;i++) {
|
|
1295 if(*srcptr==0||*srcptr=='"')break;
|
|
1296 fname[i]=*srcptr++;
|
|
1297 }
|
|
1298 fname[i]=0;
|
|
1299 processfile(fname);
|
|
1300 codeptr=0;
|
|
1301 srcline[0]=0;
|
3
|
1302 // if (co==27) loccounter = locsave;
|
0
|
1303 break;
|
|
1304 case 24: /* MOD */
|
|
1305 loccounter = 0;
|
|
1306 setlabel(lp);
|
|
1307 os9begin();
|
|
1308 break;
|
|
1309 case 25: /* EMOD */
|
|
1310 os9end();
|
|
1311 break;
|
|
1312 case 32: /* OS9 */
|
3
|
1313 generating = 1;
|
0
|
1314 setlabel(lp);
|
3
|
1315 putword(0x103f); // SWI2
|
0
|
1316 putbyte(scanexpr(0));
|
|
1317 break;
|
|
1318 case 18: /* TTL */
|
|
1319 break;
|
|
1320 case 19: /* OPT */
|
|
1321 case 26: /* NAM */
|
|
1322 case 20: /* PAG */
|
|
1323 case 3: /* ENDIF/ENDC */
|
|
1324 break;
|
|
1325 }
|
|
1326 }
|
|
1327
|
|
1328
|
|
1329 void
|
|
1330 processline()
|
|
1331 {
|
|
1332 struct symrecord * lp;
|
|
1333 struct oprecord * op;
|
|
1334 int co;
|
|
1335 char c;
|
|
1336 srcptr=srcline;
|
|
1337 oldlc=loccounter;
|
5
|
1338 // error=0;
|
0
|
1339 unknown=0;certain=1;
|
|
1340 lp=0;
|
|
1341 codeptr=0;
|
|
1342 if(isalnum(*srcptr)) {
|
|
1343 scanname();lp=findsym(namebuf);
|
|
1344 if(*srcptr==':') srcptr++;
|
|
1345 }
|
|
1346 skipspace();
|
|
1347 if(isalnum(*srcptr)) {
|
|
1348 scanname();
|
|
1349 op=findop(namebuf);
|
|
1350 if(op) {
|
|
1351 if(op->cat!=13){
|
|
1352 setlabel(lp);
|
|
1353 generating=1;
|
|
1354 }
|
|
1355 co=op->code;
|
|
1356 switch(op->cat) {
|
|
1357 case 0:onebyte(co);break;
|
|
1358 case 1:twobyte(co);break;
|
|
1359 case 2:oneimm(co);break;
|
|
1360 case 3:lea(co);break;
|
|
1361 case 4:sbranch(co);break;
|
|
1362 case 5:lbranch(co);break;
|
|
1363 case 6:lbra(co);break;
|
|
1364 case 7:arith(co);break;
|
|
1365 case 8:darith(co);break;
|
|
1366 case 9:d2arith(co);break;
|
|
1367 case 10:oneaddr(co);break;
|
|
1368 case 11:tfrexg(co);break;
|
|
1369 case 12:pshpul(co);break;
|
|
1370 case 13:pseudoop(co,lp);
|
|
1371 }
|
|
1372 c=*srcptr;
|
|
1373 if (debug) fprintf(stderr,"DEBUG: processline: mode=%d, opsize=%d, error=%d, postbyte=%02X c=%c\n",mode,opsize,error,postbyte,c);
|
|
1374 if(c!=' '&&*(srcptr-1)!=' '&&c!=0&&c!=';')error|=2;
|
|
1375 }
|
|
1376 else error|=0x8000;
|
|
1377 }else setlabel(lp);
|
|
1378 if(pass==2) {
|
|
1379 outbuffer();
|
|
1380 if(listing)outlist();
|
|
1381 }
|
|
1382 if(error)report();
|
|
1383 loccounter+=codeptr;
|
|
1384 }
|
|
1385
|
|
1386 void
|
|
1387 suppressline()
|
|
1388 {
|
|
1389 struct oprecord * op;
|
|
1390 srcptr=srcline;
|
|
1391 oldlc=loccounter;
|
|
1392 codeptr=0;
|
|
1393 if(isalnum(*srcptr)) {
|
|
1394 scanname();
|
|
1395 if(*srcptr==':')srcptr++;
|
|
1396 }
|
|
1397 skipspace();
|
|
1398 scanname();op=findop(namebuf);
|
|
1399 if(op && op->cat==13) {
|
|
1400 if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30) ifcount++;
|
|
1401 else if(op->code==3) {
|
|
1402 if(ifcount>0)ifcount--;else if(suppress==1|suppress==2)suppress=0;
|
|
1403 } else if(op->code==1) {
|
|
1404 if(ifcount==0 && suppress==2)suppress=0;
|
|
1405 }
|
|
1406 }
|
|
1407 if(pass==2&&listing)outlist();
|
|
1408 }
|
|
1409
|
|
1410 void
|
|
1411 usage(char*nm)
|
|
1412 {
|
|
1413 fprintf(stderr,"Usage: %s [-o objname] [-l listname] [-s srecord-file] srcname\n",nm);
|
|
1414 exit(2);
|
|
1415 }
|
|
1416
|
|
1417 char *
|
|
1418 strconcat(char *s,int spos,char *d)
|
|
1419 {
|
|
1420 int slen = strlen(s);
|
|
1421 int dlen = strlen(d);
|
|
1422 if ( spos == 0) spos = slen;
|
|
1423 char *out = calloc(1,spos+dlen+1);
|
|
1424 int i = 0;
|
|
1425 for(; i< spos; i++ ) out[i] = s[i];
|
|
1426 for(; i< spos+dlen+1; i++ ) out[i] = *d++;
|
|
1427 return out;
|
|
1428 }
|
|
1429
|
|
1430
|
|
1431 void
|
|
1432 getoptions(int c,char*v[])
|
|
1433 {
|
|
1434 int i=0;
|
|
1435 if(c==1)usage(v[0]);
|
|
1436 if(strcmp(v[1],"-d")==0) {
|
|
1437 debug=1;
|
|
1438 i++;
|
|
1439 }
|
|
1440 if(strcmp(v[1],"-o")==0) {
|
|
1441 if(c<4)usage(v[0]);
|
|
1442 objname = v[2];
|
|
1443 i+=2;
|
|
1444 }
|
|
1445 if(strcmp(v[i+1],"-s")==0) {
|
|
1446 if(c<4+i)usage(v[0]);
|
|
1447 objname=v[i+2];
|
|
1448 outmode=1;
|
|
1449 i+=2;
|
|
1450 }
|
|
1451 if(strcmp(v[i+1],"-l")==0) {
|
|
1452 if(c<4+i)usage(v[0]);
|
|
1453 listname=v[2+i];
|
|
1454 i+=2;
|
|
1455 }
|
|
1456 srcname=v[1+i];
|
|
1457 if(objname==0) {
|
|
1458 for(i=0;srcname[i]!='.' && srcname[i]!=0 ;i++) ;
|
|
1459 objname = strconcat(srcname,i,".b");
|
|
1460 }
|
|
1461 listing=(listname!=0);
|
|
1462 }
|
|
1463
|
|
1464 void
|
|
1465 expandline()
|
|
1466 {
|
|
1467 int i=0,j=0,k,j1;
|
|
1468 for(i=0;i<128&&j<128;i++)
|
|
1469 {
|
|
1470 if(inpline[i]=='\n') {
|
|
1471 srcline[j]=0;break;
|
|
1472 }
|
|
1473 if(inpline[i]=='\t') {
|
|
1474 j1=j;
|
|
1475 for(k=0;k<8-j1%8 && j<128;k++)srcline[j++]=' ';
|
|
1476 }else srcline[j++]=inpline[i];
|
|
1477 }
|
|
1478 srcline[127]=0;
|
|
1479 }
|
|
1480
|
|
1481
|
|
1482 void
|
|
1483 processfile(char *name)
|
|
1484 {
|
|
1485 char *oldname;
|
|
1486 int oldno;
|
|
1487 FILE *srcfile;
|
|
1488 oldname=curname;
|
|
1489 curname=name;
|
|
1490 oldno=lineno;
|
|
1491 lineno=0;
|
|
1492 if((srcfile=fopen(name,"r"))==0) {
|
|
1493 int i = strlen(oldname);
|
|
1494 while(i>0 && oldname[i]!='/') i--;
|
|
1495 if (i>0) {
|
|
1496 char *next = strconcat(oldname,i+1,name);
|
|
1497 if((srcfile=fopen(next,"r"))==0) {
|
|
1498 fprintf(stderr,"Cannot open source file %s\n",next);
|
|
1499 exit(4);
|
|
1500 }
|
|
1501 curname = next;
|
|
1502 } else {
|
|
1503 fprintf(stderr,"Cannot open source file %s\n",name);
|
|
1504 exit(4);
|
|
1505 }
|
|
1506 }
|
|
1507 while(!terminate&&fgets(inpline,128,srcfile)) {
|
|
1508 expandline();
|
|
1509 lineno++;
|
|
1510 srcptr=srcline;
|
|
1511 if(suppress)suppressline(); else processline();
|
|
1512 }
|
|
1513 fclose(srcfile);
|
|
1514 if(suppress) {
|
|
1515 fprintf(stderr,"improperly nested IF statements in %s",curname);
|
|
1516 errors++;
|
|
1517 suppress=0;
|
|
1518 }
|
|
1519 lineno=oldno;
|
|
1520 curname=oldname;
|
|
1521 }
|
|
1522
|
|
1523 int
|
|
1524 main(int argc,char *argv[])
|
|
1525 {
|
|
1526 char c;
|
|
1527 getoptions(argc,argv);
|
|
1528 pass=1;
|
|
1529 errors=0;
|
|
1530 generating=0;
|
|
1531 terminate=0;
|
|
1532 processfile(srcname);
|
|
1533 if(errors) {
|
|
1534 fprintf(stderr,"%d Pass 1 Errors, Continue?",errors);
|
|
1535 c=getchar();
|
|
1536 if(c=='n'||c=='N') exit(3);
|
|
1537 }
|
|
1538 pass=2;
|
|
1539 loccounter=0;
|
|
1540 errors=0;
|
|
1541 generating=0;
|
|
1542 terminate=0;
|
|
1543 if(listing&&((listfile=fopen(listname,"w"))==0)) {
|
|
1544 fprintf(stderr,"Cannot open list file");
|
|
1545 exit(4);
|
|
1546 }
|
|
1547 if((objfile=fopen(objname,outmode?"w":"wb"))==0) {
|
|
1548 fprintf(stderr,"Cannot write object file\n");
|
|
1549 exit(4);
|
|
1550 }
|
|
1551 processfile(srcname);
|
|
1552 fprintf(stderr,"%d Pass 2 errors.\n",errors);
|
|
1553 if(listing) {
|
|
1554 fprintf(listfile,"%d Pass 2 errors.\n",errors);
|
|
1555 outsymtable();
|
|
1556 fclose(listfile);
|
|
1557 }
|
|
1558 if(outmode){
|
|
1559 flushhex();
|
|
1560 fprintf(objfile,"S9030000FC\n");
|
|
1561 }
|
|
1562 fclose(objfile);
|
|
1563 return 0;
|
|
1564 }
|
|
1565
|