This source file includes following definitions.
- error
- Malloc
- Realloc
- Strdup
- define
- lookup
- patch
- backpatch
- output
- getl
- eval_operand
- eval_sdi
- eval_addr
- crack
- assemble
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 static char id[] = "$Id: aic7xxx_asm.c,v 2.1 1995/08/23 04:31:40 deang Exp $";
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36
37 #define MEMORY 448
38 #define MAXLINE 1024
39 #define MAXTOKEN 32
40 #define ADOTOUT "a.out"
41 #define NOVALUE -1
42
43
44
45
46 #define R_SINDEX 0x65
47 #define R_ALLONES 0x69
48 #define R_ALLZEROS 0x6a
49 #define R_NONE 0x6a
50
51 int debug;
52 int lineno, LC;
53 char *filename;
54 FILE *ifp, *ofp;
55 unsigned char M[MEMORY][4];
56
57 void
58 error(const char *s)
59 {
60 fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
61 exit(EXIT_FAILURE);
62 }
63
64 void *
65 Malloc(size_t size)
66 {
67 void *p = malloc(size);
68 if (!p)
69 error("out of memory");
70 return(p);
71 }
72
73 void *
74 Realloc(void *ptr, size_t size)
75 {
76 void *p = realloc(ptr, size);
77 if (!p)
78 error("out of memory");
79 return(p);
80 }
81
82 char *
83 Strdup(char *s)
84 {
85 char *p = (char *)Malloc(strlen(s) + 1);
86 strcpy(p, s);
87 return(p);
88 }
89
90 typedef struct sym_t {
91 struct sym_t *next;
92 char *name;
93 int value;
94 int npatch;
95 int *patch;
96 } sym_t;
97
98 sym_t *head;
99
100 void
101 define(char *name, int value)
102 {
103 sym_t *p, *q;
104
105 for (p = head, q = (sym_t *)&head; p; p = p->next) {
106 if (!strcmp(p->name, name))
107 error("redefined symbol");
108 q = p;
109 }
110
111 p = q->next = (sym_t *)Malloc(sizeof(sym_t));
112 p->next = NULL;
113 p->name = Strdup(name);
114 p->value = value;
115 p->npatch = 0;
116 p->patch = NULL;
117
118 if (debug) {
119 fprintf(stderr, "\"%s\" ", p->name);
120 if (p->value != NOVALUE)
121 fprintf(stderr, "defined as 0x%x\n", p->value);
122 else
123 fprintf(stderr, "undefined\n");
124 }
125 }
126
127 sym_t *
128 lookup(char *name)
129 {
130 sym_t *p;
131
132 for (p = head; p; p = p->next)
133 if (!strcmp(p->name, name))
134 return(p);
135 return(NULL);
136 }
137
138 void
139 patch(sym_t *p, int location)
140 {
141 p->npatch += 1;
142 p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
143
144 p->patch[p->npatch - 1] = location;
145 }
146
147 void backpatch(void)
148 {
149 int i;
150 sym_t *p;
151
152 for (p = head; p; p = p->next) {
153
154 if (p->value == NOVALUE) {
155 fprintf(stderr,
156 "%s: undefined symbol \"%s\"\n",
157 filename, p->name);
158 exit(EXIT_FAILURE);
159 }
160
161 if (p->npatch) {
162 if (debug)
163 fprintf(stderr,
164 "\"%s\" (0x%x) patched at",
165 p->name, p->value);
166
167 for (i = 0; i < p->npatch; i++) {
168 M[p->patch[i]][0] &= ~1;
169 M[p->patch[i]][0] |= ((p->value >> 8) & 1);
170 M[p->patch[i]][1] = p->value & 0xff;
171
172 if (debug)
173 fprintf(stderr, " 0x%x", p->patch[i]);
174 }
175
176 if (debug)
177 fputc('\n', stderr);
178 }
179 }
180 }
181
182
183
184
185
186 void
187 output(FILE *fp)
188 {
189 int i;
190
191 for (i = 0; i < LC; i++)
192 fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
193 M[i][3],
194 M[i][2],
195 M[i][1],
196 M[i][0]);
197 printf("%d out of %d instructions used.\n", LC, MEMORY);
198 }
199
200 char **
201 getl(int *n)
202 {
203 int i;
204 char *p, *quote;
205 static char buf[MAXLINE];
206 static char *a[MAXTOKEN];
207
208 i = 0;
209
210 while (fgets(buf, sizeof(buf), ifp)) {
211
212 lineno += 1;
213
214 if (buf[strlen(buf)-1] != '\n')
215 error("line too long");
216
217 p = strchr(buf, '#');
218 if (p)
219 *p = '\0';
220 p = buf;
221 rescan:
222 quote = strchr(p, '\"');
223 if (quote)
224 *quote = '\0';
225 for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
226 if (i < MAXTOKEN-1)
227 a[i++] = p;
228 else
229 error("too many tokens");
230 if (quote) {
231 quote++;
232 p = strchr(quote, '\"');
233 if (!p)
234 error("unterminated string constant");
235 else if (i < MAXTOKEN-1) {
236 a[i++] = quote;
237 *p = '\0';
238 p++;
239 }
240 else
241 error("too many tokens");
242 goto rescan;
243 }
244 if (i) {
245 *n = i;
246 return(a);
247 }
248 }
249 return(NULL);
250 }
251
252 #define A 0x8000
253 #define I 0x4000
254 #define SL 0x2000
255 #define SR 0x1000
256 #define RL 0x0800
257 #define RR 0x0400
258 #define LO 0x8000
259 #define LA 0x4000
260 #define LX 0x2000
261 #define NA -1
262
263 struct {
264 const char *name;
265 int n;
266 unsigned int op;
267 unsigned int dest;
268 unsigned int src;
269 unsigned int imm;
270 unsigned int addr;
271 int fmt;
272 } instr[] = {
273
274
275
276 { "mov", 3, 1, 1, 2, I|0xff, NA, 1 },
277 { "mov", 4, LO|2, NA, 1, I|0, 3, 3 },
278 { "mvi", 3, 0, 1, I|R_ALLZEROS, A|2, NA, 1 },
279 { "mvi", 4, LO|2, NA, I|R_ALLZEROS, 1, 3, 3 },
280 { "not", 2, 2, 1, 1, I|0xff, NA, 1 },
281 { "and", 3, 1, 1, 1, A|2, NA, 1 },
282 { "and", 4, 1, 1, 3, A|2, NA, 1 },
283 { "or", 3, 0, 1, 1, A|2, NA, 1 },
284 { "or", 4, 0, 1, 3, A|2, NA, 1 },
285 { "or", 5, LO|3, NA, 1, 2, 4, 3 },
286 { "xor", 3, 2, 1, 1, A|2, NA, 1 },
287 { "xor", 4, 2, 1, 3, A|2, NA, 1 },
288 { "nop", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
289 { "inc", 2, 3, 1, 1, I|1, NA, 1 },
290 { "inc", 3, 3, 1, 2, I|1, NA, 1 },
291 { "dec", 2, 3, 1, 1, I|0xff, NA, 1 },
292 { "dec", 3, 3, 1, 2, I|0xff, NA, 1 },
293 { "jmp", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
294 { "jc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
295 { "jnc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
296 { "call", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
297 { "test", 5, LA|3, NA, 1, A|2, 4, 3 },
298 { "cmp", 5, LX|3, NA, 1, A|2, 4, 3 },
299 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
300 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
301 { "clc", 1, 3, I|R_NONE, I|R_ALLZEROS, I|1, NA, 1 },
302 { "clc", 4, 3, 2, I|R_ALLZEROS, A|3, NA, 1 },
303 { "stc", 2, 3, 1, I|R_ALLONES, I|1, NA, 1 },
304 { "add", 3, 3, 1, 1, A|2, NA, 1 },
305 { "add", 4, 3, 1, 3, A|2, NA, 1 },
306 { "adc", 3, 4, 1, 1, A|2, NA, 1 },
307 { "adc", 4, 4, 1, 3, A|2, NA, 1 },
308 { "shl", 3, 5, 1, 1, SL|2, NA, 2 },
309 { "shl", 4, 5, 1, 2, SL|3, NA, 2 },
310 { "shr", 3, 5, 1, 1, SR|2, NA, 2 },
311 { "shr", 4, 5, 1, 2, SR|3, NA, 2 },
312 { "rol", 3, 5, 1, 1, RL|2, NA, 2 },
313 { "rol", 4, 5, 1, 2, RL|3, NA, 2 },
314 { "ror", 3, 5, 1, 1, RR|2, NA, 2 },
315 { "ror", 4, 5, 1, 2, RR|3, NA, 2 },
316
317
318
319 { "clr", 2, 1, 1, I|R_ALLZEROS, I|0xff, NA, 1 },
320 { 0, 0, 0, 0, 0, 0, 0, 0 }
321 };
322
323 int
324 eval_operand(char **a, int spec)
325 {
326 int i;
327 unsigned int want = spec & (LO|LA|LX);
328
329 static struct {
330 unsigned int what;
331 const char *name;
332 int value;
333 } jmptab[] = {
334 { LO, "jmp", 8 },
335 { LO, "jc", 9 },
336 { LO, "jnc", 10 },
337 { LO, "call", 11 },
338 { LA, "jz", 15 },
339 { LA, "jnz", 13 },
340 { LX, "je", 14 },
341 { LX, "jne", 12 },
342 };
343
344 spec &= ~(LO|LA|LX);
345
346 for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
347 if (jmptab[i].what == want &&
348 !strcmp(jmptab[i].name, a[spec]))
349 {
350 return(jmptab[i].value);
351 }
352
353 if (want)
354 error("invalid jump");
355
356 return(spec);
357 }
358
359 int
360 eval_sdi(char **a, int spec)
361 {
362 sym_t *p;
363 unsigned val;
364
365 if (spec == NA)
366 return(NA);
367
368 switch (spec & (A|I|SL|SR|RL|RR)) {
369 case SL:
370 case SR:
371 case RL:
372 case RR:
373 if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
374 val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
375 else {
376 p = lookup(a[spec &~ (SL|SR|RL|RR)]);
377 if (!p)
378 error("undefined symbol used");
379 val = p->value;
380 }
381
382 switch (spec & (SL|SR|RL|RR)) {
383 case SL:
384 if (val > 7)
385 return(0xf0);
386 return(((val % 8) << 4) |
387 (val % 8));
388 case SR:
389 if (val > 7)
390 return(0xf0);
391 return(((val % 8) << 4) |
392 (1 << 3) |
393 ((8 - (val % 8)) % 8));
394 case RL:
395 return(val % 8);
396 case RR:
397 return((8 - (val % 8)) % 8);
398 }
399 case I:
400 return(spec &~ I);
401 case A:
402
403
404
405
406
407
408 spec &= ~A;
409 if (!strcmp("A", a[spec]))
410 return(0);
411 if (isdigit(*a[spec]) &&
412 strtol(a[spec], NULL, 0) == 0)
413 {
414 error("immediate value of zero selects accumulator");
415 }
416
417 case 0:
418 if (isdigit(*a[spec]))
419 return(strtol(a[spec], NULL, 0));
420 p = lookup(a[spec]);
421 if (p)
422 return(p->value);
423 error("undefined symbol used");
424 }
425
426 return(NA);
427 }
428
429 int
430 eval_addr(char **a, int spec)
431 {
432 sym_t *p;
433
434 if (spec == NA)
435 return(NA);
436 if (isdigit(*a[spec]))
437 return(strtol(a[spec], NULL, 0));
438
439 p = lookup(a[spec]);
440
441 if (p) {
442 if (p->value != NOVALUE)
443 return(p->value);
444 patch(p, LC);
445 } else {
446 define(a[spec], NOVALUE);
447 p = lookup(a[spec]);
448 patch(p, LC);
449 }
450
451 return(NA);
452 }
453
454 int
455 crack(char **a, int n)
456 {
457 int i;
458 int I_imm, I_addr;
459 int I_op, I_dest, I_src, I_ret;
460
461
462
463
464
465
466 I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
467 if (I_ret && n > 1)
468 n -= 1;
469
470 for (i = 0; instr[i].name; i++) {
471
472
473
474
475
476 if (!strcmp(instr[i].name, *a) && instr[i].n == n)
477 break;
478 }
479 if (!instr[i].name)
480 error("unknown opcode or wrong number of operands");
481
482 I_op = eval_operand(a, instr[i].op);
483 I_src = eval_sdi(a, instr[i].src);
484 I_imm = eval_sdi(a, instr[i].imm);
485 I_dest = eval_sdi(a, instr[i].dest);
486 I_addr = eval_addr(a, instr[i].addr);
487
488 if( LC >= MEMORY )
489 error("Memory exhausted!\n");
490
491 switch (instr[i].fmt) {
492 case 1:
493 case 2:
494 M[LC][0] = (I_op << 1) | I_ret;
495 M[LC][1] = I_dest;
496 M[LC][2] = I_src;
497 M[LC][3] = I_imm;
498 break;
499 case 3:
500 if (I_ret)
501 error("illegal use of \"ret\"");
502 M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
503 M[LC][1] = I_addr & 0xff;
504 M[LC][2] = I_src;
505 M[LC][3] = I_imm;
506 break;
507 }
508
509 return (1);
510 }
511
512 #undef SL
513 #undef SR
514 #undef RL
515 #undef RR
516 #undef LX
517 #undef LA
518 #undef LO
519 #undef I
520 #undef A
521
522 void
523 assemble(void)
524 {
525 int n;
526 char **a;
527 sym_t *p;
528
529 while ((a = getl(&n))) {
530
531 while (a[0][strlen(*a)-1] == ':') {
532 a[0][strlen(*a)-1] = '\0';
533 p = lookup(*a);
534 if (p)
535 p->value = LC;
536 else
537 define(*a, LC);
538 a += 1;
539 n -= 1;
540 }
541
542 if (!n)
543 continue;
544
545 if (n == 3 && !strcmp("VERSION", *a))
546 fprintf(ofp, "#define %s \"%s\"\n", a[1], a[2]);
547 else {
548 if (n == 3 && !strcmp("=", a[1]))
549 define(*a, strtol(a[2], NULL, 0));
550 else
551 LC += crack(a, n);
552 }
553 }
554
555 backpatch();
556 output(ofp);
557
558 if (debug)
559 output(stderr);
560 }
561
562 int
563 main(int argc, char **argv)
564 {
565 int c;
566
567 while ((c = getopt(argc, argv, "dho:vD")) != EOF) {
568 switch (c) {
569 case 'd':
570 debug = !0;
571 break;
572 case 'D':
573 {
574 char *p;
575 if ((p = strchr(optarg, '=')) != NULL) {
576 *p = '\0';
577 define(optarg, strtol(p + 1, NULL, 0));
578 }
579 else
580 define(optarg, 1);
581 break;
582 }
583 case 'o':
584 ofp = fopen(optarg, "w");
585 if (!ofp) {
586 perror(optarg);
587 exit(EXIT_FAILURE);
588 }
589 break;
590 case 'h':
591 printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
592 *argv);
593 exit(EXIT_SUCCESS);
594 break;
595 case 'v':
596 printf("%s\n", id);
597 exit(EXIT_SUCCESS);
598 break;
599 default:
600 exit(EXIT_FAILURE);
601 break;
602 }
603 }
604
605 if (argc - optind != 1) {
606 fprintf(stderr, "%s: must have one input file\n", *argv);
607 exit(EXIT_FAILURE);
608 }
609 filename = argv[optind];
610
611 ifp = fopen(filename, "r");
612 if (!ifp) {
613 perror(filename);
614 exit(EXIT_FAILURE);
615 }
616
617 if (!ofp) {
618 ofp = fopen(ADOTOUT, "w");
619 if (!ofp) {
620 perror(ADOTOUT);
621 exit(EXIT_FAILURE);
622 }
623 }
624
625 assemble();
626 exit(EXIT_SUCCESS);
627 }