v2.4.8 -> v2.4.8.1
[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#8 $
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 = SLIST_FIRST(&search_path);
182                                      include_dir != NULL;
183                                      include_dir = SLIST_NEXT(include_dir,
184                                                               links))
185                                         /*
186                                          * All entries before a '-I-' only
187                                          * apply to includes specified with
188                                          * quotes instead of "<>".
189                                          */
190                                         include_dir->quoted_includes_only = 1;
191                         } else {
192                                 include_dir =
193                                     (path_entry_t)malloc(sizeof(*include_dir));
194                                 if (include_dir == NULL) {
195                                         perror(optarg);
196                                         stop(NULL, EX_OSERR);
197                                 }
198                                 include_dir->directory = strdup(optarg);
199                                 if (include_dir->directory == NULL) {
200                                         perror(optarg);
201                                         stop(NULL, EX_OSERR);
202                                 }
203                                 include_dir->quoted_includes_only = 0;
204                                 SLIST_INSERT_HEAD(&search_path, include_dir,
205                                                   links);
206                         }
207                         break;
208                 }
209                 case '?':
210                 default:
211                         usage();
212                         /* NOTREACHED */
213                 }
214         }
215         argc -= optind;
216         argv += optind;
217
218         if (argc != 1) {
219                 fprintf(stderr, "%s: No input file specifiled\n", appname);
220                 usage();
221                 /* NOTREACHED */
222         }
223
224         symtable_open();
225         inputfilename = *argv;
226         include_file(*argv, SOURCE_FILE);
227         retval = yyparse();
228         if (retval == 0) {
229                 if (SLIST_FIRST(&scope_stack) == NULL
230                  || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
231                         stop("Unterminated conditional expression",
232                              EX_DATAERR);
233                         /* NOTREACHED */
234                 }
235
236                 /* Process outmost scope */
237                 process_scope(SLIST_FIRST(&scope_stack));
238                 /*
239                  * Decend the tree of scopes and insert/emit
240                  * patches as appropriate.  We perform a depth first
241                  * tranversal, recursively handling each scope.
242                  */
243                 /* start at the root scope */
244                 dump_scope(SLIST_FIRST(&scope_stack));
245
246                 /* Patch up forward jump addresses */
247                 back_patch();
248
249                 if (ofile != NULL)
250                         output_code();
251                 if (regfile != NULL) {
252                         symtable_dump(regfile);
253                 }
254                 if (listfile != NULL)
255                         output_listing(inputfilename);
256         }
257
258         stop(NULL, 0);
259         /* NOTREACHED */
260         return (0);
261 }
262
263 static void
264 usage()
265 {
266
267         (void)fprintf(stderr,
268 "usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]
269                         [-r register_output_file] [-l program_list_file]
270                         input_file\n",
271                         appname);
272         exit(EX_USAGE);
273 }
274
275 static void
276 back_patch()
277 {
278         struct instruction *cur_instr;
279
280         for (cur_instr = STAILQ_FIRST(&seq_program);
281              cur_instr != NULL;
282              cur_instr = STAILQ_NEXT(cur_instr, links)) {
283                 if (cur_instr->patch_label != NULL) {
284                         struct ins_format3 *f3_instr;
285                         u_int address;
286
287                         if (cur_instr->patch_label->type != LABEL) {
288                                 char buf[255];
289
290                                 snprintf(buf, sizeof(buf),
291                                          "Undefined label %s",
292                                          cur_instr->patch_label->name);
293                                 stop(buf, EX_DATAERR);
294                                 /* NOTREACHED */
295                         }
296                         f3_instr = &cur_instr->format.format3;
297                         address = f3_instr->address;
298                         address += cur_instr->patch_label->info.linfo->address;
299                         f3_instr->address = address;
300                 }
301         }
302 }
303
304 static void
305 output_code()
306 {
307         struct instruction *cur_instr;
308         patch_t *cur_patch;
309         critical_section_t *cs;
310         symbol_node_t *cur_node;
311         int instrcount;
312
313         instrcount = 0;
314         fprintf(ofile,
315 "/*
316  * DO NOT EDIT - This file is automatically generated
317  *               from the following source files:
318  *
319 %s */\n", versions);
320
321         fprintf(ofile, "static uint8_t seqprog[] = {\n");
322         for (cur_instr = STAILQ_FIRST(&seq_program);
323              cur_instr != NULL;
324              cur_instr = STAILQ_NEXT(cur_instr, links)) {
325
326                 fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
327                         cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
328 #if BYTE_ORDER == LITTLE_ENDIAN
329                         cur_instr->format.bytes[0],
330                         cur_instr->format.bytes[1],
331                         cur_instr->format.bytes[2],
332                         cur_instr->format.bytes[3]);
333 #else
334                         cur_instr->format.bytes[3],
335                         cur_instr->format.bytes[2],
336                         cur_instr->format.bytes[1],
337                         cur_instr->format.bytes[0]);
338 #endif
339                 instrcount++;
340         }
341         fprintf(ofile, "\n};\n\n");
342
343         /*
344          *  Output patch information.  Patch functions first.
345          */
346         for (cur_node = SLIST_FIRST(&patch_functions);
347              cur_node != NULL;
348              cur_node = SLIST_NEXT(cur_node,links)) {
349                 fprintf(ofile,
350 "static int ahc_patch%d_func(struct ahc_softc *ahc);
351
352 static int
353 ahc_patch%d_func(struct ahc_softc *ahc)
354 {
355         return (%s);
356 }\n\n",
357                         cur_node->symbol->info.condinfo->func_num,
358                         cur_node->symbol->info.condinfo->func_num,
359                         cur_node->symbol->name);
360         }
361
362         fprintf(ofile,
363 "typedef int patch_func_t (struct ahc_softc *);
364 struct patch {
365         patch_func_t    *patch_func;
366         uint32_t        begin      :10,
367                         skip_instr :10,
368                         skip_patch :12;
369 } patches[] = {\n");
370
371         for(cur_patch = STAILQ_FIRST(&patches);
372             cur_patch != NULL;
373             cur_patch = STAILQ_NEXT(cur_patch,links)) {
374                 fprintf(ofile, "%s\t{ ahc_patch%d_func, %d, %d, %d }",
375                         cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
376                         cur_patch->patch_func, cur_patch->begin,
377                         cur_patch->skip_instr, cur_patch->skip_patch);
378         }
379
380         fprintf(ofile, "\n};\n");
381
382         fprintf(ofile,
383 "struct cs {
384         u_int16_t       begin;
385         u_int16_t       end;
386 } critical_sections[] = {\n");
387
388         for(cs = TAILQ_FIRST(&cs_tailq);
389             cs != NULL;
390             cs = TAILQ_NEXT(cs, links)) {
391                 fprintf(ofile, "%s\t{ %d, %d }",
392                         cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
393                         cs->begin_addr, cs->end_addr);
394         }
395
396         fprintf(ofile, "\n};\n");
397
398         fprintf(ofile,
399 "const int num_critical_sections = sizeof(critical_sections)
400                                  / sizeof(*critical_sections);\n");
401
402         fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
403 }
404
405 static void
406 dump_scope(scope_t *scope)
407 {
408         scope_t *cur_scope;
409
410         /*
411          * Emit the first patch for this scope
412          */
413         emit_patch(scope, 0);
414
415         /*
416          * Dump each scope within this one.
417          */
418         cur_scope = TAILQ_FIRST(&scope->inner_scope);
419
420         while (cur_scope != NULL) {
421
422                 dump_scope(cur_scope);
423
424                 cur_scope = TAILQ_NEXT(cur_scope, scope_links);
425         }
426
427         /*
428          * Emit the second, closing, patch for this scope
429          */
430         emit_patch(scope, 1);
431 }
432
433 void
434 emit_patch(scope_t *scope, int patch)
435 {
436         patch_info_t *pinfo;
437         patch_t *new_patch;
438
439         pinfo = &scope->patches[patch];
440
441         if (pinfo->skip_instr == 0)
442                 /* No-Op patch */
443                 return;
444
445         new_patch = (patch_t *)malloc(sizeof(*new_patch));
446
447         if (new_patch == NULL)
448                 stop("Could not malloc patch structure", EX_OSERR);
449
450         memset(new_patch, 0, sizeof(*new_patch));
451
452         if (patch == 0) {
453                 new_patch->patch_func = scope->func_num;
454                 new_patch->begin = scope->begin_addr;
455         } else {
456                 new_patch->patch_func = 0;
457                 new_patch->begin = scope->end_addr;
458         }
459         new_patch->skip_instr = pinfo->skip_instr;
460         new_patch->skip_patch = pinfo->skip_patch;
461         STAILQ_INSERT_TAIL(&patches, new_patch, links);
462 }
463
464 void
465 output_listing(char *ifilename)
466 {
467         char buf[1024];
468         FILE *ifile;
469         struct instruction *cur_instr;
470         patch_t *cur_patch;
471         symbol_node_t *cur_func;
472         int *func_values;
473         int instrcount;
474         int instrptr;
475         int line;
476         int func_count;
477         int skip_addr;
478
479         instrcount = 0;
480         instrptr = 0;
481         line = 1;
482         skip_addr = 0;
483         if ((ifile = fopen(ifilename, "r")) == NULL) {
484                 perror(ifilename);
485                 stop(NULL, EX_DATAERR);
486         }
487
488         /*
489          * Determine which options to apply to this listing.
490          */
491         for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
492             cur_func != NULL;
493             cur_func = SLIST_NEXT(cur_func, links))
494                 func_count++;
495
496         func_values = NULL;
497         if (func_count != 0) {
498                 func_values = (int *)malloc(func_count * sizeof(int));
499
500                 if (func_values == NULL)
501                         stop("Could not malloc", EX_OSERR);
502                 
503                 func_values[0] = 0; /* FALSE func */
504                 func_count--;
505
506                 /*
507                  * Ask the user to fill in the return values for
508                  * the rest of the functions.
509                  */
510                 
511                 
512                 for (cur_func = SLIST_FIRST(&patch_functions);
513                      cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
514                      cur_func = SLIST_NEXT(cur_func, links), func_count--) {
515                         int input;
516                         
517                         fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
518                         fprintf(stdout,
519                                 "Enter the return value for "
520                                 "this expression[T/F]:");
521
522                         while (1) {
523
524                                 input = getchar();
525                                 input = toupper(input);
526
527                                 if (input == 'T') {
528                                         func_values[func_count] = 1;
529                                         break;
530                                 } else if (input == 'F') {
531                                         func_values[func_count] = 0;
532                                         break;
533                                 }
534                         }
535                         if (isatty(fileno(stdin)) == 0)
536                                 putchar(input);
537                 }
538                 fprintf(stdout, "\nThanks!\n");
539         }
540
541         /* Now output the listing */
542         cur_patch = STAILQ_FIRST(&patches);
543         for(cur_instr = STAILQ_FIRST(&seq_program);
544             cur_instr != NULL;
545             cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
546
547                 if (check_patch(&cur_patch, instrcount,
548                                 &skip_addr, func_values) == 0) {
549                         /* Don't count this instruction as it is in a patch
550                          * that was removed.
551                          */
552                         continue;
553                 }
554
555                 while (line < cur_instr->srcline) {
556                         fgets(buf, sizeof(buf), ifile);
557                                 fprintf(listfile, "\t\t%s", buf);
558                                 line++;
559                 }
560                 fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
561 #if BYTE_ORDER == LITTLE_ENDIAN
562                         cur_instr->format.bytes[0],
563                         cur_instr->format.bytes[1],
564                         cur_instr->format.bytes[2],
565                         cur_instr->format.bytes[3]);
566 #else
567                         cur_instr->format.bytes[3],
568                         cur_instr->format.bytes[2],
569                         cur_instr->format.bytes[1],
570                         cur_instr->format.bytes[0]);
571 #endif
572                 fgets(buf, sizeof(buf), ifile);
573                 fprintf(listfile, "\t%s", buf);
574                 line++;
575                 instrptr++;
576         }
577         /* Dump the remainder of the file */
578         while(fgets(buf, sizeof(buf), ifile) != NULL)
579                 fprintf(listfile, "\t\t%s", buf);
580
581         fclose(ifile);
582 }
583
584 static int
585 check_patch(patch_t **start_patch, int start_instr,
586             int *skip_addr, int *func_vals)
587 {
588         patch_t *cur_patch;
589
590         cur_patch = *start_patch;
591
592         while (cur_patch != NULL && start_instr == cur_patch->begin) {
593                 if (func_vals[cur_patch->patch_func] == 0) {
594                         int skip;
595
596                         /* Start rejecting code */
597                         *skip_addr = start_instr + cur_patch->skip_instr;
598                         for (skip = cur_patch->skip_patch;
599                              skip > 0 && cur_patch != NULL;
600                              skip--)
601                                 cur_patch = STAILQ_NEXT(cur_patch, links);
602                 } else {
603                         /* Accepted this patch.  Advance to the next
604                          * one and wait for our intruction pointer to
605                          * hit this point.
606                          */
607                         cur_patch = STAILQ_NEXT(cur_patch, links);
608                 }
609         }
610
611         *start_patch = cur_patch;
612         if (start_instr < *skip_addr)
613                 /* Still skipping */
614                 return (0);
615
616         return (1);
617 }
618
619 /*
620  * Print out error information if appropriate, and clean up before
621  * terminating the program.
622  */
623 void
624 stop(const char *string, int err_code)
625 {
626         if (string != NULL) {
627                 fprintf(stderr, "%s: ", appname);
628                 if (yyfilename != NULL) {
629                         fprintf(stderr, "Stopped at file %s, line %d - ",
630                                 yyfilename, yylineno);
631                 }
632                 fprintf(stderr, "%s\n", string);
633         }
634
635         if (ofile != NULL) {
636                 fclose(ofile);
637                 if (err_code != 0) {
638                         fprintf(stderr, "%s: Removing %s due to error\n",
639                                 appname, ofilename);
640                         unlink(ofilename);
641                 }
642         }
643
644         if (regfile != NULL) {
645                 fclose(regfile);
646                 if (err_code != 0) {
647                         fprintf(stderr, "%s: Removing %s due to error\n",
648                                 appname, regfilename);
649                         unlink(regfilename);
650                 }
651         }
652
653         if (listfile != NULL) {
654                 fclose(listfile);
655                 if (err_code != 0) {
656                         fprintf(stderr, "%s: Removing %s due to error\n",
657                                 appname, listfilename);
658                         unlink(listfilename);
659                 }
660         }
661
662         symlist_free(&patch_functions);
663         symtable_close();
664
665         exit(err_code);
666 }
667
668 struct instruction *
669 seq_alloc()
670 {
671         struct instruction *new_instr;
672
673         new_instr = (struct instruction *)malloc(sizeof(struct instruction));
674         if (new_instr == NULL)
675                 stop("Unable to malloc instruction object", EX_SOFTWARE);
676         memset(new_instr, 0, sizeof(*new_instr));
677         STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
678         new_instr->srcline = yylineno;
679         return new_instr;
680 }
681
682 critical_section_t *
683 cs_alloc()
684 {
685         critical_section_t *new_cs;
686
687         new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
688         if (new_cs == NULL)
689                 stop("Unable to malloc critical_section object", EX_SOFTWARE);
690         memset(new_cs, 0, sizeof(*new_cs));
691         
692         TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
693         return new_cs;
694 }
695
696 scope_t *
697 scope_alloc()
698 {
699         scope_t *new_scope;
700
701         new_scope = (scope_t *)malloc(sizeof(scope_t));
702         if (new_scope == NULL)
703                 stop("Unable to malloc scope object", EX_SOFTWARE);
704         memset(new_scope, 0, sizeof(*new_scope));
705         TAILQ_INIT(&new_scope->inner_scope);
706         
707         if (SLIST_FIRST(&scope_stack) != NULL) {
708                 TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
709                                   new_scope, scope_links);
710         }
711         /* This patch is now the current scope */
712         SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
713         return new_scope;
714 }
715
716 void
717 process_scope(scope_t *scope)
718 {
719         /*
720          * We are "leaving" this scope.  We should now have
721          * enough information to process the lists of scopes
722          * we encapsulate.
723          */
724         scope_t *cur_scope;
725         u_int skip_patch_count;
726         u_int skip_instr_count;
727
728         cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
729         skip_patch_count = 0;
730         skip_instr_count = 0;
731         while (cur_scope != NULL) {
732                 u_int patch0_patch_skip;
733
734                 patch0_patch_skip = 0;
735                 switch (cur_scope->type) {
736                 case SCOPE_IF:
737                 case SCOPE_ELSE_IF:
738                         if (skip_instr_count != 0) {
739                                 /* Create a tail patch */
740                                 patch0_patch_skip++;
741                                 cur_scope->patches[1].skip_patch =
742                                     skip_patch_count + 1;
743                                 cur_scope->patches[1].skip_instr =
744                                     skip_instr_count;
745                         }
746
747                         /* Count Head patch */
748                         patch0_patch_skip++;
749
750                         /* Count any patches contained in our inner scope */
751                         patch0_patch_skip += cur_scope->inner_scope_patches;
752
753                         cur_scope->patches[0].skip_patch = patch0_patch_skip;
754                         cur_scope->patches[0].skip_instr =
755                             cur_scope->end_addr - cur_scope->begin_addr;
756
757                         skip_instr_count += cur_scope->patches[0].skip_instr;
758
759                         skip_patch_count += patch0_patch_skip;
760                         if (cur_scope->type == SCOPE_IF) {
761                                 scope->inner_scope_patches += skip_patch_count;
762                                 skip_patch_count = 0;
763                                 skip_instr_count = 0;
764                         }
765                         break;
766                 case SCOPE_ELSE:
767                         /* Count any patches contained in our innter scope */
768                         skip_patch_count += cur_scope->inner_scope_patches;
769
770                         skip_instr_count += cur_scope->end_addr
771                                           - cur_scope->begin_addr;
772                         break;
773                 case SCOPE_ROOT:
774                         stop("Unexpected scope type encountered", EX_SOFTWARE);
775                         /* NOTREACHED */
776                 }
777
778                 cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
779         }
780 }