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
|
|
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) {
|
1
|
1140 if(!outmode)for(i=0;i<operand;i++) {
|
|
1141 crc = os9crc(0,crc);
|
|
1142 fputc(0,objfile);
|
|
1143 } else flushhex();
|
0
|
1144 }
|
|
1145 hexaddr=loccounter;
|
|
1146 break;
|
|
1147 case 5:/* EQU */
|
|
1148 operand=scanexpr(0);
|
|
1149 if(!lp)error|=32;
|
|
1150 else {
|
|
1151 if(lp->cat==13||lp->cat==6||
|
|
1152 (lp->value==(unsigned short)operand&&pass==2)) {
|
|
1153 if(exprcat==2)lp->cat=2;
|
|
1154 else lp->cat=0;
|
|
1155 lp->value=operand;
|
|
1156 } else error|=8;
|
|
1157 }
|
|
1158 break;
|
|
1159 case 7:/* FCB */
|
|
1160 setlabel(lp);
|
|
1161 generating=1;
|
|
1162 do {
|
|
1163 if(*srcptr==',')srcptr++;
|
|
1164 skipspace();
|
|
1165 if(*srcptr=='\"') {
|
|
1166 srcptr++;
|
|
1167 while(*srcptr!='\"'&&*srcptr)
|
|
1168 putbyte(*srcptr++);
|
|
1169 if(*srcptr=='\"')srcptr++;
|
|
1170 } else {
|
|
1171 putbyte(scanexpr(0));
|
|
1172 if(unknown&&pass==2)error|=4;
|
|
1173 }
|
|
1174 skipspace();
|
|
1175 } while(*srcptr==',');
|
|
1176 break;
|
|
1177 case 8:/* FCC */
|
|
1178 setlabel(lp);
|
|
1179 skipspace();
|
|
1180 c=*srcptr++;
|
|
1181 while(*srcptr!=c&&*srcptr)
|
|
1182 putbyte(*srcptr++);
|
|
1183 if(*srcptr==c)srcptr++;
|
|
1184 break;
|
|
1185 case 9:/* FDB */
|
|
1186 setlabel(lp);
|
|
1187 generating=1;
|
|
1188 do {
|
|
1189 if(*srcptr==',')srcptr++;
|
|
1190 skipspace();
|
|
1191 putword(scanexpr(0));
|
|
1192 if(unknown&&pass==2)error|=4;
|
|
1193 skipspace();
|
|
1194 } while(*srcptr==',');
|
|
1195 break;
|
|
1196 case 23 :/* FCS */
|
|
1197 setlabel(lp);
|
|
1198 generating=1;
|
|
1199 skipspace();
|
|
1200 int sep = *srcptr;
|
|
1201 if(sep=='\"' || sep=='/') {
|
|
1202 srcptr++;
|
|
1203 while(*srcptr!=sep&&*srcptr)
|
|
1204 putbyte(*srcptr++);
|
|
1205 if(*srcptr==sep)srcptr++;
|
|
1206 codebuf[codeptr-1] |= 0x80; // os9 string termination
|
|
1207 }
|
|
1208 break;
|
|
1209 case 1: /* ELSE */
|
|
1210 suppress=1;
|
|
1211 break;
|
|
1212 case 21: /* IFP1 */
|
|
1213 if(pass==2)suppress=2;
|
|
1214 break;
|
|
1215 case 29: /* IFGT */
|
|
1216 operand=scanexpr(0);
|
|
1217 if(unknown)error|=4;
|
|
1218 if(operand>0)suppress=2;
|
|
1219 break;
|
|
1220 case 31: /* IFLT */
|
|
1221 operand=scanexpr(0);
|
|
1222 if(unknown)error|=4;
|
|
1223 if(operand<0)suppress=2;
|
|
1224 break;
|
|
1225 case 28: /* IFNE */
|
|
1226 operand=scanexpr(0);
|
|
1227 if(unknown)error|=4;
|
|
1228 if(operand==0)suppress=2;
|
|
1229 break;
|
|
1230 case 30: /* IFEQ */
|
|
1231 case 10: /* IF */
|
|
1232 operand=scanexpr(0);
|
|
1233 if(unknown)error|=4;
|
|
1234 if(!operand)suppress=2;
|
|
1235 break;
|
|
1236 case 12: /* ORG */
|
|
1237 operand=scanexpr(0);
|
|
1238 if(unknown)error|=4;
|
|
1239 if(generating&&pass==2) {
|
|
1240 for(i=0;i<(unsigned short)operand-loccounter;i++)
|
1
|
1241 if(!outmode) { fputc(0,objfile); crc=os9crc(0,crc); } else flushhex();
|
0
|
1242 }
|
|
1243 loccounter=operand;
|
|
1244 hexaddr=loccounter;
|
|
1245 break;
|
|
1246 case 14: /* SETDP */
|
|
1247 operand=scanexpr(0);
|
|
1248 if(unknown)error|=4;
|
|
1249 if(!(operand&255))operand=(unsigned short)operand>>8;
|
|
1250 if((unsigned)operand>255)operand=-1;
|
|
1251 dpsetting=operand;
|
|
1252 break;
|
|
1253 case 15: /* SET */
|
|
1254 operand=scanexpr(0);
|
|
1255 if(!lp)error|=32;
|
|
1256 else {
|
|
1257 if(lp->cat&1||lp->cat==6) {
|
|
1258 if(exprcat==2)lp->cat=3;
|
|
1259 else lp->cat=1;
|
|
1260 lp->value=operand;
|
|
1261 } else error|=8;
|
|
1262 }
|
|
1263 break;
|
|
1264 case 2: /* END */
|
|
1265 terminate=1;
|
|
1266 break;
|
|
1267 case 27: /* USE */
|
|
1268 locsave = loccounter ;
|
|
1269 case 16: /* INCLUDE */
|
|
1270 skipspace();
|
|
1271 if(*srcptr=='"')srcptr++;
|
|
1272 i = 0;
|
|
1273 for(i=0; !(srcptr[i]==0||srcptr[i]=='"'); i++);
|
|
1274 int len = i;
|
|
1275 fname = calloc(1,len);
|
|
1276 for(i=0;i<len;i++) {
|
|
1277 if(*srcptr==0||*srcptr=='"')break;
|
|
1278 fname[i]=*srcptr++;
|
|
1279 }
|
|
1280 fname[i]=0;
|
|
1281 processfile(fname);
|
|
1282 codeptr=0;
|
|
1283 srcline[0]=0;
|
|
1284 if (co==27) loccounter = locsave;
|
|
1285 break;
|
|
1286 case 24: /* MOD */
|
|
1287 loccounter = 0;
|
|
1288 setlabel(lp);
|
|
1289 os9begin();
|
|
1290 break;
|
|
1291 case 25: /* EMOD */
|
|
1292 os9end();
|
|
1293 break;
|
|
1294 case 32: /* OS9 */
|
|
1295 setlabel(lp);
|
|
1296 putword(0x103f); // SWI2
|
|
1297 putbyte(scanexpr(0));
|
|
1298 break;
|
|
1299 case 18: /* TTL */
|
|
1300 break;
|
|
1301 case 19: /* OPT */
|
|
1302 case 26: /* NAM */
|
|
1303 case 20: /* PAG */
|
|
1304 case 3: /* ENDIF/ENDC */
|
|
1305 break;
|
|
1306 }
|
|
1307 }
|
|
1308
|
|
1309
|
|
1310 void
|
|
1311 processline()
|
|
1312 {
|
|
1313 struct symrecord * lp;
|
|
1314 struct oprecord * op;
|
|
1315 int co;
|
|
1316 char c;
|
|
1317 srcptr=srcline;
|
|
1318 oldlc=loccounter;
|
|
1319 error=0;
|
|
1320 unknown=0;certain=1;
|
|
1321 lp=0;
|
|
1322 codeptr=0;
|
|
1323 if(isalnum(*srcptr)) {
|
|
1324 scanname();lp=findsym(namebuf);
|
|
1325 if(*srcptr==':') srcptr++;
|
|
1326 }
|
|
1327 skipspace();
|
|
1328 if(isalnum(*srcptr)) {
|
|
1329 scanname();
|
|
1330 op=findop(namebuf);
|
|
1331 if(op) {
|
|
1332 if(op->cat!=13){
|
|
1333 setlabel(lp);
|
|
1334 generating=1;
|
|
1335 }
|
|
1336 co=op->code;
|
|
1337 switch(op->cat) {
|
|
1338 case 0:onebyte(co);break;
|
|
1339 case 1:twobyte(co);break;
|
|
1340 case 2:oneimm(co);break;
|
|
1341 case 3:lea(co);break;
|
|
1342 case 4:sbranch(co);break;
|
|
1343 case 5:lbranch(co);break;
|
|
1344 case 6:lbra(co);break;
|
|
1345 case 7:arith(co);break;
|
|
1346 case 8:darith(co);break;
|
|
1347 case 9:d2arith(co);break;
|
|
1348 case 10:oneaddr(co);break;
|
|
1349 case 11:tfrexg(co);break;
|
|
1350 case 12:pshpul(co);break;
|
|
1351 case 13:pseudoop(co,lp);
|
|
1352 }
|
|
1353 c=*srcptr;
|
|
1354 if (debug) fprintf(stderr,"DEBUG: processline: mode=%d, opsize=%d, error=%d, postbyte=%02X c=%c\n",mode,opsize,error,postbyte,c);
|
|
1355 if(c!=' '&&*(srcptr-1)!=' '&&c!=0&&c!=';')error|=2;
|
|
1356 }
|
|
1357 else error|=0x8000;
|
|
1358 }else setlabel(lp);
|
|
1359 if(pass==2) {
|
|
1360 outbuffer();
|
|
1361 if(listing)outlist();
|
|
1362 }
|
|
1363 if(error)report();
|
|
1364 loccounter+=codeptr;
|
|
1365 }
|
|
1366
|
|
1367 void
|
|
1368 suppressline()
|
|
1369 {
|
|
1370 struct oprecord * op;
|
|
1371 srcptr=srcline;
|
|
1372 oldlc=loccounter;
|
|
1373 codeptr=0;
|
|
1374 if(isalnum(*srcptr)) {
|
|
1375 scanname();
|
|
1376 if(*srcptr==':')srcptr++;
|
|
1377 }
|
|
1378 skipspace();
|
|
1379 scanname();op=findop(namebuf);
|
|
1380 if(op && op->cat==13) {
|
|
1381 if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30) ifcount++;
|
|
1382 else if(op->code==3) {
|
|
1383 if(ifcount>0)ifcount--;else if(suppress==1|suppress==2)suppress=0;
|
|
1384 } else if(op->code==1) {
|
|
1385 if(ifcount==0 && suppress==2)suppress=0;
|
|
1386 }
|
|
1387 }
|
|
1388 if(pass==2&&listing)outlist();
|
|
1389 }
|
|
1390
|
|
1391 void
|
|
1392 usage(char*nm)
|
|
1393 {
|
|
1394 fprintf(stderr,"Usage: %s [-o objname] [-l listname] [-s srecord-file] srcname\n",nm);
|
|
1395 exit(2);
|
|
1396 }
|
|
1397
|
|
1398 char *
|
|
1399 strconcat(char *s,int spos,char *d)
|
|
1400 {
|
|
1401 int slen = strlen(s);
|
|
1402 int dlen = strlen(d);
|
|
1403 if ( spos == 0) spos = slen;
|
|
1404 char *out = calloc(1,spos+dlen+1);
|
|
1405 int i = 0;
|
|
1406 for(; i< spos; i++ ) out[i] = s[i];
|
|
1407 for(; i< spos+dlen+1; i++ ) out[i] = *d++;
|
|
1408 return out;
|
|
1409 }
|
|
1410
|
|
1411
|
|
1412 void
|
|
1413 getoptions(int c,char*v[])
|
|
1414 {
|
|
1415 int i=0;
|
|
1416 if(c==1)usage(v[0]);
|
|
1417 if(strcmp(v[1],"-d")==0) {
|
|
1418 debug=1;
|
|
1419 i++;
|
|
1420 }
|
|
1421 if(strcmp(v[1],"-o")==0) {
|
|
1422 if(c<4)usage(v[0]);
|
|
1423 objname = v[2];
|
|
1424 i+=2;
|
|
1425 }
|
|
1426 if(strcmp(v[i+1],"-s")==0) {
|
|
1427 if(c<4+i)usage(v[0]);
|
|
1428 objname=v[i+2];
|
|
1429 outmode=1;
|
|
1430 i+=2;
|
|
1431 }
|
|
1432 if(strcmp(v[i+1],"-l")==0) {
|
|
1433 if(c<4+i)usage(v[0]);
|
|
1434 listname=v[2+i];
|
|
1435 i+=2;
|
|
1436 }
|
|
1437 srcname=v[1+i];
|
|
1438 if(objname==0) {
|
|
1439 for(i=0;srcname[i]!='.' && srcname[i]!=0 ;i++) ;
|
|
1440 objname = strconcat(srcname,i,".b");
|
|
1441 }
|
|
1442 listing=(listname!=0);
|
|
1443 }
|
|
1444
|
|
1445 void
|
|
1446 expandline()
|
|
1447 {
|
|
1448 int i=0,j=0,k,j1;
|
|
1449 for(i=0;i<128&&j<128;i++)
|
|
1450 {
|
|
1451 if(inpline[i]=='\n') {
|
|
1452 srcline[j]=0;break;
|
|
1453 }
|
|
1454 if(inpline[i]=='\t') {
|
|
1455 j1=j;
|
|
1456 for(k=0;k<8-j1%8 && j<128;k++)srcline[j++]=' ';
|
|
1457 }else srcline[j++]=inpline[i];
|
|
1458 }
|
|
1459 srcline[127]=0;
|
|
1460 }
|
|
1461
|
|
1462
|
|
1463 void
|
|
1464 processfile(char *name)
|
|
1465 {
|
|
1466 char *oldname;
|
|
1467 int oldno;
|
|
1468 FILE *srcfile;
|
|
1469 oldname=curname;
|
|
1470 curname=name;
|
|
1471 oldno=lineno;
|
|
1472 lineno=0;
|
|
1473 if((srcfile=fopen(name,"r"))==0) {
|
|
1474 int i = strlen(oldname);
|
|
1475 while(i>0 && oldname[i]!='/') i--;
|
|
1476 if (i>0) {
|
|
1477 char *next = strconcat(oldname,i+1,name);
|
|
1478 if((srcfile=fopen(next,"r"))==0) {
|
|
1479 fprintf(stderr,"Cannot open source file %s\n",next);
|
|
1480 exit(4);
|
|
1481 }
|
|
1482 curname = next;
|
|
1483 } else {
|
|
1484 fprintf(stderr,"Cannot open source file %s\n",name);
|
|
1485 exit(4);
|
|
1486 }
|
|
1487 }
|
|
1488 while(!terminate&&fgets(inpline,128,srcfile)) {
|
|
1489 expandline();
|
|
1490 lineno++;
|
|
1491 srcptr=srcline;
|
|
1492 if(suppress)suppressline(); else processline();
|
|
1493 }
|
|
1494 fclose(srcfile);
|
|
1495 if(suppress) {
|
|
1496 fprintf(stderr,"improperly nested IF statements in %s",curname);
|
|
1497 errors++;
|
|
1498 suppress=0;
|
|
1499 }
|
|
1500 lineno=oldno;
|
|
1501 curname=oldname;
|
|
1502 }
|
|
1503
|
|
1504 int
|
|
1505 main(int argc,char *argv[])
|
|
1506 {
|
|
1507 char c;
|
|
1508 getoptions(argc,argv);
|
|
1509 pass=1;
|
|
1510 errors=0;
|
|
1511 generating=0;
|
|
1512 terminate=0;
|
|
1513 processfile(srcname);
|
|
1514 if(errors) {
|
|
1515 fprintf(stderr,"%d Pass 1 Errors, Continue?",errors);
|
|
1516 c=getchar();
|
|
1517 if(c=='n'||c=='N') exit(3);
|
|
1518 }
|
|
1519 pass=2;
|
|
1520 loccounter=0;
|
|
1521 errors=0;
|
|
1522 generating=0;
|
|
1523 terminate=0;
|
|
1524 if(listing&&((listfile=fopen(listname,"w"))==0)) {
|
|
1525 fprintf(stderr,"Cannot open list file");
|
|
1526 exit(4);
|
|
1527 }
|
|
1528 if((objfile=fopen(objname,outmode?"w":"wb"))==0) {
|
|
1529 fprintf(stderr,"Cannot write object file\n");
|
|
1530 exit(4);
|
|
1531 }
|
|
1532 processfile(srcname);
|
|
1533 fprintf(stderr,"%d Pass 2 errors.\n",errors);
|
|
1534 if(listing) {
|
|
1535 fprintf(listfile,"%d Pass 2 errors.\n",errors);
|
|
1536 outsymtable();
|
|
1537 fclose(listfile);
|
|
1538 }
|
|
1539 if(outmode){
|
|
1540 flushhex();
|
|
1541 fprintf(objfile,"S9030000FC\n");
|
|
1542 }
|
|
1543 fclose(objfile);
|
|
1544 return 0;
|
|
1545 }
|
|
1546
|