xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm.c (revision 73c4bad04d786baa713109c8210ea69a9c05651a)
1098ca2bdSWarner Losh /*-
2c5cb3888SJustin T. Gibbs  * Aic7xxx SCSI host adapter firmware asssembler
30ef8c301SJustin T. Gibbs  *
47ce72dbaSJustin T. Gibbs  * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
563183d8cSJustin T. Gibbs  * Copyright (c) 2001, 2002 Adaptec Inc.
63cddb2a3SJustin T. Gibbs  * All rights reserved.
70ef8c301SJustin T. Gibbs  *
83cddb2a3SJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
93cddb2a3SJustin T. Gibbs  * modification, are permitted provided that the following conditions
103cddb2a3SJustin T. Gibbs  * are met:
113cddb2a3SJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
12f68f348bSJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
137ce72dbaSJustin T. Gibbs  *    without modification.
147ce72dbaSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
157ce72dbaSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
167ce72dbaSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
177ce72dbaSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
187ce72dbaSJustin T. Gibbs  *    binary redistribution.
197ce72dbaSJustin T. Gibbs  * 3. Neither the names of the above-listed copyright holders nor the names
207ce72dbaSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
217ce72dbaSJustin T. Gibbs  *    from this software without specific prior written permission.
220ef8c301SJustin T. Gibbs  *
23aa6dfd9dSJustin T. Gibbs  * Alternatively, this software may be distributed under the terms of the
247ce72dbaSJustin T. Gibbs  * GNU General Public License ("GPL") version 2 as published by the Free
257ce72dbaSJustin T. Gibbs  * Software Foundation.
26aa6dfd9dSJustin T. Gibbs  *
277ce72dbaSJustin T. Gibbs  * NO WARRANTY
287ce72dbaSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
297ce72dbaSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
307ce72dbaSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
317ce72dbaSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
327ce72dbaSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
333cddb2a3SJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
343cddb2a3SJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357ce72dbaSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
367ce72dbaSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
377ce72dbaSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
387ce72dbaSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
390ef8c301SJustin T. Gibbs  *
4091d00a4fSJustin T. Gibbs  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
4132da3127SJustin T. Gibbs  *
42c3aac50fSPeter Wemm  * $FreeBSD$
43c5cb3888SJustin T. Gibbs  */
44c5cb3888SJustin T. Gibbs #include <sys/types.h>
45c5cb3888SJustin T. Gibbs #include <sys/mman.h>
46c5cb3888SJustin T. Gibbs 
4795a5efc2SJustin T. Gibbs #include <ctype.h>
48083d01f2SJustin T. Gibbs #include <inttypes.h>
497ce72dbaSJustin T. Gibbs #include <regex.h>
500ef8c301SJustin T. Gibbs #include <stdio.h>
510ef8c301SJustin T. Gibbs #include <stdlib.h>
52c5cb3888SJustin T. Gibbs #include <string.h>
53c5cb3888SJustin T. Gibbs #include <sysexits.h>
540ef8c301SJustin T. Gibbs #include <unistd.h>
550ef8c301SJustin T. Gibbs 
567ce72dbaSJustin T. Gibbs #if linux
577ce72dbaSJustin T. Gibbs #include <endian.h>
587ce72dbaSJustin T. Gibbs #else
597ce72dbaSJustin T. Gibbs #include <machine/endian.h>
607ce72dbaSJustin T. Gibbs #endif
617ce72dbaSJustin T. Gibbs 
62c66dbc92SJustin T. Gibbs #include "aicasm.h"
63c66dbc92SJustin T. Gibbs #include "aicasm_symbol.h"
64aa6dfd9dSJustin T. Gibbs #include "aicasm_insformat.h"
650ef8c301SJustin T. Gibbs 
663bafc9d4SJustin T. Gibbs typedef struct patch {
67e3975643SJake Burkholder 	STAILQ_ENTRY(patch) links;
683bafc9d4SJustin T. Gibbs 	int		patch_func;
693bafc9d4SJustin T. Gibbs 	u_int		begin;
703bafc9d4SJustin T. Gibbs 	u_int		skip_instr;
713bafc9d4SJustin T. Gibbs 	u_int		skip_patch;
723bafc9d4SJustin T. Gibbs } patch_t;
733bafc9d4SJustin T. Gibbs 
74e3975643SJake Burkholder STAILQ_HEAD(patch_list, patch) patches;
753bafc9d4SJustin T. Gibbs 
763bafc9d4SJustin T. Gibbs static void usage(void);
773bafc9d4SJustin T. Gibbs static void back_patch(void);
78aa6dfd9dSJustin T. Gibbs static void output_code(void);
79aa6dfd9dSJustin T. Gibbs static void output_listing(char *ifilename);
8095a5efc2SJustin T. Gibbs static void dump_scope(scope_t *scope);
813bafc9d4SJustin T. Gibbs static void emit_patch(scope_t *scope, int patch);
82b18a2ef1SXin LI static int check_patch(patch_t **start_patch, unsigned int start_instr,
83b18a2ef1SXin LI 		       unsigned int *skip_addr, int *func_vals);
840ef8c301SJustin T. Gibbs 
85c5cb3888SJustin T. Gibbs struct path_list search_path;
86c5cb3888SJustin T. Gibbs int includes_search_curdir;
87c5cb3888SJustin T. Gibbs char *appname;
8863183d8cSJustin T. Gibbs char *stock_include_file;
89adf51647SJustin T. Gibbs FILE *ofile;
90c5cb3888SJustin T. Gibbs char *ofilename;
91f68f348bSJustin T. Gibbs char *regfilename;
92f68f348bSJustin T. Gibbs FILE *regfile;
93f68f348bSJustin T. Gibbs char *listfilename;
94f68f348bSJustin T. Gibbs FILE *listfile;
9563183d8cSJustin T. Gibbs char *regdiagfilename;
9663183d8cSJustin T. Gibbs FILE *regdiagfile;
977ce72dbaSJustin T. Gibbs int   src_mode;
987ce72dbaSJustin T. Gibbs int   dst_mode;
990ef8c301SJustin T. Gibbs 
100e3975643SJake Burkholder static STAILQ_HEAD(,instruction) seq_program;
101083d01f2SJustin T. Gibbs struct cs_tailq cs_tailq;
1023bafc9d4SJustin T. Gibbs struct scope_list scope_stack;
1033bafc9d4SJustin T. Gibbs symlist_t patch_functions;
104c5cb3888SJustin T. Gibbs 
105c5cb3888SJustin T. Gibbs #if DEBUG
106c5cb3888SJustin T. Gibbs extern int yy_flex_debug;
1077ce72dbaSJustin T. Gibbs extern int mm_flex_debug;
108c5cb3888SJustin T. Gibbs extern int yydebug;
1097ce72dbaSJustin T. Gibbs extern int mmdebug;
110c5cb3888SJustin T. Gibbs #endif
111c5cb3888SJustin T. Gibbs extern FILE *yyin;
11232da3127SJustin T. Gibbs extern int yyparse(void);
11332da3127SJustin T. Gibbs 
11432da3127SJustin T. Gibbs int main(int argc, char *argv[]);
115c5cb3888SJustin T. Gibbs 
116c5cb3888SJustin T. Gibbs int
11732da3127SJustin T. Gibbs main(int argc, char *argv[])
1183cddb2a3SJustin T. Gibbs {
119c5cb3888SJustin T. Gibbs 	int  ch;
120c5cb3888SJustin T. Gibbs 	int  retval;
121c5cb3888SJustin T. Gibbs 	char *inputfilename;
1223bafc9d4SJustin T. Gibbs 	scope_t *sentinal;
123adf51647SJustin T. Gibbs 
1243bafc9d4SJustin T. Gibbs 	STAILQ_INIT(&patches);
125c5cb3888SJustin T. Gibbs 	SLIST_INIT(&search_path);
126c5cb3888SJustin T. Gibbs 	STAILQ_INIT(&seq_program);
127083d01f2SJustin T. Gibbs 	TAILQ_INIT(&cs_tailq);
1283bafc9d4SJustin T. Gibbs 	SLIST_INIT(&scope_stack);
1293bafc9d4SJustin T. Gibbs 
1303bafc9d4SJustin T. Gibbs 	/* Set Sentinal scope node */
1313bafc9d4SJustin T. Gibbs 	sentinal = scope_alloc();
1323bafc9d4SJustin T. Gibbs 	sentinal->type = SCOPE_ROOT;
1333bafc9d4SJustin T. Gibbs 
134c5cb3888SJustin T. Gibbs 	includes_search_curdir = 1;
135c5cb3888SJustin T. Gibbs 	appname = *argv;
136c5cb3888SJustin T. Gibbs 	regfile = NULL;
137c5cb3888SJustin T. Gibbs 	listfile = NULL;
138c5cb3888SJustin T. Gibbs #if DEBUG
139c5cb3888SJustin T. Gibbs 	yy_flex_debug = 0;
1407ce72dbaSJustin T. Gibbs 	mm_flex_debug = 0;
1413bafc9d4SJustin T. Gibbs 	yydebug = 0;
1427ce72dbaSJustin T. Gibbs 	mmdebug = 0;
143c5cb3888SJustin T. Gibbs #endif
144a122cca9STom Rhodes 	while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:X")) != -1) {
145c5cb3888SJustin T. Gibbs 		switch(ch) {
146c5cb3888SJustin T. Gibbs 		case 'd':
147c5cb3888SJustin T. Gibbs #if DEBUG
148f68f348bSJustin T. Gibbs 			if (strcmp(optarg, "s") == 0) {
149c5cb3888SJustin T. Gibbs 				yy_flex_debug = 1;
1507ce72dbaSJustin T. Gibbs 				mm_flex_debug = 1;
151f68f348bSJustin T. Gibbs 			} else if (strcmp(optarg, "p") == 0) {
152c5cb3888SJustin T. Gibbs 				yydebug = 1;
1537ce72dbaSJustin T. Gibbs 				mmdebug = 1;
154f68f348bSJustin T. Gibbs 			} else {
155f68f348bSJustin T. Gibbs 				fprintf(stderr, "%s: -d Requires either an "
156f68f348bSJustin T. Gibbs 					"'s' or 'p' argument\n", appname);
157f68f348bSJustin T. Gibbs 				usage();
158f68f348bSJustin T. Gibbs 			}
159c5cb3888SJustin T. Gibbs #else
160c5cb3888SJustin T. Gibbs 			stop("-d: Assembler not built with debugging "
161c5cb3888SJustin T. Gibbs 			     "information", EX_SOFTWARE);
162c5cb3888SJustin T. Gibbs #endif
163c5cb3888SJustin T. Gibbs 			break;
16463183d8cSJustin T. Gibbs 		case 'i':
16563183d8cSJustin T. Gibbs 			stock_include_file = optarg;
16663183d8cSJustin T. Gibbs 			break;
167c5cb3888SJustin T. Gibbs 		case 'l':
168c5cb3888SJustin T. Gibbs 			/* Create a program listing */
169c5cb3888SJustin T. Gibbs 			if ((listfile = fopen(optarg, "w")) == NULL) {
170c5cb3888SJustin T. Gibbs 				perror(optarg);
171c5cb3888SJustin T. Gibbs 				stop(NULL, EX_CANTCREAT);
172c5cb3888SJustin T. Gibbs 			}
173c5cb3888SJustin T. Gibbs 			listfilename = optarg;
174c5cb3888SJustin T. Gibbs 			break;
175c5cb3888SJustin T. Gibbs 		case 'n':
176c5cb3888SJustin T. Gibbs 			/* Don't complain about the -nostdinc directrive */
177c5cb3888SJustin T. Gibbs 			if (strcmp(optarg, "ostdinc")) {
178c5cb3888SJustin T. Gibbs 				fprintf(stderr, "%s: Unknown option -%c%s\n",
179c5cb3888SJustin T. Gibbs 					appname, ch, optarg);
180c5cb3888SJustin T. Gibbs 				usage();
181c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
182c5cb3888SJustin T. Gibbs 			}
183c5cb3888SJustin T. Gibbs 			break;
184c5cb3888SJustin T. Gibbs 		case 'o':
185c2c5fd34SJustin T. Gibbs 			if ((ofile = fopen(optarg, "w")) == NULL) {
1860ef8c301SJustin T. Gibbs 				perror(optarg);
187c5cb3888SJustin T. Gibbs 				stop(NULL, EX_CANTCREAT);
188c5cb3888SJustin T. Gibbs 			}
189c5cb3888SJustin T. Gibbs 			ofilename = optarg;
190c5cb3888SJustin T. Gibbs 			break;
19163183d8cSJustin T. Gibbs 		case 'p':
19263183d8cSJustin T. Gibbs 			/* Create Register Diagnostic "printing" Functions */
19363183d8cSJustin T. Gibbs 			if ((regdiagfile = fopen(optarg, "w")) == NULL) {
19463183d8cSJustin T. Gibbs 				perror(optarg);
19563183d8cSJustin T. Gibbs 				stop(NULL, EX_CANTCREAT);
19663183d8cSJustin T. Gibbs 			}
19763183d8cSJustin T. Gibbs 			regdiagfilename = optarg;
19863183d8cSJustin T. Gibbs 			break;
199c5cb3888SJustin T. Gibbs 		case 'r':
200c5cb3888SJustin T. Gibbs 			if ((regfile = fopen(optarg, "w")) == NULL) {
201c5cb3888SJustin T. Gibbs 				perror(optarg);
202c5cb3888SJustin T. Gibbs 				stop(NULL, EX_CANTCREAT);
203c5cb3888SJustin T. Gibbs 			}
204c5cb3888SJustin T. Gibbs 			regfilename = optarg;
205c5cb3888SJustin T. Gibbs 			break;
206c5cb3888SJustin T. Gibbs 		case 'I':
207c5cb3888SJustin T. Gibbs 		{
208c5cb3888SJustin T. Gibbs 			path_entry_t include_dir;
209c5cb3888SJustin T. Gibbs 
210c5cb3888SJustin T. Gibbs 			if (strcmp(optarg, "-") == 0) {
211c5cb3888SJustin T. Gibbs 				if (includes_search_curdir == 0) {
212c5cb3888SJustin T. Gibbs 					fprintf(stderr, "%s: Warning - '-I-' "
213c5cb3888SJustin T. Gibbs 							"specified multiple "
214c5cb3888SJustin T. Gibbs 							"times\n", appname);
215c5cb3888SJustin T. Gibbs 				}
216c5cb3888SJustin T. Gibbs 				includes_search_curdir = 0;
217fc2ffbe6SPoul-Henning Kamp 				for (include_dir = SLIST_FIRST(&search_path);
218c5cb3888SJustin T. Gibbs 				     include_dir != NULL;
2192d0fbde8SJustin T. Gibbs 				     include_dir = SLIST_NEXT(include_dir,
2202d0fbde8SJustin T. Gibbs 							      links))
221c5cb3888SJustin T. Gibbs 					/*
222c5cb3888SJustin T. Gibbs 					 * All entries before a '-I-' only
223c5cb3888SJustin T. Gibbs 					 * apply to includes specified with
224c5cb3888SJustin T. Gibbs 					 * quotes instead of "<>".
225c5cb3888SJustin T. Gibbs 					 */
226c5cb3888SJustin T. Gibbs 					include_dir->quoted_includes_only = 1;
227c5cb3888SJustin T. Gibbs 			} else {
228c5cb3888SJustin T. Gibbs 				include_dir =
229c5cb3888SJustin T. Gibbs 				    (path_entry_t)malloc(sizeof(*include_dir));
230c5cb3888SJustin T. Gibbs 				if (include_dir == NULL) {
231c5cb3888SJustin T. Gibbs 					perror(optarg);
232c5cb3888SJustin T. Gibbs 					stop(NULL, EX_OSERR);
233c5cb3888SJustin T. Gibbs 				}
234c5cb3888SJustin T. Gibbs 				include_dir->directory = strdup(optarg);
235c5cb3888SJustin T. Gibbs 				if (include_dir->directory == NULL) {
236c5cb3888SJustin T. Gibbs 					perror(optarg);
237c5cb3888SJustin T. Gibbs 					stop(NULL, EX_OSERR);
238c5cb3888SJustin T. Gibbs 				}
239c5cb3888SJustin T. Gibbs 				include_dir->quoted_includes_only = 0;
240c5cb3888SJustin T. Gibbs 				SLIST_INSERT_HEAD(&search_path, include_dir,
241c5cb3888SJustin T. Gibbs 						  links);
2420ef8c301SJustin T. Gibbs 			}
2430ef8c301SJustin T. Gibbs 			break;
244c5cb3888SJustin T. Gibbs 		}
245a122cca9STom Rhodes 		case 'X':
246a122cca9STom Rhodes 			/* icc version of -nostdinc */
247a122cca9STom Rhodes 			break;
248c5cb3888SJustin T. Gibbs 		case '?':
2490ef8c301SJustin T. Gibbs 		default:
250c5cb3888SJustin T. Gibbs 			usage();
251c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
252c5cb3888SJustin T. Gibbs 		}
253c5cb3888SJustin T. Gibbs 	}
254c5cb3888SJustin T. Gibbs 	argc -= optind;
255c5cb3888SJustin T. Gibbs 	argv += optind;
256c5cb3888SJustin T. Gibbs 
257c5cb3888SJustin T. Gibbs 	if (argc != 1) {
258c5cb3888SJustin T. Gibbs 		fprintf(stderr, "%s: No input file specifiled\n", appname);
259c5cb3888SJustin T. Gibbs 		usage();
260c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
261c5cb3888SJustin T. Gibbs 	}
262c5cb3888SJustin T. Gibbs 
26363183d8cSJustin T. Gibbs 	if (regdiagfile != NULL
26463183d8cSJustin T. Gibbs 	 && (regfile == NULL || stock_include_file == NULL)) {
26563183d8cSJustin T. Gibbs 		fprintf(stderr,
26663183d8cSJustin T. Gibbs 			"%s: The -p option requires the -r and -i options.\n",
26763183d8cSJustin T. Gibbs 			appname);
26863183d8cSJustin T. Gibbs 		usage();
26963183d8cSJustin T. Gibbs 		/* NOTREACHED */
27063183d8cSJustin T. Gibbs 	}
271c5cb3888SJustin T. Gibbs 	symtable_open();
272c5cb3888SJustin T. Gibbs 	inputfilename = *argv;
273c5cb3888SJustin T. Gibbs 	include_file(*argv, SOURCE_FILE);
274c5cb3888SJustin T. Gibbs 	retval = yyparse();
275c5cb3888SJustin T. Gibbs 	if (retval == 0) {
2763bafc9d4SJustin T. Gibbs 		if (SLIST_FIRST(&scope_stack) == NULL
2773bafc9d4SJustin T. Gibbs 		 || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
2787ce72dbaSJustin T. Gibbs 			stop("Unterminated conditional expression", EX_DATAERR);
2793bafc9d4SJustin T. Gibbs 			/* NOTREACHED */
2803bafc9d4SJustin T. Gibbs 		}
2813bafc9d4SJustin T. Gibbs 
2823bafc9d4SJustin T. Gibbs 		/* Process outmost scope */
2833bafc9d4SJustin T. Gibbs 		process_scope(SLIST_FIRST(&scope_stack));
2843bafc9d4SJustin T. Gibbs 		/*
2853bafc9d4SJustin T. Gibbs 		 * Decend the tree of scopes and insert/emit
2863bafc9d4SJustin T. Gibbs 		 * patches as appropriate.  We perform a depth first
2873bafc9d4SJustin T. Gibbs 		 * tranversal, recursively handling each scope.
2883bafc9d4SJustin T. Gibbs 		 */
2893bafc9d4SJustin T. Gibbs 		/* start at the root scope */
2903bafc9d4SJustin T. Gibbs 		dump_scope(SLIST_FIRST(&scope_stack));
2913bafc9d4SJustin T. Gibbs 
2923bafc9d4SJustin T. Gibbs 		/* Patch up forward jump addresses */
293c5cb3888SJustin T. Gibbs 		back_patch();
2943bafc9d4SJustin T. Gibbs 
295c5cb3888SJustin T. Gibbs 		if (ofile != NULL)
296aa6dfd9dSJustin T. Gibbs 			output_code();
29763183d8cSJustin T. Gibbs 		if (regfile != NULL)
29863183d8cSJustin T. Gibbs 			symtable_dump(regfile, regdiagfile);
299c5cb3888SJustin T. Gibbs 		if (listfile != NULL)
300aa6dfd9dSJustin T. Gibbs 			output_listing(inputfilename);
301c5cb3888SJustin T. Gibbs 	}
302c5cb3888SJustin T. Gibbs 
303c5cb3888SJustin T. Gibbs 	stop(NULL, 0);
304c5cb3888SJustin T. Gibbs 	/* NOTREACHED */
305c5cb3888SJustin T. Gibbs 	return (0);
306c5cb3888SJustin T. Gibbs }
307c5cb3888SJustin T. Gibbs 
308c5cb3888SJustin T. Gibbs static void
30973c4bad0SEd Schouten usage(void)
310c5cb3888SJustin T. Gibbs {
311c5cb3888SJustin T. Gibbs 
3121c147cc3SJustin T. Gibbs 	(void)fprintf(stderr,
313a122cca9STom Rhodes "usage: %-16s [-nostdinc|-X] [-I-] [-I directory] [-o output_file]\n"
31463183d8cSJustin T. Gibbs "	[-r register_output_file [-p register_diag_file -i includefile]]\n"
31563183d8cSJustin T. Gibbs "	[-l program_list_file]\n"
31663183d8cSJustin T. Gibbs "	input_file\n", appname);
317c5cb3888SJustin T. Gibbs 	exit(EX_USAGE);
318c5cb3888SJustin T. Gibbs }
319c5cb3888SJustin T. Gibbs 
320c5cb3888SJustin T. Gibbs static void
32173c4bad0SEd Schouten back_patch(void)
322c5cb3888SJustin T. Gibbs {
323c5cb3888SJustin T. Gibbs 	struct instruction *cur_instr;
324c5cb3888SJustin T. Gibbs 
325fc2ffbe6SPoul-Henning Kamp 	for (cur_instr = STAILQ_FIRST(&seq_program);
326c5cb3888SJustin T. Gibbs 	     cur_instr != NULL;
327fc2ffbe6SPoul-Henning Kamp 	     cur_instr = STAILQ_NEXT(cur_instr, links)) {
328c5cb3888SJustin T. Gibbs 		if (cur_instr->patch_label != NULL) {
329c5cb3888SJustin T. Gibbs 			struct ins_format3 *f3_instr;
330c5cb3888SJustin T. Gibbs 			u_int address;
331c5cb3888SJustin T. Gibbs 
332c5cb3888SJustin T. Gibbs 			if (cur_instr->patch_label->type != LABEL) {
333c5cb3888SJustin T. Gibbs 				char buf[255];
334c5cb3888SJustin T. Gibbs 
335c5cb3888SJustin T. Gibbs 				snprintf(buf, sizeof(buf),
336c5cb3888SJustin T. Gibbs 					 "Undefined label %s",
337c5cb3888SJustin T. Gibbs 					 cur_instr->patch_label->name);
338c5cb3888SJustin T. Gibbs 				stop(buf, EX_DATAERR);
339c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
340c5cb3888SJustin T. Gibbs 			}
341c5cb3888SJustin T. Gibbs 			f3_instr = &cur_instr->format.format3;
3423bafc9d4SJustin T. Gibbs 			address = f3_instr->address;
343c5cb3888SJustin T. Gibbs 			address += cur_instr->patch_label->info.linfo->address;
3443bafc9d4SJustin T. Gibbs 			f3_instr->address = address;
345c5cb3888SJustin T. Gibbs 		}
3460ef8c301SJustin T. Gibbs 	}
3470ef8c301SJustin T. Gibbs }
3480ef8c301SJustin T. Gibbs 
349c5cb3888SJustin T. Gibbs static void
35073c4bad0SEd Schouten output_code(void)
351c5cb3888SJustin T. Gibbs {
352c5cb3888SJustin T. Gibbs 	struct instruction *cur_instr;
353c5cb3888SJustin T. Gibbs 	patch_t *cur_patch;
354083d01f2SJustin T. Gibbs 	critical_section_t *cs;
355c5cb3888SJustin T. Gibbs 	symbol_node_t *cur_node;
356c5cb3888SJustin T. Gibbs 	int instrcount;
357c5cb3888SJustin T. Gibbs 
358c5cb3888SJustin T. Gibbs 	instrcount = 0;
359c5cb3888SJustin T. Gibbs 	fprintf(ofile,
3609b2af00eSJustin T. Gibbs "/*\n"
3619b2af00eSJustin T. Gibbs " * DO NOT EDIT - This file is automatically generated\n"
3629b2af00eSJustin T. Gibbs " *		 from the following source files:\n"
3639b2af00eSJustin T. Gibbs " *\n"
3649b2af00eSJustin T. Gibbs "%s */\n", versions);
365c5cb3888SJustin T. Gibbs 
366aa6dfd9dSJustin T. Gibbs 	fprintf(ofile, "static uint8_t seqprog[] = {\n");
367fc2ffbe6SPoul-Henning Kamp 	for (cur_instr = STAILQ_FIRST(&seq_program);
368c5cb3888SJustin T. Gibbs 	     cur_instr != NULL;
369fc2ffbe6SPoul-Henning Kamp 	     cur_instr = STAILQ_NEXT(cur_instr, links)) {
3703bafc9d4SJustin T. Gibbs 
371b1721cfbSJustin T. Gibbs 		fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
372fc2ffbe6SPoul-Henning Kamp 			cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
373aa6dfd9dSJustin T. Gibbs #if BYTE_ORDER == LITTLE_ENDIAN
374c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[0],
375c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[1],
376c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[2],
377c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[3]);
378aa6dfd9dSJustin T. Gibbs #else
379aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[3],
380aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[2],
381aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[1],
382aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[0]);
383aa6dfd9dSJustin T. Gibbs #endif
384c5cb3888SJustin T. Gibbs 		instrcount++;
3850ef8c301SJustin T. Gibbs 	}
386b1721cfbSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
3870ef8c301SJustin T. Gibbs 
3887ce72dbaSJustin T. Gibbs 	if (patch_arg_list == NULL)
3897ce72dbaSJustin T. Gibbs 		stop("Patch argument list not defined",
3907ce72dbaSJustin T. Gibbs 		     EX_DATAERR);
3917ce72dbaSJustin T. Gibbs 
392c5cb3888SJustin T. Gibbs 	/*
3933bafc9d4SJustin T. Gibbs 	 *  Output patch information.  Patch functions first.
394c5cb3888SJustin T. Gibbs 	 */
39563183d8cSJustin T. Gibbs 	fprintf(ofile,
39663183d8cSJustin T. Gibbs "typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
39763183d8cSJustin T. Gibbs 
3983bafc9d4SJustin T. Gibbs 	for (cur_node = SLIST_FIRST(&patch_functions);
399c5cb3888SJustin T. Gibbs 	     cur_node != NULL;
4003bafc9d4SJustin T. Gibbs 	     cur_node = SLIST_NEXT(cur_node,links)) {
4013bafc9d4SJustin T. Gibbs 		fprintf(ofile,
40263183d8cSJustin T. Gibbs "static %spatch_func_t %spatch%d_func;\n"
4039b2af00eSJustin T. Gibbs "\n"
4049b2af00eSJustin T. Gibbs "static int\n"
40563183d8cSJustin T. Gibbs "%spatch%d_func(%s)\n"
4069b2af00eSJustin T. Gibbs "{\n"
4079b2af00eSJustin T. Gibbs "	return (%s);\n"
4089b2af00eSJustin T. Gibbs "}\n\n",
40963183d8cSJustin T. Gibbs 			prefix,
41063183d8cSJustin T. Gibbs 			prefix,
4113bafc9d4SJustin T. Gibbs 			cur_node->symbol->info.condinfo->func_num,
41263183d8cSJustin T. Gibbs 			prefix,
4133bafc9d4SJustin T. Gibbs 			cur_node->symbol->info.condinfo->func_num,
4147ce72dbaSJustin T. Gibbs 			patch_arg_list,
4153bafc9d4SJustin T. Gibbs 			cur_node->symbol->name);
416c5cb3888SJustin T. Gibbs 	}
417adf51647SJustin T. Gibbs 
418c5cb3888SJustin T. Gibbs 	fprintf(ofile,
4199b2af00eSJustin T. Gibbs "static struct patch {\n"
42063183d8cSJustin T. Gibbs "	%spatch_func_t		*patch_func;\n"
4219b2af00eSJustin T. Gibbs "	uint32_t		 begin		:10,\n"
4229b2af00eSJustin T. Gibbs "				 skip_instr	:10,\n"
4239b2af00eSJustin T. Gibbs "				 skip_patch	:12;\n"
42463183d8cSJustin T. Gibbs "} patches[] = {\n", prefix);
425c5cb3888SJustin T. Gibbs 
4263bafc9d4SJustin T. Gibbs 	for (cur_patch = STAILQ_FIRST(&patches);
427c5cb3888SJustin T. Gibbs 	     cur_patch != NULL;
4283bafc9d4SJustin T. Gibbs 	     cur_patch = STAILQ_NEXT(cur_patch,links)) {
42963183d8cSJustin T. Gibbs 		fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
430b1721cfbSJustin T. Gibbs 			cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
43163183d8cSJustin T. Gibbs 			prefix,
4323bafc9d4SJustin T. Gibbs 			cur_patch->patch_func, cur_patch->begin,
4333bafc9d4SJustin T. Gibbs 			cur_patch->skip_instr, cur_patch->skip_patch);
4343bafc9d4SJustin T. Gibbs 	}
435c5cb3888SJustin T. Gibbs 
4369b2af00eSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
437c5cb3888SJustin T. Gibbs 
438083d01f2SJustin T. Gibbs 	fprintf(ofile,
4399b2af00eSJustin T. Gibbs "static struct cs {\n"
44063183d8cSJustin T. Gibbs "	uint16_t	begin;\n"
44163183d8cSJustin T. Gibbs "	uint16_t	end;\n"
4429b2af00eSJustin T. Gibbs "} critical_sections[] = {\n");
443083d01f2SJustin T. Gibbs 
444083d01f2SJustin T. Gibbs 	for (cs = TAILQ_FIRST(&cs_tailq);
445083d01f2SJustin T. Gibbs 	     cs != NULL;
446083d01f2SJustin T. Gibbs 	     cs = TAILQ_NEXT(cs, links)) {
447b1721cfbSJustin T. Gibbs 		fprintf(ofile, "%s\t{ %d, %d }",
448b1721cfbSJustin T. Gibbs 			cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
449083d01f2SJustin T. Gibbs 			cs->begin_addr, cs->end_addr);
450083d01f2SJustin T. Gibbs 	}
451083d01f2SJustin T. Gibbs 
4529b2af00eSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
453083d01f2SJustin T. Gibbs 
454b1721cfbSJustin T. Gibbs 	fprintf(ofile,
4559b2af00eSJustin T. Gibbs "static const int num_critical_sections = sizeof(critical_sections)\n"
4569b2af00eSJustin T. Gibbs "				       / sizeof(*critical_sections);\n");
457b1721cfbSJustin T. Gibbs 
458c5cb3888SJustin T. Gibbs 	fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
4590ef8c301SJustin T. Gibbs }
4600ef8c301SJustin T. Gibbs 
46195a5efc2SJustin T. Gibbs static void
4623bafc9d4SJustin T. Gibbs dump_scope(scope_t *scope)
463c5cb3888SJustin T. Gibbs {
4643bafc9d4SJustin T. Gibbs 	scope_t *cur_scope;
4653bafc9d4SJustin T. Gibbs 
4663bafc9d4SJustin T. Gibbs 	/*
4673bafc9d4SJustin T. Gibbs 	 * Emit the first patch for this scope
4683bafc9d4SJustin T. Gibbs 	 */
4693bafc9d4SJustin T. Gibbs 	emit_patch(scope, 0);
4703bafc9d4SJustin T. Gibbs 
4713bafc9d4SJustin T. Gibbs 	/*
4723bafc9d4SJustin T. Gibbs 	 * Dump each scope within this one.
4733bafc9d4SJustin T. Gibbs 	 */
4743bafc9d4SJustin T. Gibbs 	cur_scope = TAILQ_FIRST(&scope->inner_scope);
4753bafc9d4SJustin T. Gibbs 
4763bafc9d4SJustin T. Gibbs 	while (cur_scope != NULL) {
4773bafc9d4SJustin T. Gibbs 
4783bafc9d4SJustin T. Gibbs 		dump_scope(cur_scope);
4793bafc9d4SJustin T. Gibbs 
4803bafc9d4SJustin T. Gibbs 		cur_scope = TAILQ_NEXT(cur_scope, scope_links);
4813bafc9d4SJustin T. Gibbs 	}
4823bafc9d4SJustin T. Gibbs 
4833bafc9d4SJustin T. Gibbs 	/*
4843bafc9d4SJustin T. Gibbs 	 * Emit the second, closing, patch for this scope
4853bafc9d4SJustin T. Gibbs 	 */
4863bafc9d4SJustin T. Gibbs 	emit_patch(scope, 1);
4873bafc9d4SJustin T. Gibbs }
4883bafc9d4SJustin T. Gibbs 
4893bafc9d4SJustin T. Gibbs void
4903bafc9d4SJustin T. Gibbs emit_patch(scope_t *scope, int patch)
4913bafc9d4SJustin T. Gibbs {
4923bafc9d4SJustin T. Gibbs 	patch_info_t *pinfo;
4933bafc9d4SJustin T. Gibbs 	patch_t *new_patch;
4943bafc9d4SJustin T. Gibbs 
4953bafc9d4SJustin T. Gibbs 	pinfo = &scope->patches[patch];
4963bafc9d4SJustin T. Gibbs 
4973bafc9d4SJustin T. Gibbs 	if (pinfo->skip_instr == 0)
4983bafc9d4SJustin T. Gibbs 		/* No-Op patch */
4993bafc9d4SJustin T. Gibbs 		return;
5003bafc9d4SJustin T. Gibbs 
5013bafc9d4SJustin T. Gibbs 	new_patch = (patch_t *)malloc(sizeof(*new_patch));
5023bafc9d4SJustin T. Gibbs 
5033bafc9d4SJustin T. Gibbs 	if (new_patch == NULL)
5043bafc9d4SJustin T. Gibbs 		stop("Could not malloc patch structure", EX_OSERR);
5053bafc9d4SJustin T. Gibbs 
5063bafc9d4SJustin T. Gibbs 	memset(new_patch, 0, sizeof(*new_patch));
5073bafc9d4SJustin T. Gibbs 
5083bafc9d4SJustin T. Gibbs 	if (patch == 0) {
5093bafc9d4SJustin T. Gibbs 		new_patch->patch_func = scope->func_num;
5103bafc9d4SJustin T. Gibbs 		new_patch->begin = scope->begin_addr;
5113bafc9d4SJustin T. Gibbs 	} else {
5123bafc9d4SJustin T. Gibbs 		new_patch->patch_func = 0;
5133bafc9d4SJustin T. Gibbs 		new_patch->begin = scope->end_addr;
5143bafc9d4SJustin T. Gibbs 	}
5153bafc9d4SJustin T. Gibbs 	new_patch->skip_instr = pinfo->skip_instr;
5163bafc9d4SJustin T. Gibbs 	new_patch->skip_patch = pinfo->skip_patch;
5173bafc9d4SJustin T. Gibbs 	STAILQ_INSERT_TAIL(&patches, new_patch, links);
5183bafc9d4SJustin T. Gibbs }
5193bafc9d4SJustin T. Gibbs 
5203bafc9d4SJustin T. Gibbs void
521aa6dfd9dSJustin T. Gibbs output_listing(char *ifilename)
5223bafc9d4SJustin T. Gibbs {
5233bafc9d4SJustin T. Gibbs 	char buf[1024];
524c5cb3888SJustin T. Gibbs 	FILE *ifile;
525c5cb3888SJustin T. Gibbs 	struct instruction *cur_instr;
5263bafc9d4SJustin T. Gibbs 	patch_t *cur_patch;
5273bafc9d4SJustin T. Gibbs 	symbol_node_t *cur_func;
5283bafc9d4SJustin T. Gibbs 	int *func_values;
529c5cb3888SJustin T. Gibbs 	int instrcount;
5301c147cc3SJustin T. Gibbs 	int instrptr;
531b18a2ef1SXin LI 	unsigned int line;
5323bafc9d4SJustin T. Gibbs 	int func_count;
5333bafc9d4SJustin T. Gibbs 	int skip_addr;
534c5cb3888SJustin T. Gibbs 
535c5cb3888SJustin T. Gibbs 	instrcount = 0;
5361c147cc3SJustin T. Gibbs 	instrptr = 0;
537c5cb3888SJustin T. Gibbs 	line = 1;
5383bafc9d4SJustin T. Gibbs 	skip_addr = 0;
539c5cb3888SJustin T. Gibbs 	if ((ifile = fopen(ifilename, "r")) == NULL) {
540c5cb3888SJustin T. Gibbs 		perror(ifilename);
541c5cb3888SJustin T. Gibbs 		stop(NULL, EX_DATAERR);
542c5cb3888SJustin T. Gibbs 	}
5431c147cc3SJustin T. Gibbs 
5441c147cc3SJustin T. Gibbs 	/*
5451c147cc3SJustin T. Gibbs 	 * Determine which options to apply to this listing.
5461c147cc3SJustin T. Gibbs 	 */
5473bafc9d4SJustin T. Gibbs 	for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
5483bafc9d4SJustin T. Gibbs 	    cur_func != NULL;
5493bafc9d4SJustin T. Gibbs 	    cur_func = SLIST_NEXT(cur_func, links))
5503bafc9d4SJustin T. Gibbs 		func_count++;
5511c147cc3SJustin T. Gibbs 
55232da3127SJustin T. Gibbs 	func_values = NULL;
5533bafc9d4SJustin T. Gibbs 	if (func_count != 0) {
5543bafc9d4SJustin T. Gibbs 		func_values = (int *)malloc(func_count * sizeof(int));
5553bafc9d4SJustin T. Gibbs 
5563bafc9d4SJustin T. Gibbs 		if (func_values == NULL)
5573bafc9d4SJustin T. Gibbs 			stop("Could not malloc", EX_OSERR);
5583bafc9d4SJustin T. Gibbs 
5593bafc9d4SJustin T. Gibbs 		func_values[0] = 0; /* FALSE func */
5603bafc9d4SJustin T. Gibbs 		func_count--;
5613bafc9d4SJustin T. Gibbs 
5623bafc9d4SJustin T. Gibbs 		/*
5633bafc9d4SJustin T. Gibbs 		 * Ask the user to fill in the return values for
5643bafc9d4SJustin T. Gibbs 		 * the rest of the functions.
5653bafc9d4SJustin T. Gibbs 		 */
5663bafc9d4SJustin T. Gibbs 
5673bafc9d4SJustin T. Gibbs 
5683bafc9d4SJustin T. Gibbs 		for (cur_func = SLIST_FIRST(&patch_functions);
5693bafc9d4SJustin T. Gibbs 		     cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
5703bafc9d4SJustin T. Gibbs 		     cur_func = SLIST_NEXT(cur_func, links), func_count--) {
5713bafc9d4SJustin T. Gibbs 			int input;
5723bafc9d4SJustin T. Gibbs 
5733bafc9d4SJustin T. Gibbs 			fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
5743bafc9d4SJustin T. Gibbs 			fprintf(stdout,
5753bafc9d4SJustin T. Gibbs 				"Enter the return value for "
5763bafc9d4SJustin T. Gibbs 				"this expression[T/F]:");
5773bafc9d4SJustin T. Gibbs 
5783bafc9d4SJustin T. Gibbs 			while (1) {
5793bafc9d4SJustin T. Gibbs 
5803bafc9d4SJustin T. Gibbs 				input = getchar();
5813bafc9d4SJustin T. Gibbs 				input = toupper(input);
5823bafc9d4SJustin T. Gibbs 
5833bafc9d4SJustin T. Gibbs 				if (input == 'T') {
5843bafc9d4SJustin T. Gibbs 					func_values[func_count] = 1;
5853bafc9d4SJustin T. Gibbs 					break;
5863bafc9d4SJustin T. Gibbs 				} else if (input == 'F') {
5873bafc9d4SJustin T. Gibbs 					func_values[func_count] = 0;
5883bafc9d4SJustin T. Gibbs 					break;
5891c147cc3SJustin T. Gibbs 				}
5903bafc9d4SJustin T. Gibbs 			}
591e287abc8SJustin T. Gibbs 			if (isatty(fileno(stdin)) == 0)
592e287abc8SJustin T. Gibbs 				putchar(input);
5933bafc9d4SJustin T. Gibbs 		}
5943bafc9d4SJustin T. Gibbs 		fprintf(stdout, "\nThanks!\n");
5951c147cc3SJustin T. Gibbs 	}
5961c147cc3SJustin T. Gibbs 
5973bafc9d4SJustin T. Gibbs 	/* Now output the listing */
5983bafc9d4SJustin T. Gibbs 	cur_patch = STAILQ_FIRST(&patches);
5993bafc9d4SJustin T. Gibbs 	for (cur_instr = STAILQ_FIRST(&seq_program);
600c5cb3888SJustin T. Gibbs 	     cur_instr != NULL;
6013bafc9d4SJustin T. Gibbs 	     cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
6021c147cc3SJustin T. Gibbs 
6033bafc9d4SJustin T. Gibbs 		if (check_patch(&cur_patch, instrcount,
6043bafc9d4SJustin T. Gibbs 				&skip_addr, func_values) == 0) {
6051c147cc3SJustin T. Gibbs 			/* Don't count this instruction as it is in a patch
6061c147cc3SJustin T. Gibbs 			 * that was removed.
6071c147cc3SJustin T. Gibbs 			 */
6081c147cc3SJustin T. Gibbs                         continue;
6093bafc9d4SJustin T. Gibbs 		}
6101c147cc3SJustin T. Gibbs 
611c5cb3888SJustin T. Gibbs 		while (line < cur_instr->srcline) {
612c5cb3888SJustin T. Gibbs 			fgets(buf, sizeof(buf), ifile);
61391d00a4fSJustin T. Gibbs 				fprintf(listfile, "             \t%s", buf);
614c5cb3888SJustin T. Gibbs 				line++;
615c5cb3888SJustin T. Gibbs 		}
61691d00a4fSJustin T. Gibbs 		fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
617aa6dfd9dSJustin T. Gibbs #if BYTE_ORDER == LITTLE_ENDIAN
618c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[0],
619c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[1],
620c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[2],
621c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[3]);
622aa6dfd9dSJustin T. Gibbs #else
623aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[3],
624aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[2],
625aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[1],
626aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[0]);
627aa6dfd9dSJustin T. Gibbs #endif
62891d00a4fSJustin T. Gibbs 		/*
62991d00a4fSJustin T. Gibbs 		 * Macro expansions can cause several instructions
63091d00a4fSJustin T. Gibbs 		 * to be output for a single source line.  Only
63191d00a4fSJustin T. Gibbs 		 * advance the line once in these cases.
63291d00a4fSJustin T. Gibbs 		 */
63391d00a4fSJustin T. Gibbs 		if (line == cur_instr->srcline) {
634c5cb3888SJustin T. Gibbs 			fgets(buf, sizeof(buf), ifile);
6351c147cc3SJustin T. Gibbs 			fprintf(listfile, "\t%s", buf);
636c5cb3888SJustin T. Gibbs 			line++;
63791d00a4fSJustin T. Gibbs 		} else {
63891d00a4fSJustin T. Gibbs 			fprintf(listfile, "\n");
63991d00a4fSJustin T. Gibbs 		}
6401c147cc3SJustin T. Gibbs 		instrptr++;
641c5cb3888SJustin T. Gibbs 	}
64256d7cd7cSChristian Brueffer 	free(func_values);
64356d7cd7cSChristian Brueffer 
6441c147cc3SJustin T. Gibbs 	/* Dump the remainder of the file */
6451c147cc3SJustin T. Gibbs 	while(fgets(buf, sizeof(buf), ifile) != NULL)
64691d00a4fSJustin T. Gibbs 		fprintf(listfile, "             %s", buf);
6471c147cc3SJustin T. Gibbs 
648c5cb3888SJustin T. Gibbs 	fclose(ifile);
649c5cb3888SJustin T. Gibbs }
650c5cb3888SJustin T. Gibbs 
6513bafc9d4SJustin T. Gibbs static int
652b18a2ef1SXin LI check_patch(patch_t **start_patch, unsigned int start_instr,
653b18a2ef1SXin LI 	    unsigned int *skip_addr, int *func_vals)
6541c147cc3SJustin T. Gibbs {
6553bafc9d4SJustin T. Gibbs 	patch_t *cur_patch;
6563bafc9d4SJustin T. Gibbs 
6573bafc9d4SJustin T. Gibbs 	cur_patch = *start_patch;
6583bafc9d4SJustin T. Gibbs 
6593bafc9d4SJustin T. Gibbs 	while (cur_patch != NULL && start_instr == cur_patch->begin) {
6603bafc9d4SJustin T. Gibbs 		if (func_vals[cur_patch->patch_func] == 0) {
6613bafc9d4SJustin T. Gibbs 			int skip;
6623bafc9d4SJustin T. Gibbs 
6633bafc9d4SJustin T. Gibbs 			/* Start rejecting code */
6643bafc9d4SJustin T. Gibbs 			*skip_addr = start_instr + cur_patch->skip_instr;
6653bafc9d4SJustin T. Gibbs 			for (skip = cur_patch->skip_patch;
6663bafc9d4SJustin T. Gibbs 			     skip > 0 && cur_patch != NULL;
6673bafc9d4SJustin T. Gibbs 			     skip--)
6683bafc9d4SJustin T. Gibbs 				cur_patch = STAILQ_NEXT(cur_patch, links);
6693bafc9d4SJustin T. Gibbs 		} else {
6703bafc9d4SJustin T. Gibbs 			/* Accepted this patch.  Advance to the next
6713bafc9d4SJustin T. Gibbs 			 * one and wait for our intruction pointer to
6723bafc9d4SJustin T. Gibbs 			 * hit this point.
6731c147cc3SJustin T. Gibbs 			 */
6743bafc9d4SJustin T. Gibbs 			cur_patch = STAILQ_NEXT(cur_patch, links);
6751c147cc3SJustin T. Gibbs 		}
6763bafc9d4SJustin T. Gibbs 	}
6773bafc9d4SJustin T. Gibbs 
6783bafc9d4SJustin T. Gibbs 	*start_patch = cur_patch;
6793bafc9d4SJustin T. Gibbs 	if (start_instr < *skip_addr)
6803bafc9d4SJustin T. Gibbs 		/* Still skipping */
6813bafc9d4SJustin T. Gibbs 		return (0);
6823bafc9d4SJustin T. Gibbs 
6833bafc9d4SJustin T. Gibbs 	return (1);
6841c147cc3SJustin T. Gibbs }
6851c147cc3SJustin T. Gibbs 
686c5cb3888SJustin T. Gibbs /*
687c5cb3888SJustin T. Gibbs  * Print out error information if appropriate, and clean up before
688c5cb3888SJustin T. Gibbs  * terminating the program.
689c5cb3888SJustin T. Gibbs  */
690c5cb3888SJustin T. Gibbs void
69132da3127SJustin T. Gibbs stop(const char *string, int err_code)
692c5cb3888SJustin T. Gibbs {
693c5cb3888SJustin T. Gibbs 	if (string != NULL) {
694c5cb3888SJustin T. Gibbs 		fprintf(stderr, "%s: ", appname);
695c5cb3888SJustin T. Gibbs 		if (yyfilename != NULL) {
696c5cb3888SJustin T. Gibbs 			fprintf(stderr, "Stopped at file %s, line %d - ",
697c5cb3888SJustin T. Gibbs 				yyfilename, yylineno);
698c5cb3888SJustin T. Gibbs 		}
699c5cb3888SJustin T. Gibbs 		fprintf(stderr, "%s\n", string);
700c5cb3888SJustin T. Gibbs 	}
701c5cb3888SJustin T. Gibbs 
702c5cb3888SJustin T. Gibbs 	if (ofile != NULL) {
703c5cb3888SJustin T. Gibbs 		fclose(ofile);
704c5cb3888SJustin T. Gibbs 		if (err_code != 0) {
705c5cb3888SJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
706c5cb3888SJustin T. Gibbs 				appname, ofilename);
707c5cb3888SJustin T. Gibbs 			unlink(ofilename);
7080ef8c301SJustin T. Gibbs 		}
7090ef8c301SJustin T. Gibbs 	}
7100ef8c301SJustin T. Gibbs 
711f68f348bSJustin T. Gibbs 	if (regfile != NULL) {
712f68f348bSJustin T. Gibbs 		fclose(regfile);
713f68f348bSJustin T. Gibbs 		if (err_code != 0) {
714f68f348bSJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
715f68f348bSJustin T. Gibbs 				appname, regfilename);
716f68f348bSJustin T. Gibbs 			unlink(regfilename);
717f68f348bSJustin T. Gibbs 		}
718f68f348bSJustin T. Gibbs 	}
719f68f348bSJustin T. Gibbs 
720f68f348bSJustin T. Gibbs 	if (listfile != NULL) {
721f68f348bSJustin T. Gibbs 		fclose(listfile);
722f68f348bSJustin T. Gibbs 		if (err_code != 0) {
723f68f348bSJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
724f68f348bSJustin T. Gibbs 				appname, listfilename);
725f68f348bSJustin T. Gibbs 			unlink(listfilename);
726f68f348bSJustin T. Gibbs 		}
727f68f348bSJustin T. Gibbs 	}
728f68f348bSJustin T. Gibbs 
7293bafc9d4SJustin T. Gibbs 	symlist_free(&patch_functions);
730c5cb3888SJustin T. Gibbs 	symtable_close();
731c5cb3888SJustin T. Gibbs 
732c5cb3888SJustin T. Gibbs 	exit(err_code);
733adf51647SJustin T. Gibbs }
734adf51647SJustin T. Gibbs 
735c5cb3888SJustin T. Gibbs struct instruction *
73673c4bad0SEd Schouten seq_alloc(void)
737c5cb3888SJustin T. Gibbs {
738c5cb3888SJustin T. Gibbs 	struct instruction *new_instr;
739c5cb3888SJustin T. Gibbs 
740c5cb3888SJustin T. Gibbs 	new_instr = (struct instruction *)malloc(sizeof(struct instruction));
741c5cb3888SJustin T. Gibbs 	if (new_instr == NULL)
742c5cb3888SJustin T. Gibbs 		stop("Unable to malloc instruction object", EX_SOFTWARE);
743c5cb3888SJustin T. Gibbs 	memset(new_instr, 0, sizeof(*new_instr));
744c5cb3888SJustin T. Gibbs 	STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
745c5cb3888SJustin T. Gibbs 	new_instr->srcline = yylineno;
746c5cb3888SJustin T. Gibbs 	return new_instr;
747adf51647SJustin T. Gibbs }
748c5cb3888SJustin T. Gibbs 
749083d01f2SJustin T. Gibbs critical_section_t *
75073c4bad0SEd Schouten cs_alloc(void)
751083d01f2SJustin T. Gibbs {
752083d01f2SJustin T. Gibbs 	critical_section_t *new_cs;
753083d01f2SJustin T. Gibbs 
754083d01f2SJustin T. Gibbs 	new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
755083d01f2SJustin T. Gibbs 	if (new_cs == NULL)
756083d01f2SJustin T. Gibbs 		stop("Unable to malloc critical_section object", EX_SOFTWARE);
757083d01f2SJustin T. Gibbs 	memset(new_cs, 0, sizeof(*new_cs));
758083d01f2SJustin T. Gibbs 
759083d01f2SJustin T. Gibbs 	TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
760083d01f2SJustin T. Gibbs 	return new_cs;
761083d01f2SJustin T. Gibbs }
762083d01f2SJustin T. Gibbs 
7633bafc9d4SJustin T. Gibbs scope_t *
76473c4bad0SEd Schouten scope_alloc(void)
765c5cb3888SJustin T. Gibbs {
7663bafc9d4SJustin T. Gibbs 	scope_t *new_scope;
767c5cb3888SJustin T. Gibbs 
7683bafc9d4SJustin T. Gibbs 	new_scope = (scope_t *)malloc(sizeof(scope_t));
7693bafc9d4SJustin T. Gibbs 	if (new_scope == NULL)
7703bafc9d4SJustin T. Gibbs 		stop("Unable to malloc scope object", EX_SOFTWARE);
7713bafc9d4SJustin T. Gibbs 	memset(new_scope, 0, sizeof(*new_scope));
7723bafc9d4SJustin T. Gibbs 	TAILQ_INIT(&new_scope->inner_scope);
7733bafc9d4SJustin T. Gibbs 
7743bafc9d4SJustin T. Gibbs 	if (SLIST_FIRST(&scope_stack) != NULL) {
7753bafc9d4SJustin T. Gibbs 		TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
7763bafc9d4SJustin T. Gibbs 				  new_scope, scope_links);
7773bafc9d4SJustin T. Gibbs 	}
7783bafc9d4SJustin T. Gibbs 	/* This patch is now the current scope */
7793bafc9d4SJustin T. Gibbs 	SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
7803bafc9d4SJustin T. Gibbs 	return new_scope;
7813bafc9d4SJustin T. Gibbs }
7823bafc9d4SJustin T. Gibbs 
7833bafc9d4SJustin T. Gibbs void
7843bafc9d4SJustin T. Gibbs process_scope(scope_t *scope)
7853bafc9d4SJustin T. Gibbs {
7863bafc9d4SJustin T. Gibbs 	/*
7873bafc9d4SJustin T. Gibbs 	 * We are "leaving" this scope.  We should now have
7883bafc9d4SJustin T. Gibbs 	 * enough information to process the lists of scopes
7893bafc9d4SJustin T. Gibbs 	 * we encapsulate.
7903bafc9d4SJustin T. Gibbs 	 */
7913bafc9d4SJustin T. Gibbs 	scope_t *cur_scope;
7923bafc9d4SJustin T. Gibbs 	u_int skip_patch_count;
7933bafc9d4SJustin T. Gibbs 	u_int skip_instr_count;
7943bafc9d4SJustin T. Gibbs 
7953bafc9d4SJustin T. Gibbs 	cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
7963bafc9d4SJustin T. Gibbs 	skip_patch_count = 0;
7973bafc9d4SJustin T. Gibbs 	skip_instr_count = 0;
7983bafc9d4SJustin T. Gibbs 	while (cur_scope != NULL) {
7993bafc9d4SJustin T. Gibbs 		u_int patch0_patch_skip;
8003bafc9d4SJustin T. Gibbs 
8013bafc9d4SJustin T. Gibbs 		patch0_patch_skip = 0;
8023bafc9d4SJustin T. Gibbs 		switch (cur_scope->type) {
8033bafc9d4SJustin T. Gibbs 		case SCOPE_IF:
8043bafc9d4SJustin T. Gibbs 		case SCOPE_ELSE_IF:
8053bafc9d4SJustin T. Gibbs 			if (skip_instr_count != 0) {
8063bafc9d4SJustin T. Gibbs 				/* Create a tail patch */
8073bafc9d4SJustin T. Gibbs 				patch0_patch_skip++;
8083bafc9d4SJustin T. Gibbs 				cur_scope->patches[1].skip_patch =
8093bafc9d4SJustin T. Gibbs 				    skip_patch_count + 1;
8103bafc9d4SJustin T. Gibbs 				cur_scope->patches[1].skip_instr =
8113bafc9d4SJustin T. Gibbs 				    skip_instr_count;
8123bafc9d4SJustin T. Gibbs 			}
8133bafc9d4SJustin T. Gibbs 
8143bafc9d4SJustin T. Gibbs 			/* Count Head patch */
8153bafc9d4SJustin T. Gibbs 			patch0_patch_skip++;
8163bafc9d4SJustin T. Gibbs 
8173bafc9d4SJustin T. Gibbs 			/* Count any patches contained in our inner scope */
8183bafc9d4SJustin T. Gibbs 			patch0_patch_skip += cur_scope->inner_scope_patches;
8193bafc9d4SJustin T. Gibbs 
8203bafc9d4SJustin T. Gibbs 			cur_scope->patches[0].skip_patch = patch0_patch_skip;
8213bafc9d4SJustin T. Gibbs 			cur_scope->patches[0].skip_instr =
8223bafc9d4SJustin T. Gibbs 			    cur_scope->end_addr - cur_scope->begin_addr;
8233bafc9d4SJustin T. Gibbs 
8243bafc9d4SJustin T. Gibbs 			skip_instr_count += cur_scope->patches[0].skip_instr;
8253bafc9d4SJustin T. Gibbs 
8263bafc9d4SJustin T. Gibbs 			skip_patch_count += patch0_patch_skip;
8273bafc9d4SJustin T. Gibbs 			if (cur_scope->type == SCOPE_IF) {
8283bafc9d4SJustin T. Gibbs 				scope->inner_scope_patches += skip_patch_count;
8293bafc9d4SJustin T. Gibbs 				skip_patch_count = 0;
8303bafc9d4SJustin T. Gibbs 			        skip_instr_count = 0;
8313bafc9d4SJustin T. Gibbs 			}
8323bafc9d4SJustin T. Gibbs 			break;
8333bafc9d4SJustin T. Gibbs 		case SCOPE_ELSE:
8343bafc9d4SJustin T. Gibbs 			/* Count any patches contained in our innter scope */
8353bafc9d4SJustin T. Gibbs 			skip_patch_count += cur_scope->inner_scope_patches;
8363bafc9d4SJustin T. Gibbs 
8373bafc9d4SJustin T. Gibbs 			skip_instr_count += cur_scope->end_addr
8383bafc9d4SJustin T. Gibbs 					  - cur_scope->begin_addr;
8393bafc9d4SJustin T. Gibbs 			break;
84095a5efc2SJustin T. Gibbs 		case SCOPE_ROOT:
84195a5efc2SJustin T. Gibbs 			stop("Unexpected scope type encountered", EX_SOFTWARE);
84295a5efc2SJustin T. Gibbs 			/* NOTREACHED */
8433bafc9d4SJustin T. Gibbs 		}
8443bafc9d4SJustin T. Gibbs 
8453bafc9d4SJustin T. Gibbs 		cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
8463bafc9d4SJustin T. Gibbs 	}
847adf51647SJustin T. Gibbs }
848