[BACK]Return to aicasm.c CVS log [TXT][DIR] Up to [local] / sys / dev / microcode / aic7xxx

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