Annotation of sys/dev/microcode/aic7xxx/aicasm.c, Revision 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