This source file includes following definitions.
- patch_t
- TAILQ_HEAD
- usage
- back_patch
- output_code
- dump_scope
- emit_patch
- output_listing
- check_patch
- stop
- seq_alloc
- cs_alloc
- scope_alloc
- process_scope
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <sys/cdefs.h>
46 #include <sys/types.h>
47 #include <sys/mman.h>
48
49 #include <ctype.h>
50 #include <inttypes.h>
51 #include <regex.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <sysexits.h>
56 #include <unistd.h>
57
58 #if linux
59 #include <endian.h>
60 #else
61 #include <machine/endian.h>
62 #endif
63
64 #include "aicasm.h"
65 #include "aicasm_symbol.h"
66 #include "aicasm_insformat.h"
67
68 typedef struct patch {
69 TAILQ_ENTRY(patch) links;
70 int patch_func;
71 u_int begin;
72 u_int skip_instr;
73 u_int skip_patch;
74 } patch_t;
75
76 TAILQ_HEAD(patch_list, patch) patches;
77
78 static void usage(void);
79 static void back_patch(void);
80 static void output_code(void);
81 static void output_listing(char *ifilename);
82 static void dump_scope(scope_t *scope);
83 static void emit_patch(scope_t *scope, int patch);
84 static int check_patch(patch_t **start_patch, int start_instr,
85 int *skip_addr, int *func_vals);
86
87 struct path_list search_path;
88 int includes_search_curdir;
89 char *appname;
90 char *stock_include_file;
91 FILE *ofile;
92 char *ofilename;
93 char *regfilename;
94 FILE *regfile;
95 char *listfilename;
96 FILE *listfile;
97 char *regdiagfilename;
98 FILE *regdiagfile;
99 int src_mode;
100 int dst_mode;
101
102 static TAILQ_HEAD(,instruction) seq_program;
103 struct cs_tailq cs_tailq;
104 struct scope_list scope_stack;
105 symlist_t patch_functions;
106
107 #if DEBUG
108 extern int yy_flex_debug;
109 extern int mm_flex_debug;
110 extern int yydebug;
111 extern int mmdebug;
112 #endif
113 extern FILE *yyin;
114 extern int yyparse(void);
115
116 int main(int argc, char *argv[]);
117
118 int
119 main(int argc, char *argv[])
120 {
121 extern char *optarg;
122 extern int optind;
123 int ch;
124 int retval;
125 char *inputfilename;
126 scope_t *sentinal;
127
128 TAILQ_INIT(&patches);
129 SLIST_INIT(&search_path);
130 TAILQ_INIT(&seq_program);
131 TAILQ_INIT(&cs_tailq);
132 SLIST_INIT(&scope_stack);
133
134
135 sentinal = scope_alloc();
136 sentinal->type = SCOPE_ROOT;
137
138 includes_search_curdir = 1;
139 appname = *argv;
140 regfile = NULL;
141 listfile = NULL;
142 #if DEBUG
143 yy_flex_debug = 0;
144 mm_flex_debug = 0;
145 yydebug = 0;
146 mmdebug = 0;
147 #endif
148 while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:X")) != -1) {
149 switch(ch) {
150 case 'd':
151 #if DEBUG
152 if (strcmp(optarg, "s") == 0) {
153 yy_flex_debug = 1;
154 mm_flex_debug = 1;
155 } else if (strcmp(optarg, "p") == 0) {
156 yydebug = 1;
157 mmdebug = 1;
158 } else {
159 fprintf(stderr, "%s: -d Requires either an "
160 "'s' or 'p' argument\n", appname);
161 usage();
162 }
163 #else
164 stop("-d: Assembler not built with debugging "
165 "information", EX_SOFTWARE);
166 #endif
167 break;
168 case 'i':
169 stock_include_file = optarg;
170 break;
171 case 'l':
172
173 if ((listfile = fopen(optarg, "w")) == NULL) {
174 perror(optarg);
175 stop(NULL, EX_CANTCREAT);
176 }
177 listfilename = optarg;
178 break;
179 case 'n':
180
181 if (strcmp(optarg, "ostdinc")) {
182 fprintf(stderr, "%s: Unknown option -%c%s\n",
183 appname, ch, optarg);
184 usage();
185
186 }
187 break;
188 case 'o':
189 if ((ofile = fopen(optarg, "w")) == NULL) {
190 perror(optarg);
191 stop(NULL, EX_CANTCREAT);
192 }
193 ofilename = optarg;
194 break;
195 case 'p':
196
197 if ((regdiagfile = fopen(optarg, "w")) == NULL) {
198 perror(optarg);
199 stop(NULL, EX_CANTCREAT);
200 }
201 regdiagfilename = optarg;
202 break;
203 case 'r':
204 if ((regfile = fopen(optarg, "w")) == NULL) {
205 perror(optarg);
206 stop(NULL, EX_CANTCREAT);
207 }
208 regfilename = optarg;
209 break;
210 case 'I':
211 {
212 path_entry_t include_dir;
213
214 if (strcmp(optarg, "-") == 0) {
215 if (includes_search_curdir == 0) {
216 fprintf(stderr, "%s: Warning - '-I-' "
217 "specified multiple "
218 "times\n", appname);
219 }
220 includes_search_curdir = 0;
221 for (include_dir = SLIST_FIRST(&search_path);
222 include_dir != NULL;
223 include_dir = SLIST_NEXT(include_dir,
224 links))
225
226
227
228
229
230 include_dir->quoted_includes_only = 1;
231 } else {
232 include_dir =
233 (path_entry_t)malloc(sizeof(*include_dir));
234 if (include_dir == NULL) {
235 perror(optarg);
236 stop(NULL, EX_OSERR);
237 }
238 include_dir->directory = strdup(optarg);
239 if (include_dir->directory == NULL) {
240 perror(optarg);
241 stop(NULL, EX_OSERR);
242 }
243 include_dir->quoted_includes_only = 0;
244 SLIST_INSERT_HEAD(&search_path, include_dir,
245 links);
246 }
247 break;
248 }
249 case 'X':
250
251 break;
252 case '?':
253 default:
254 usage();
255
256 }
257 }
258 argc -= optind;
259 argv += optind;
260
261 if (argc != 1) {
262 fprintf(stderr, "%s: No input file specifiled\n", appname);
263 usage();
264
265 }
266
267 if (regdiagfile != NULL
268 && (regfile == NULL || stock_include_file == NULL)) {
269 fprintf(stderr,
270 "%s: The -p option requires the -r and -i options.\n",
271 appname);
272 usage();
273
274 }
275 symtable_open();
276 inputfilename = *argv;
277 include_file(*argv, SOURCE_FILE);
278 retval = yyparse();
279 if (retval == 0) {
280 if (SLIST_FIRST(&scope_stack) == NULL
281 || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
282 stop("Unterminated conditional expression", EX_DATAERR);
283
284 }
285
286
287 process_scope(SLIST_FIRST(&scope_stack));
288
289
290
291
292
293
294 dump_scope(SLIST_FIRST(&scope_stack));
295
296
297 back_patch();
298
299 if (ofile != NULL)
300 output_code();
301 if (regfile != NULL)
302 symtable_dump(regfile, regdiagfile);
303 if (listfile != NULL)
304 output_listing(inputfilename);
305 }
306
307 stop(NULL, 0);
308
309 return (0);
310 }
311
312 static void
313 usage()
314 {
315
316 (void)fprintf(stderr,
317 "usage: %-16s [-nostdinc|-X] [-I-] [-I directory] [-o output_file]\n"
318 " [-r register_output_file [-p register_diag_file -i includefile]]\n"
319 " [-l program_list_file]\n"
320 " input_file\n", appname);
321 exit(EX_USAGE);
322 }
323
324 static void
325 back_patch()
326 {
327 struct instruction *cur_instr;
328
329 for (cur_instr = TAILQ_FIRST(&seq_program);
330 cur_instr != NULL;
331 cur_instr = TAILQ_NEXT(cur_instr, links)) {
332 if (cur_instr->patch_label != NULL) {
333 struct ins_format3 *f3_instr;
334 u_int address;
335
336 if (cur_instr->patch_label->type != LABEL) {
337 char buf[255];
338
339 snprintf(buf, sizeof(buf),
340 "Undefined label %s",
341 cur_instr->patch_label->name);
342 stop(buf, EX_DATAERR);
343
344 }
345 f3_instr = &cur_instr->format.format3;
346 address = f3_instr->address;
347 address += cur_instr->patch_label->info.linfo->address;
348 f3_instr->address = address;
349 }
350 }
351 }
352
353 static void
354 output_code()
355 {
356 struct instruction *cur_instr;
357 patch_t *cur_patch;
358 critical_section_t *cs;
359 symbol_node_t *cur_node;
360 int instrcount;
361
362 instrcount = 0;
363 fprintf(ofile,
364 "/*\n"
365 " * DO NOT EDIT - This file is automatically generated\n"
366 " * from the following source files:\n"
367 " *\n"
368 "%s */\n", versions);
369
370 fprintf(ofile, "static const uint8_t seqprog[] = {\n");
371 for (cur_instr = TAILQ_FIRST(&seq_program);
372 cur_instr != NULL;
373 cur_instr = TAILQ_NEXT(cur_instr, links)) {
374
375 fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
376 cur_instr == TAILQ_FIRST(&seq_program) ? "" : ",\n",
377 #if BYTE_ORDER == LITTLE_ENDIAN
378 cur_instr->format.bytes[0],
379 cur_instr->format.bytes[1],
380 cur_instr->format.bytes[2],
381 cur_instr->format.bytes[3]);
382 #else
383 cur_instr->format.bytes[3],
384 cur_instr->format.bytes[2],
385 cur_instr->format.bytes[1],
386 cur_instr->format.bytes[0]);
387 #endif
388 instrcount++;
389 }
390 fprintf(ofile, "\n};\n\n");
391
392 if (patch_arg_list == NULL)
393 stop("Patch argument list not defined",
394 EX_DATAERR);
395
396
397
398
399 fprintf(ofile,
400 "typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
401
402 for (cur_node = SLIST_FIRST(&patch_functions);
403 cur_node != NULL;
404 cur_node = SLIST_NEXT(cur_node,links)) {
405 fprintf(ofile,
406 "static %spatch_func_t %spatch%d_func;\n"
407 "\n"
408 "static int\n"
409 "%spatch%d_func(%s)\n"
410 "{\n"
411 " return (%s);\n"
412 "}\n\n",
413 prefix,
414 prefix,
415 cur_node->symbol->info.condinfo->func_num,
416 prefix,
417 cur_node->symbol->info.condinfo->func_num,
418 patch_arg_list,
419 cur_node->symbol->name);
420 }
421
422 fprintf(ofile,
423 "static const struct patch {\n"
424 " %spatch_func_t *patch_func;\n"
425 " uint32_t begin :10,\n"
426 " skip_instr :10,\n"
427 " skip_patch :12;\n"
428 "} patches[] = {\n", prefix);
429
430 for (cur_patch = TAILQ_FIRST(&patches);
431 cur_patch != NULL;
432 cur_patch = TAILQ_NEXT(cur_patch,links)) {
433 fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
434 cur_patch == TAILQ_FIRST(&patches) ? "" : ",\n",
435 prefix,
436 cur_patch->patch_func, cur_patch->begin,
437 cur_patch->skip_instr, cur_patch->skip_patch);
438 }
439
440 fprintf(ofile, "\n};\n\n");
441
442 fprintf(ofile,
443 "static const struct cs {\n"
444 " uint16_t begin;\n"
445 " uint16_t end;\n"
446 "} critical_sections[] = {\n");
447
448 for (cs = TAILQ_FIRST(&cs_tailq);
449 cs != NULL;
450 cs = TAILQ_NEXT(cs, links)) {
451 fprintf(ofile, "%s\t{ %d, %d }",
452 cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
453 cs->begin_addr, cs->end_addr);
454 }
455
456 fprintf(ofile, "\n};\n\n");
457
458 fprintf(ofile,
459 "#define NUM_CRITICAL_SECTIONS (sizeof(critical_sections) / sizeof(*critical_sections))\n");
460
461 fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
462 }
463
464 static void
465 dump_scope(scope_t *scope)
466 {
467 scope_t *cur_scope;
468
469
470
471
472 emit_patch(scope, 0);
473
474
475
476
477 cur_scope = TAILQ_FIRST(&scope->inner_scope);
478
479 while (cur_scope != NULL) {
480
481 dump_scope(cur_scope);
482
483 cur_scope = TAILQ_NEXT(cur_scope, scope_links);
484 }
485
486
487
488
489 emit_patch(scope, 1);
490 }
491
492 void
493 emit_patch(scope_t *scope, int patch)
494 {
495 patch_info_t *pinfo;
496 patch_t *new_patch;
497
498 pinfo = &scope->patches[patch];
499
500 if (pinfo->skip_instr == 0)
501
502 return;
503
504 new_patch = (patch_t *)malloc(sizeof(*new_patch));
505
506 if (new_patch == NULL)
507 stop("Could not malloc patch structure", EX_OSERR);
508
509 memset(new_patch, 0, sizeof(*new_patch));
510
511 if (patch == 0) {
512 new_patch->patch_func = scope->func_num;
513 new_patch->begin = scope->begin_addr;
514 } else {
515 new_patch->patch_func = 0;
516 new_patch->begin = scope->end_addr;
517 }
518 new_patch->skip_instr = pinfo->skip_instr;
519 new_patch->skip_patch = pinfo->skip_patch;
520 TAILQ_INSERT_TAIL(&patches, new_patch, links);
521 }
522
523 void
524 output_listing(char *ifilename)
525 {
526 char buf[1024];
527 FILE *ifile;
528 struct instruction *cur_instr;
529 patch_t *cur_patch;
530 symbol_node_t *cur_func;
531 int *func_values;
532 int instrcount;
533 int instrptr;
534 int line;
535 int func_count;
536 int skip_addr;
537
538 instrcount = 0;
539 instrptr = 0;
540 line = 1;
541 skip_addr = 0;
542 if ((ifile = fopen(ifilename, "r")) == NULL) {
543 perror(ifilename);
544 stop(NULL, EX_DATAERR);
545 }
546
547
548
549
550 for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
551 cur_func != NULL;
552 cur_func = SLIST_NEXT(cur_func, links))
553 func_count++;
554
555 func_values = NULL;
556 if (func_count != 0) {
557 func_values = (int *)malloc(func_count * sizeof(int));
558
559 if (func_values == NULL)
560 stop("Could not malloc", EX_OSERR);
561
562 func_values[0] = 0;
563 func_count--;
564
565
566
567
568
569
570
571 for (cur_func = SLIST_FIRST(&patch_functions);
572 cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
573 cur_func = SLIST_NEXT(cur_func, links), func_count--) {
574 int input;
575
576 fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
577 fprintf(stdout,
578 "Enter the return value for "
579 "this expression[T/F]:");
580
581 while (1) {
582
583 input = getchar();
584 input = toupper(input);
585
586 if (input == 'T') {
587 func_values[func_count] = 1;
588 break;
589 } else if (input == 'F') {
590 func_values[func_count] = 0;
591 break;
592 }
593 }
594 if (isatty(fileno(stdin)) == 0)
595 putchar(input);
596 }
597 fprintf(stdout, "\nThanks!\n");
598 }
599
600
601 cur_patch = TAILQ_FIRST(&patches);
602 for (cur_instr = TAILQ_FIRST(&seq_program);
603 cur_instr != NULL;
604 cur_instr = TAILQ_NEXT(cur_instr, links), instrcount++) {
605
606 if (check_patch(&cur_patch, instrcount,
607 &skip_addr, func_values) == 0) {
608
609
610
611 continue;
612 }
613
614 while (line < cur_instr->srcline) {
615 fgets(buf, sizeof(buf), ifile);
616 fprintf(listfile, " \t%s", buf);
617 line++;
618 }
619 fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
620 #if BYTE_ORDER == LITTLE_ENDIAN
621 cur_instr->format.bytes[0],
622 cur_instr->format.bytes[1],
623 cur_instr->format.bytes[2],
624 cur_instr->format.bytes[3]);
625 #else
626 cur_instr->format.bytes[3],
627 cur_instr->format.bytes[2],
628 cur_instr->format.bytes[1],
629 cur_instr->format.bytes[0]);
630 #endif
631
632
633
634
635
636 if (line == cur_instr->srcline) {
637 fgets(buf, sizeof(buf), ifile);
638 fprintf(listfile, "\t%s", buf);
639 line++;
640 } else {
641 fprintf(listfile, "\n");
642 }
643 instrptr++;
644 }
645
646 while(fgets(buf, sizeof(buf), ifile) != NULL)
647 fprintf(listfile, " %s", buf);
648
649 fclose(ifile);
650 }
651
652 static int
653 check_patch(patch_t **start_patch, int start_instr,
654 int *skip_addr, int *func_vals)
655 {
656 patch_t *cur_patch;
657
658 cur_patch = *start_patch;
659
660 while (cur_patch != NULL && start_instr == cur_patch->begin) {
661 if (func_vals[cur_patch->patch_func] == 0) {
662 int skip;
663
664
665 *skip_addr = start_instr + cur_patch->skip_instr;
666 for (skip = cur_patch->skip_patch;
667 skip > 0 && cur_patch != NULL;
668 skip--)
669 cur_patch = TAILQ_NEXT(cur_patch, links);
670 } else {
671
672
673
674
675 cur_patch = TAILQ_NEXT(cur_patch, links);
676 }
677 }
678
679 *start_patch = cur_patch;
680 if (start_instr < *skip_addr)
681
682 return (0);
683
684 return (1);
685 }
686
687
688
689
690
691 void
692 stop(const char *string, int err_code)
693 {
694 if (string != NULL) {
695 fprintf(stderr, "%s: ", appname);
696 if (yyfilename != NULL) {
697 fprintf(stderr, "Stopped at file %s, line %d - ",
698 yyfilename, yylineno);
699 }
700 fprintf(stderr, "%s\n", string);
701 }
702
703 if (ofile != NULL) {
704 fclose(ofile);
705 if (err_code != 0) {
706 fprintf(stderr, "%s: Removing %s due to error\n",
707 appname, ofilename);
708 unlink(ofilename);
709 }
710 }
711
712 if (regfile != NULL) {
713 fclose(regfile);
714 if (err_code != 0) {
715 fprintf(stderr, "%s: Removing %s due to error\n",
716 appname, regfilename);
717 unlink(regfilename);
718 }
719 }
720
721 if (listfile != NULL) {
722 fclose(listfile);
723 if (err_code != 0) {
724 fprintf(stderr, "%s: Removing %s due to error\n",
725 appname, listfilename);
726 unlink(listfilename);
727 }
728 }
729
730 symlist_free(&patch_functions);
731 symtable_close();
732
733 exit(err_code);
734 }
735
736 struct instruction *
737 seq_alloc()
738 {
739 struct instruction *new_instr;
740
741 new_instr = (struct instruction *)malloc(sizeof(struct instruction));
742 if (new_instr == NULL)
743 stop("Unable to malloc instruction object", EX_SOFTWARE);
744 memset(new_instr, 0, sizeof(*new_instr));
745 TAILQ_INSERT_TAIL(&seq_program, new_instr, links);
746 new_instr->srcline = yylineno;
747 return new_instr;
748 }
749
750 critical_section_t *
751 cs_alloc()
752 {
753 critical_section_t *new_cs;
754
755 new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
756 if (new_cs == NULL)
757 stop("Unable to malloc critical_section object", EX_SOFTWARE);
758 memset(new_cs, 0, sizeof(*new_cs));
759
760 TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
761 return new_cs;
762 }
763
764 scope_t *
765 scope_alloc()
766 {
767 scope_t *new_scope;
768
769 new_scope = (scope_t *)malloc(sizeof(scope_t));
770 if (new_scope == NULL)
771 stop("Unable to malloc scope object", EX_SOFTWARE);
772 memset(new_scope, 0, sizeof(*new_scope));
773 TAILQ_INIT(&new_scope->inner_scope);
774
775 if (SLIST_FIRST(&scope_stack) != NULL) {
776 TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
777 new_scope, scope_links);
778 }
779
780 SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
781 return new_scope;
782 }
783
784 void
785 process_scope(scope_t *scope)
786 {
787
788
789
790
791
792 scope_t *cur_scope;
793 u_int skip_patch_count;
794 u_int skip_instr_count;
795
796 cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
797 skip_patch_count = 0;
798 skip_instr_count = 0;
799 while (cur_scope != NULL) {
800 u_int patch0_patch_skip;
801
802 patch0_patch_skip = 0;
803 switch (cur_scope->type) {
804 case SCOPE_IF:
805 case SCOPE_ELSE_IF:
806 if (skip_instr_count != 0) {
807
808 patch0_patch_skip++;
809 cur_scope->patches[1].skip_patch =
810 skip_patch_count + 1;
811 cur_scope->patches[1].skip_instr =
812 skip_instr_count;
813 }
814
815
816 patch0_patch_skip++;
817
818
819 patch0_patch_skip += cur_scope->inner_scope_patches;
820
821 cur_scope->patches[0].skip_patch = patch0_patch_skip;
822 cur_scope->patches[0].skip_instr =
823 cur_scope->end_addr - cur_scope->begin_addr;
824
825 skip_instr_count += cur_scope->patches[0].skip_instr;
826
827 skip_patch_count += patch0_patch_skip;
828 if (cur_scope->type == SCOPE_IF) {
829 scope->inner_scope_patches += skip_patch_count;
830 skip_patch_count = 0;
831 skip_instr_count = 0;
832 }
833 break;
834 case SCOPE_ELSE:
835
836 skip_patch_count += cur_scope->inner_scope_patches;
837
838 skip_instr_count += cur_scope->end_addr
839 - cur_scope->begin_addr;
840 break;
841 case SCOPE_ROOT:
842 stop("Unexpected scope type encountered", EX_SOFTWARE);
843
844 }
845
846 cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
847 }
848 }