Annotation of sys/dev/microcode/aic7xxx/aicasm.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aicasm.c,v 1.14 2005/10/04 23:46:14 krw Exp $ */
2: /*
3: * Aic7xxx SCSI host adapter firmware asssembler
4: *
5: * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
6: * Copyright (c) 2001, 2002 Adaptec Inc.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions, and the following disclaimer,
14: * without modification.
15: * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16: * substantially similar to the "NO WARRANTY" disclaimer below
17: * ("Disclaimer") and any redistribution must be conditioned upon
18: * including a substantially similar Disclaimer requirement for further
19: * binary redistribution.
20: * 3. Neither the names of the above-listed copyright holders nor the names
21: * of any contributors may be used to endorse or promote products derived
22: * from this software without specific prior written permission.
23: *
24: * Alternatively, this software may be distributed under the terms of the
25: * GNU General Public License ("GPL") version 2 as published by the Free
26: * Software Foundation.
27: *
28: * NO WARRANTY
29: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
32: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39: * POSSIBILITY OF SUCH DAMAGES.
40: *
41: * $Id: aicasm.c,v 1.14 2005/10/04 23:46:14 krw Exp $
42: *
43: * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm.c,v 1.37 2004/03/12 21:45:25 trhodes Exp $
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: /* Set Sentinal scope node */
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: /* Create a program listing */
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: /* Don't complain about the -nostdinc directrive */
181: if (strcmp(optarg, "ostdinc")) {
182: fprintf(stderr, "%s: Unknown option -%c%s\n",
183: appname, ch, optarg);
184: usage();
185: /* NOTREACHED */
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: /* Create Register Diagnostic "printing" Functions */
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: * All entries before a '-I-' only
227: * apply to includes specified with
228: * quotes instead of "<>".
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: /* icc version of -nostdinc */
251: break;
252: case '?':
253: default:
254: usage();
255: /* NOTREACHED */
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: /* NOTREACHED */
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: /* NOTREACHED */
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: /* NOTREACHED */
284: }
285:
286: /* Process outmost scope */
287: process_scope(SLIST_FIRST(&scope_stack));
288: /*
289: * Decend the tree of scopes and insert/emit
290: * patches as appropriate. We perform a depth first
291: * tranversal, recursively handling each scope.
292: */
293: /* start at the root scope */
294: dump_scope(SLIST_FIRST(&scope_stack));
295:
296: /* Patch up forward jump addresses */
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: /* NOTREACHED */
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: /* NOTREACHED */
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: * Output patch information. Patch functions first.
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: * Emit the first patch for this scope
471: */
472: emit_patch(scope, 0);
473:
474: /*
475: * Dump each scope within this one.
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: * Emit the second, closing, patch for this scope
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: /* No-Op patch */
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: * Determine which options to apply to this listing.
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; /* FALSE func */
563: func_count--;
564:
565: /*
566: * Ask the user to fill in the return values for
567: * the rest of the functions.
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: /* Now output the listing */
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: /* Don't count this instruction as it is in a patch
609: * that was removed.
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: * Macro expansions can cause several instructions
633: * to be output for a single source line. Only
634: * advance the line once in these cases.
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: /* Dump the remainder of the file */
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: /* Start rejecting code */
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: /* Accepted this patch. Advance to the next
672: * one and wait for our intruction pointer to
673: * hit this point.
674: */
675: cur_patch = TAILQ_NEXT(cur_patch, links);
676: }
677: }
678:
679: *start_patch = cur_patch;
680: if (start_instr < *skip_addr)
681: /* Still skipping */
682: return (0);
683:
684: return (1);
685: }
686:
687: /*
688: * Print out error information if appropriate, and clean up before
689: * terminating the program.
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: /* This patch is now the current scope */
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: * We are "leaving" this scope. We should now have
789: * enough information to process the lists of scopes
790: * we encapsulate.
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: /* Create a tail patch */
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: /* Count Head patch */
816: patch0_patch_skip++;
817:
818: /* Count any patches contained in our inner scope */
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: /* Count any patches contained in our innter scope */
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: /* NOTREACHED */
844: }
845:
846: cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
847: }
848: }
CVSweb