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