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