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