v2.4.2.1 -> v2.4.2.2
[opensuse:kernel.git] / drivers / scsi / aic7xxx / aicasm / aicasm.c
1 /*
2  * Aic7xxx SCSI host adapter firmware asssembler
3  *
4  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, and the following disclaimer,
12  *    without modification, immediately at the beginning of the file.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * Alternatively, this software may be distributed under the terms of the
17  * GNU Public License ("GPL").
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $Id: //depot/src/aic7xxx/aicasm/aicasm.c#6 $
32  *
33  * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm.c,v 1.29 2000/10/05 04:25:42 gibbs Exp $
34  */
35 #include <sys/types.h>
36 #include <sys/mman.h>
37
38 #include <ctype.h>
39 #include <inttypes.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sysexits.h>
44 #include <unistd.h>
45
46 #include "aicasm.h"
47 #include "aicasm_symbol.h"
48 #include "aicasm_insformat.h"
49
50 typedef struct patch {
51         STAILQ_ENTRY(patch) links;
52         int             patch_func;
53         u_int           begin;
54         u_int           skip_instr;
55         u_int           skip_patch;
56 } patch_t;
57
58 STAILQ_HEAD(patch_list, patch) patches;
59
60 static void usage(void);
61 static void back_patch(void);
62 static void output_code(void);
63 static void output_listing(char *ifilename);
64 static void dump_scope(scope_t *scope);
65 static void emit_patch(scope_t *scope, int patch);
66 static int check_patch(patch_t **start_patch, int start_instr,
67                        int *skip_addr, int *func_vals);
68
69 struct path_list search_path;
70 int includes_search_curdir;
71 char *appname;
72 FILE *ofile;
73 char *ofilename;
74 char *regfilename;
75 FILE *regfile;
76 char *listfilename;
77 FILE *listfile;
78
79 static STAILQ_HEAD(,instruction) seq_program;
80 struct cs_tailq cs_tailq;
81 struct scope_list scope_stack;
82 symlist_t patch_functions;
83
84 #if DEBUG
85 extern int yy_flex_debug;
86 extern int yydebug;
87 #endif
88 extern FILE *yyin;
89 extern int yyparse(void);
90
91 int main(int argc, char *argv[]);
92
93 int
94 main(int argc, char *argv[])
95 {
96         extern char *optarg;
97         extern int optind;
98         int  ch;
99         int  retval;
100         char *inputfilename;
101         scope_t *sentinal;
102
103         STAILQ_INIT(&patches);
104         SLIST_INIT(&search_path);
105         STAILQ_INIT(&seq_program);
106         TAILQ_INIT(&cs_tailq);
107         SLIST_INIT(&scope_stack);
108
109         /* Set Sentinal scope node */
110         sentinal = scope_alloc();
111         sentinal->type = SCOPE_ROOT;
112         
113         includes_search_curdir = 1;
114         appname = *argv;
115         regfile = NULL;
116         listfile = NULL;
117 #if DEBUG
118         yy_flex_debug = 0;
119         yydebug = 0;
120 #endif
121         while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != -1) {
122                 switch(ch) {
123                 case 'd':
124 #if DEBUG
125                         if (strcmp(optarg, "s") == 0) {
126                                 yy_flex_debug = 1;
127                         } else if (strcmp(optarg, "p") == 0) {
128                                 yydebug = 1;
129                         } else {
130                                 fprintf(stderr, "%s: -d Requires either an "
131                                         "'s' or 'p' argument\n", appname);
132                                 usage();
133                         }
134 #else
135                         stop("-d: Assembler not built with debugging "
136                              "information", EX_SOFTWARE);
137 #endif
138                         break;
139                 case 'l':
140                         /* Create a program listing */
141                         if ((listfile = fopen(optarg, "w")) == NULL) {
142                                 perror(optarg);
143                                 stop(NULL, EX_CANTCREAT);
144                         }
145                         listfilename = optarg;
146                         break;
147                 case 'n':
148                         /* Don't complain about the -nostdinc directrive */
149                         if (strcmp(optarg, "ostdinc")) {
150                                 fprintf(stderr, "%s: Unknown option -%c%s\n",
151                                         appname, ch, optarg);
152                                 usage();
153                                 /* NOTREACHED */
154                         }
155                         break;
156                 case 'o':
157                         if ((ofile = fopen(optarg, "w")) == NULL) {
158                                 perror(optarg);
159                                 stop(NULL, EX_CANTCREAT);
160                         }
161                         ofilename = optarg;
162                         break;
163                 case 'r':
164                         if ((regfile = fopen(optarg, "w")) == NULL) {
165                                 perror(optarg);
166                                 stop(NULL, EX_CANTCREAT);
167                         }
168                         regfilename = optarg;
169                         break;
170                 case 'I':
171                 {
172                         path_entry_t include_dir;
173
174                         if (strcmp(optarg, "-") == 0) {
175                                 if (includes_search_curdir == 0) {
176                                         fprintf(stderr, "%s: Warning - '-I-' "
177                                                         "specified multiple "
178                                                         "times\n", appname);
179                                 }
180                                 includes_search_curdir = 0;
181                                 for (include_dir = search_path.slh_first;
182                                      include_dir != NULL;
183                                      include_dir = include_dir->links.sle_next)
184                                         /*
185                                          * All entries before a '-I-' only
186                                          * apply to includes specified with
187                                          * quotes instead of "<>".
188                                          */
189                                         include_dir->quoted_includes_only = 1;
190                         } else {
191                                 include_dir =
192                                     (path_entry_t)malloc(sizeof(*include_dir));
193                                 if (include_dir == NULL) {
194                                         perror(optarg);
195                                         stop(NULL, EX_OSERR);
196                                 }
197                                 include_dir->directory = strdup(optarg);
198                                 if (include_dir->directory == NULL) {
199                                         perror(optarg);
200                                         stop(NULL, EX_OSERR);
201                                 }
202                                 include_dir->quoted_includes_only = 0;
203                                 SLIST_INSERT_HEAD(&search_path, include_dir,
204                                                   links);
205                         }
206                         break;
207                 }
208                 case '?':
209                 default:
210                         usage();
211                         /* NOTREACHED */
212                 }
213         }
214         argc -= optind;
215         argv += optind;
216
217         if (argc != 1) {
218                 fprintf(stderr, "%s: No input file specifiled\n", appname);
219                 usage();
220                 /* NOTREACHED */
221         }
222
223         symtable_open();
224         inputfilename = *argv;
225         include_file(*argv, SOURCE_FILE);
226         retval = yyparse();
227         if (retval == 0) {
228                 if (SLIST_FIRST(&scope_stack) == NULL
229                  || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
230                         stop("Unterminated conditional expression",
231                              EX_DATAERR);
232                         /* NOTREACHED */
233                 }
234
235                 /* Process outmost scope */
236                 process_scope(SLIST_FIRST(&scope_stack));
237                 /*
238                  * Decend the tree of scopes and insert/emit
239                  * patches as appropriate.  We perform a depth first
240                  * tranversal, recursively handling each scope.
241                  */
242                 /* start at the root scope */
243                 dump_scope(SLIST_FIRST(&scope_stack));
244
245                 /* Patch up forward jump addresses */
246                 back_patch();
247
248                 if (ofile != NULL)
249                         output_code();
250                 if (regfile != NULL) {
251                         symtable_dump(regfile);
252                 }
253                 if (listfile != NULL)
254                         output_listing(inputfilename);
255         }
256
257         stop(NULL, 0);
258         /* NOTREACHED */
259         return (0);
260 }
261
262 static void
263 usage()
264 {
265
266         (void)fprintf(stderr,
267 "usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]
268                         [-r register_output_file] [-l program_list_file]
269                         input_file\n",
270                         appname);
271         exit(EX_USAGE);
272 }
273
274 static void
275 back_patch()
276 {
277         struct instruction *cur_instr;
278
279         for(cur_instr = seq_program.stqh_first;
280             cur_instr != NULL;
281             cur_instr = cur_instr->links.stqe_next) {
282                 if (cur_instr->patch_label != NULL) {
283                         struct ins_format3 *f3_instr;
284                         u_int address;
285
286                         if (cur_instr->patch_label->type != LABEL) {
287                                 char buf[255];
288
289                                 snprintf(buf, sizeof(buf),
290                                          "Undefined label %s",
291                                          cur_instr->patch_label->name);
292                                 stop(buf, EX_DATAERR);
293                                 /* NOTREACHED */
294                         }
295                         f3_instr = &cur_instr->format.format3;
296                         address = f3_instr->address;
297                         address += cur_instr->patch_label->info.linfo->address;
298                         f3_instr->address = address;
299                 }
300         }
301 }
302
303 static void
304 output_code()
305 {
306         struct instruction *cur_instr;
307         patch_t *cur_patch;
308         critical_section_t *cs;
309         symbol_node_t *cur_node;
310         int instrcount;
311
312         instrcount = 0;
313         fprintf(ofile,
314 "/*
315   * DO NOT EDIT - This file is automatically generated.
316   */\n");
317
318         fprintf(ofile, "static uint8_t seqprog[] = {\n");
319         for(cur_instr = seq_program.stqh_first;
320             cur_instr != NULL;
321             cur_instr = cur_instr->links.stqe_next) {
322
323                 fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
324                         cur_instr == seq_program.stqh_first ? "" : ",\n",
325 #if BYTE_ORDER == LITTLE_ENDIAN
326                         cur_instr->format.bytes[0],
327                         cur_instr->format.bytes[1],
328                         cur_instr->format.bytes[2],
329                         cur_instr->format.bytes[3]);
330 #else
331                         cur_instr->format.bytes[3],
332                         cur_instr->format.bytes[2],
333                         cur_instr->format.bytes[1],
334                         cur_instr->format.bytes[0]);
335 #endif
336                 instrcount++;
337         }
338         fprintf(ofile, "\n};\n\n");
339
340         /*
341          *  Output patch information.  Patch functions first.
342          */
343         for(cur_node = SLIST_FIRST(&patch_functions);
344             cur_node != NULL;
345             cur_node = SLIST_NEXT(cur_node,links)) {
346                 fprintf(ofile,
347 "static int ahc_patch%d_func(struct ahc_softc *ahc);
348
349 static int
350 ahc_patch%d_func(struct ahc_softc *ahc)
351 {
352         return (%s);
353 }\n\n",
354                         cur_node->symbol->info.condinfo->func_num,
355                         cur_node->symbol->info.condinfo->func_num,
356                         cur_node->symbol->name);
357         }
358
359         fprintf(ofile,
360 "typedef int patch_func_t (struct ahc_softc *);
361 struct patch {
362         patch_func_t    *patch_func;
363         uint32_t        begin      :10,
364                         skip_instr :10,
365                         skip_patch :12;
366 } patches[] = {\n");
367
368         for(cur_patch = STAILQ_FIRST(&patches);
369             cur_patch != NULL;
370             cur_patch = STAILQ_NEXT(cur_patch,links)) {
371                 fprintf(ofile, "%s\t{ ahc_patch%d_func, %d, %d, %d }",
372                         cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
373                         cur_patch->patch_func, cur_patch->begin,
374                         cur_patch->skip_instr, cur_patch->skip_patch);
375         }
376
377         fprintf(ofile, "\n};\n");
378
379         fprintf(ofile,
380 "struct cs {
381         u_int16_t       begin;
382         u_int16_t       end;
383 } critical_sections[] = {\n");
384
385         for(cs = TAILQ_FIRST(&cs_tailq);
386             cs != NULL;
387             cs = TAILQ_NEXT(cs, links)) {
388                 fprintf(ofile, "%s\t{ %d, %d }",
389                         cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
390                         cs->begin_addr, cs->end_addr);
391         }
392
393         fprintf(ofile, "\n};\n");
394
395         fprintf(ofile,
396 "const int num_critical_sections = sizeof(critical_sections)
397                                  / sizeof(*critical_sections);\n");
398
399         fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
400 }
401
402 static void
403 dump_scope(scope_t *scope)
404 {
405         scope_t *cur_scope;
406
407         /*
408          * Emit the first patch for this scope
409          */
410         emit_patch(scope, 0);
411
412         /*
413          * Dump each scope within this one.
414          */
415         cur_scope = TAILQ_FIRST(&scope->inner_scope);
416
417         while (cur_scope != NULL) {
418
419                 dump_scope(cur_scope);
420
421                 cur_scope = TAILQ_NEXT(cur_scope, scope_links);
422         }
423
424         /*
425          * Emit the second, closing, patch for this scope
426          */
427         emit_patch(scope, 1);
428 }
429
430 void
431 emit_patch(scope_t *scope, int patch)
432 {
433         patch_info_t *pinfo;
434         patch_t *new_patch;
435
436         pinfo = &scope->patches[patch];
437
438         if (pinfo->skip_instr == 0)
439                 /* No-Op patch */
440                 return;
441
442         new_patch = (patch_t *)malloc(sizeof(*new_patch));
443
444         if (new_patch == NULL)
445                 stop("Could not malloc patch structure", EX_OSERR);
446
447         memset(new_patch, 0, sizeof(*new_patch));
448
449         if (patch == 0) {
450                 new_patch->patch_func = scope->func_num;
451                 new_patch->begin = scope->begin_addr;
452         } else {
453                 new_patch->patch_func = 0;
454                 new_patch->begin = scope->end_addr;
455         }
456         new_patch->skip_instr = pinfo->skip_instr;
457         new_patch->skip_patch = pinfo->skip_patch;
458         STAILQ_INSERT_TAIL(&patches, new_patch, links);
459 }
460
461 void
462 output_listing(char *ifilename)
463 {
464         char buf[1024];
465         FILE *ifile;
466         struct instruction *cur_instr;
467         patch_t *cur_patch;
468         symbol_node_t *cur_func;
469         int *func_values;
470         int instrcount;
471         int instrptr;
472         int line;
473         int func_count;
474         int skip_addr;
475
476         instrcount = 0;
477         instrptr = 0;
478         line = 1;
479         skip_addr = 0;
480         if ((ifile = fopen(ifilename, "r")) == NULL) {
481                 perror(ifilename);
482                 stop(NULL, EX_DATAERR);
483         }
484
485         /*
486          * Determine which options to apply to this listing.
487          */
488         for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
489             cur_func != NULL;
490             cur_func = SLIST_NEXT(cur_func, links))
491                 func_count++;
492
493         func_values = NULL;
494         if (func_count != 0) {
495                 func_values = (int *)malloc(func_count * sizeof(int));
496
497                 if (func_values == NULL)
498                         stop("Could not malloc", EX_OSERR);
499                 
500                 func_values[0] = 0; /* FALSE func */
501                 func_count--;
502
503                 /*
504                  * Ask the user to fill in the return values for
505                  * the rest of the functions.
506                  */
507                 
508                 
509                 for (cur_func = SLIST_FIRST(&patch_functions);
510                      cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
511                      cur_func = SLIST_NEXT(cur_func, links), func_count--) {
512                         int input;
513                         
514                         fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
515                         fprintf(stdout,
516                                 "Enter the return value for "
517                                 "this expression[T/F]:");
518
519                         while (1) {
520
521                                 input = getchar();
522                                 input = toupper(input);
523
524                                 if (input == 'T') {
525                                         func_values[func_count] = 1;
526                                         break;
527                                 } else if (input == 'F') {
528                                         func_values[func_count] = 0;
529                                         break;
530                                 }
531                         }
532                         if (isatty(fileno(stdin)) == 0)
533                                 putchar(input);
534                 }
535                 fprintf(stdout, "\nThanks!\n");
536         }
537
538         /* Now output the listing */
539         cur_patch = STAILQ_FIRST(&patches);
540         for(cur_instr = STAILQ_FIRST(&seq_program);
541             cur_instr != NULL;
542             cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
543
544                 if (check_patch(&cur_patch, instrcount,
545                                 &skip_addr, func_values) == 0) {
546                         /* Don't count this instruction as it is in a patch
547                          * that was removed.
548                          */
549                         continue;
550                 }
551
552                 while (line < cur_instr->srcline) {
553                         fgets(buf, sizeof(buf), ifile);
554                                 fprintf(listfile, "\t\t%s", buf);
555                                 line++;
556                 }
557                 fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
558 #if BYTE_ORDER == LITTLE_ENDIAN
559                         cur_instr->format.bytes[0],
560                         cur_instr->format.bytes[1],
561                         cur_instr->format.bytes[2],
562                         cur_instr->format.bytes[3]);
563 #else
564                         cur_instr->format.bytes[3],
565                         cur_instr->format.bytes[2],
566                         cur_instr->format.bytes[1],
567                         cur_instr->format.bytes[0]);
568 #endif
569                 fgets(buf, sizeof(buf), ifile);
570                 fprintf(listfile, "\t%s", buf);
571                 line++;
572                 instrptr++;
573         }
574         /* Dump the remainder of the file */
575         while(fgets(buf, sizeof(buf), ifile) != NULL)
576                 fprintf(listfile, "\t\t%s", buf);
577
578         fclose(ifile);
579 }
580
581 static int
582 check_patch(patch_t **start_patch, int start_instr,
583             int *skip_addr, int *func_vals)
584 {
585         patch_t *cur_patch;
586
587         cur_patch = *start_patch;
588
589         while (cur_patch != NULL && start_instr == cur_patch->begin) {
590                 if (func_vals[cur_patch->patch_func] == 0) {
591                         int skip;
592
593                         /* Start rejecting code */
594                         *skip_addr = start_instr + cur_patch->skip_instr;
595                         for (skip = cur_patch->skip_patch;
596                              skip > 0 && cur_patch != NULL;
597                              skip--)
598                                 cur_patch = STAILQ_NEXT(cur_patch, links);
599                 } else {
600                         /* Accepted this patch.  Advance to the next
601                          * one and wait for our intruction pointer to
602                          * hit this point.
603                          */
604                         cur_patch = STAILQ_NEXT(cur_patch, links);
605                 }
606         }
607
608         *start_patch = cur_patch;
609         if (start_instr < *skip_addr)
610                 /* Still skipping */
611                 return (0);
612
613         return (1);
614 }
615
616 /*
617  * Print out error information if appropriate, and clean up before
618  * terminating the program.
619  */
620 void
621 stop(const char *string, int err_code)
622 {
623         if (string != NULL) {
624                 fprintf(stderr, "%s: ", appname);
625                 if (yyfilename != NULL) {
626                         fprintf(stderr, "Stopped at file %s, line %d - ",
627                                 yyfilename, yylineno);
628                 }
629                 fprintf(stderr, "%s\n", string);
630         }
631
632         if (ofile != NULL) {
633                 fclose(ofile);
634                 if (err_code != 0) {
635                         fprintf(stderr, "%s: Removing %s due to error\n",
636                                 appname, ofilename);
637                         unlink(ofilename);
638                 }
639         }
640
641         if (regfile != NULL) {
642                 fclose(regfile);
643                 if (err_code != 0) {
644                         fprintf(stderr, "%s: Removing %s due to error\n",
645                                 appname, regfilename);
646                         unlink(regfilename);
647                 }
648         }
649
650         if (listfile != NULL) {
651                 fclose(listfile);
652                 if (err_code != 0) {
653                         fprintf(stderr, "%s: Removing %s due to error\n",
654                                 appname, listfilename);
655                         unlink(listfilename);
656                 }
657         }
658
659         symlist_free(&patch_functions);
660         symtable_close();
661
662         exit(err_code);
663 }
664
665 struct instruction *
666 seq_alloc()
667 {
668         struct instruction *new_instr;
669
670         new_instr = (struct instruction *)malloc(sizeof(struct instruction));
671         if (new_instr == NULL)
672                 stop("Unable to malloc instruction object", EX_SOFTWARE);
673         memset(new_instr, 0, sizeof(*new_instr));
674         STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
675         new_instr->srcline = yylineno;
676         return new_instr;
677 }
678
679 critical_section_t *
680 cs_alloc()
681 {
682         critical_section_t *new_cs;
683
684         new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
685         if (new_cs == NULL)
686                 stop("Unable to malloc critical_section object", EX_SOFTWARE);
687         memset(new_cs, 0, sizeof(*new_cs));
688         
689         TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
690         return new_cs;
691 }
692
693 scope_t *
694 scope_alloc()
695 {
696         scope_t *new_scope;
697
698         new_scope = (scope_t *)malloc(sizeof(scope_t));
699         if (new_scope == NULL)
700                 stop("Unable to malloc scope object", EX_SOFTWARE);
701         memset(new_scope, 0, sizeof(*new_scope));
702         TAILQ_INIT(&new_scope->inner_scope);
703         
704         if (SLIST_FIRST(&scope_stack) != NULL) {
705                 TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
706                                   new_scope, scope_links);
707         }
708         /* This patch is now the current scope */
709         SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
710         return new_scope;
711 }
712
713 void
714 process_scope(scope_t *scope)
715 {
716         /*
717          * We are "leaving" this scope.  We should now have
718          * enough information to process the lists of scopes
719          * we encapsulate.
720          */
721         scope_t *cur_scope;
722         u_int skip_patch_count;
723         u_int skip_instr_count;
724
725         cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
726         skip_patch_count = 0;
727         skip_instr_count = 0;
728         while (cur_scope != NULL) {
729                 u_int patch0_patch_skip;
730
731                 patch0_patch_skip = 0;
732                 switch (cur_scope->type) {
733                 case SCOPE_IF:
734                 case SCOPE_ELSE_IF:
735                         if (skip_instr_count != 0) {
736                                 /* Create a tail patch */
737                                 patch0_patch_skip++;
738                                 cur_scope->patches[1].skip_patch =
739                                     skip_patch_count + 1;
740                                 cur_scope->patches[1].skip_instr =
741                                     skip_instr_count;
742                         }
743
744                         /* Count Head patch */
745                         patch0_patch_skip++;
746
747                         /* Count any patches contained in our inner scope */
748                         patch0_patch_skip += cur_scope->inner_scope_patches;
749
750                         cur_scope->patches[0].skip_patch = patch0_patch_skip;
751                         cur_scope->patches[0].skip_instr =
752                             cur_scope->end_addr - cur_scope->begin_addr;
753
754                         skip_instr_count += cur_scope->patches[0].skip_instr;
755
756                         skip_patch_count += patch0_patch_skip;
757                         if (cur_scope->type == SCOPE_IF) {
758                                 scope->inner_scope_patches += skip_patch_count;
759                                 skip_patch_count = 0;
760                                 skip_instr_count = 0;
761                         }
762                         break;
763                 case SCOPE_ELSE:
764                         /* Count any patches contained in our innter scope */
765                         skip_patch_count += cur_scope->inner_scope_patches;
766
767                         skip_instr_count += cur_scope->end_addr
768                                           - cur_scope->begin_addr;
769                         break;
770                 case SCOPE_ROOT:
771                         stop("Unexpected scope type encountered", EX_SOFTWARE);
772                         /* NOTREACHED */
773                 }
774
775                 cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
776         }
777 }