xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1098ca2bdSWarner Losh /*-
2c5cb3888SJustin T. Gibbs  * Aic7xxx SCSI host adapter firmware asssembler
30ef8c301SJustin T. Gibbs  *
4718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
5718cf2ccSPedro F. Giffuni  *
67ce72dbaSJustin T. Gibbs  * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
763183d8cSJustin T. Gibbs  * Copyright (c) 2001, 2002 Adaptec Inc.
83cddb2a3SJustin T. Gibbs  * All rights reserved.
90ef8c301SJustin T. Gibbs  *
103cddb2a3SJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
113cddb2a3SJustin T. Gibbs  * modification, are permitted provided that the following conditions
123cddb2a3SJustin T. Gibbs  * are met:
133cddb2a3SJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
14f68f348bSJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
157ce72dbaSJustin T. Gibbs  *    without modification.
167ce72dbaSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
177ce72dbaSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
187ce72dbaSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
197ce72dbaSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
207ce72dbaSJustin T. Gibbs  *    binary redistribution.
217ce72dbaSJustin T. Gibbs  * 3. Neither the names of the above-listed copyright holders nor the names
227ce72dbaSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
237ce72dbaSJustin T. Gibbs  *    from this software without specific prior written permission.
240ef8c301SJustin T. Gibbs  *
25aa6dfd9dSJustin T. Gibbs  * Alternatively, this software may be distributed under the terms of the
267ce72dbaSJustin T. Gibbs  * GNU General Public License ("GPL") version 2 as published by the Free
277ce72dbaSJustin T. Gibbs  * Software Foundation.
28aa6dfd9dSJustin T. Gibbs  *
297ce72dbaSJustin T. Gibbs  * NO WARRANTY
307ce72dbaSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
317ce72dbaSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
327ce72dbaSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
337ce72dbaSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
347ce72dbaSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
353cddb2a3SJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
363cddb2a3SJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
377ce72dbaSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
387ce72dbaSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
397ce72dbaSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
407ce72dbaSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
410ef8c301SJustin T. Gibbs  *
4291d00a4fSJustin T. Gibbs  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
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 
56cb0f0a02SEd Maste #if defined(__linux__) || defined(__GLIBC__)
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 
76*6d099821SAlfonso Gregory static void usage(void) __dead2;
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
main(int argc,char * argv[])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':
176d35e1c29SGordon Bergling 			/* Don't complain about the -nostdinc directive */
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) {
258d35e1c29SGordon Bergling 		fprintf(stderr, "%s: No input file specified\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 		/*
285d35e1c29SGordon Bergling 		 * Descend the tree of scopes and insert/emit
2863bafc9d4SJustin T. Gibbs 		 * patches as appropriate.  We perform a depth first
287d35e1c29SGordon Bergling 		 * transversal, 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
usage(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
back_patch(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
output_code(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)) {
370b1721cfbSJustin T. Gibbs 		fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
371fc2ffbe6SPoul-Henning Kamp 			cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
372aa6dfd9dSJustin T. Gibbs #if BYTE_ORDER == LITTLE_ENDIAN
373c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[0],
374c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[1],
375c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[2],
376c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[3]);
377aa6dfd9dSJustin T. Gibbs #else
378aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[3],
379aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[2],
380aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[1],
381aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[0]);
382aa6dfd9dSJustin T. Gibbs #endif
383c5cb3888SJustin T. Gibbs 		instrcount++;
3840ef8c301SJustin T. Gibbs 	}
385b1721cfbSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
3860ef8c301SJustin T. Gibbs 
3877ce72dbaSJustin T. Gibbs 	if (patch_arg_list == NULL)
3887ce72dbaSJustin T. Gibbs 		stop("Patch argument list not defined",
3897ce72dbaSJustin T. Gibbs 		     EX_DATAERR);
3907ce72dbaSJustin T. Gibbs 
391c5cb3888SJustin T. Gibbs 	/*
3923bafc9d4SJustin T. Gibbs 	 *  Output patch information.  Patch functions first.
393c5cb3888SJustin T. Gibbs 	 */
39463183d8cSJustin T. Gibbs 	fprintf(ofile,
39563183d8cSJustin T. Gibbs "typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
39663183d8cSJustin T. Gibbs 
3973bafc9d4SJustin T. Gibbs 	for (cur_node = SLIST_FIRST(&patch_functions);
398c5cb3888SJustin T. Gibbs 	     cur_node != NULL;
3993bafc9d4SJustin T. Gibbs 	     cur_node = SLIST_NEXT(cur_node,links)) {
4003bafc9d4SJustin T. Gibbs 		fprintf(ofile,
40163183d8cSJustin T. Gibbs "static %spatch_func_t %spatch%d_func;\n"
4029b2af00eSJustin T. Gibbs "\n"
4039b2af00eSJustin T. Gibbs "static int\n"
40463183d8cSJustin T. Gibbs "%spatch%d_func(%s)\n"
4059b2af00eSJustin T. Gibbs "{\n"
4069b2af00eSJustin T. Gibbs "	return (%s);\n"
4079b2af00eSJustin T. Gibbs "}\n\n",
40863183d8cSJustin T. Gibbs 			prefix,
40963183d8cSJustin T. Gibbs 			prefix,
4103bafc9d4SJustin T. Gibbs 			cur_node->symbol->info.condinfo->func_num,
41163183d8cSJustin T. Gibbs 			prefix,
4123bafc9d4SJustin T. Gibbs 			cur_node->symbol->info.condinfo->func_num,
4137ce72dbaSJustin T. Gibbs 			patch_arg_list,
4143bafc9d4SJustin T. Gibbs 			cur_node->symbol->name);
415c5cb3888SJustin T. Gibbs 	}
416adf51647SJustin T. Gibbs 
417c5cb3888SJustin T. Gibbs 	fprintf(ofile,
4189b2af00eSJustin T. Gibbs "static struct patch {\n"
41963183d8cSJustin T. Gibbs "	%spatch_func_t		*patch_func;\n"
4209b2af00eSJustin T. Gibbs "	uint32_t		 begin		:10,\n"
4219b2af00eSJustin T. Gibbs "				 skip_instr	:10,\n"
4229b2af00eSJustin T. Gibbs "				 skip_patch	:12;\n"
42363183d8cSJustin T. Gibbs "} patches[] = {\n", prefix);
424c5cb3888SJustin T. Gibbs 
4253bafc9d4SJustin T. Gibbs 	for (cur_patch = STAILQ_FIRST(&patches);
426c5cb3888SJustin T. Gibbs 	     cur_patch != NULL;
4273bafc9d4SJustin T. Gibbs 	     cur_patch = STAILQ_NEXT(cur_patch,links)) {
42863183d8cSJustin T. Gibbs 		fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
429b1721cfbSJustin T. Gibbs 			cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
43063183d8cSJustin T. Gibbs 			prefix,
4313bafc9d4SJustin T. Gibbs 			cur_patch->patch_func, cur_patch->begin,
4323bafc9d4SJustin T. Gibbs 			cur_patch->skip_instr, cur_patch->skip_patch);
4333bafc9d4SJustin T. Gibbs 	}
434c5cb3888SJustin T. Gibbs 
4359b2af00eSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
436c5cb3888SJustin T. Gibbs 
437083d01f2SJustin T. Gibbs 	fprintf(ofile,
4389b2af00eSJustin T. Gibbs "static struct cs {\n"
43963183d8cSJustin T. Gibbs "	uint16_t	begin;\n"
44063183d8cSJustin T. Gibbs "	uint16_t	end;\n"
4419b2af00eSJustin T. Gibbs "} critical_sections[] = {\n");
442083d01f2SJustin T. Gibbs 
443083d01f2SJustin T. Gibbs 	for (cs = TAILQ_FIRST(&cs_tailq);
444083d01f2SJustin T. Gibbs 	     cs != NULL;
445083d01f2SJustin T. Gibbs 	     cs = TAILQ_NEXT(cs, links)) {
446b1721cfbSJustin T. Gibbs 		fprintf(ofile, "%s\t{ %d, %d }",
447b1721cfbSJustin T. Gibbs 			cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
448083d01f2SJustin T. Gibbs 			cs->begin_addr, cs->end_addr);
449083d01f2SJustin T. Gibbs 	}
450083d01f2SJustin T. Gibbs 
4519b2af00eSJustin T. Gibbs 	fprintf(ofile, "\n};\n\n");
452083d01f2SJustin T. Gibbs 
453b1721cfbSJustin T. Gibbs 	fprintf(ofile,
4549b2af00eSJustin T. Gibbs "static const int num_critical_sections = sizeof(critical_sections)\n"
4559b2af00eSJustin T. Gibbs "				       / sizeof(*critical_sections);\n");
456b1721cfbSJustin T. Gibbs 
457c5cb3888SJustin T. Gibbs 	fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
4580ef8c301SJustin T. Gibbs }
4590ef8c301SJustin T. Gibbs 
46095a5efc2SJustin T. Gibbs static void
dump_scope(scope_t * scope)4613bafc9d4SJustin T. Gibbs dump_scope(scope_t *scope)
462c5cb3888SJustin T. Gibbs {
4633bafc9d4SJustin T. Gibbs 	scope_t *cur_scope;
4643bafc9d4SJustin T. Gibbs 
4653bafc9d4SJustin T. Gibbs 	/*
4663bafc9d4SJustin T. Gibbs 	 * Emit the first patch for this scope
4673bafc9d4SJustin T. Gibbs 	 */
4683bafc9d4SJustin T. Gibbs 	emit_patch(scope, 0);
4693bafc9d4SJustin T. Gibbs 
4703bafc9d4SJustin T. Gibbs 	/*
4713bafc9d4SJustin T. Gibbs 	 * Dump each scope within this one.
4723bafc9d4SJustin T. Gibbs 	 */
4733bafc9d4SJustin T. Gibbs 	cur_scope = TAILQ_FIRST(&scope->inner_scope);
4743bafc9d4SJustin T. Gibbs 
4753bafc9d4SJustin T. Gibbs 	while (cur_scope != NULL) {
4763bafc9d4SJustin T. Gibbs 		dump_scope(cur_scope);
4773bafc9d4SJustin T. Gibbs 
4783bafc9d4SJustin T. Gibbs 		cur_scope = TAILQ_NEXT(cur_scope, scope_links);
4793bafc9d4SJustin T. Gibbs 	}
4803bafc9d4SJustin T. Gibbs 
4813bafc9d4SJustin T. Gibbs 	/*
4823bafc9d4SJustin T. Gibbs 	 * Emit the second, closing, patch for this scope
4833bafc9d4SJustin T. Gibbs 	 */
4843bafc9d4SJustin T. Gibbs 	emit_patch(scope, 1);
4853bafc9d4SJustin T. Gibbs }
4863bafc9d4SJustin T. Gibbs 
4873bafc9d4SJustin T. Gibbs void
emit_patch(scope_t * scope,int patch)4883bafc9d4SJustin T. Gibbs emit_patch(scope_t *scope, int patch)
4893bafc9d4SJustin T. Gibbs {
4903bafc9d4SJustin T. Gibbs 	patch_info_t *pinfo;
4913bafc9d4SJustin T. Gibbs 	patch_t *new_patch;
4923bafc9d4SJustin T. Gibbs 
4933bafc9d4SJustin T. Gibbs 	pinfo = &scope->patches[patch];
4943bafc9d4SJustin T. Gibbs 
4953bafc9d4SJustin T. Gibbs 	if (pinfo->skip_instr == 0)
4963bafc9d4SJustin T. Gibbs 		/* No-Op patch */
4973bafc9d4SJustin T. Gibbs 		return;
4983bafc9d4SJustin T. Gibbs 
4993bafc9d4SJustin T. Gibbs 	new_patch = (patch_t *)malloc(sizeof(*new_patch));
5003bafc9d4SJustin T. Gibbs 
5013bafc9d4SJustin T. Gibbs 	if (new_patch == NULL)
5023bafc9d4SJustin T. Gibbs 		stop("Could not malloc patch structure", EX_OSERR);
5033bafc9d4SJustin T. Gibbs 
5043bafc9d4SJustin T. Gibbs 	memset(new_patch, 0, sizeof(*new_patch));
5053bafc9d4SJustin T. Gibbs 
5063bafc9d4SJustin T. Gibbs 	if (patch == 0) {
5073bafc9d4SJustin T. Gibbs 		new_patch->patch_func = scope->func_num;
5083bafc9d4SJustin T. Gibbs 		new_patch->begin = scope->begin_addr;
5093bafc9d4SJustin T. Gibbs 	} else {
5103bafc9d4SJustin T. Gibbs 		new_patch->patch_func = 0;
5113bafc9d4SJustin T. Gibbs 		new_patch->begin = scope->end_addr;
5123bafc9d4SJustin T. Gibbs 	}
5133bafc9d4SJustin T. Gibbs 	new_patch->skip_instr = pinfo->skip_instr;
5143bafc9d4SJustin T. Gibbs 	new_patch->skip_patch = pinfo->skip_patch;
5153bafc9d4SJustin T. Gibbs 	STAILQ_INSERT_TAIL(&patches, new_patch, links);
5163bafc9d4SJustin T. Gibbs }
5173bafc9d4SJustin T. Gibbs 
5183bafc9d4SJustin T. Gibbs void
output_listing(char * ifilename)519aa6dfd9dSJustin T. Gibbs output_listing(char *ifilename)
5203bafc9d4SJustin T. Gibbs {
5213bafc9d4SJustin T. Gibbs 	char buf[1024];
522c5cb3888SJustin T. Gibbs 	FILE *ifile;
523c5cb3888SJustin T. Gibbs 	struct instruction *cur_instr;
5243bafc9d4SJustin T. Gibbs 	patch_t *cur_patch;
5253bafc9d4SJustin T. Gibbs 	symbol_node_t *cur_func;
5263bafc9d4SJustin T. Gibbs 	int *func_values;
527c5cb3888SJustin T. Gibbs 	int instrcount;
5281c147cc3SJustin T. Gibbs 	int instrptr;
529b18a2ef1SXin LI 	unsigned int line;
5303bafc9d4SJustin T. Gibbs 	int func_count;
531cec20e14SDimitry Andric 	unsigned int skip_addr;
532c5cb3888SJustin T. Gibbs 
533c5cb3888SJustin T. Gibbs 	instrcount = 0;
5341c147cc3SJustin T. Gibbs 	instrptr = 0;
535c5cb3888SJustin T. Gibbs 	line = 1;
5363bafc9d4SJustin T. Gibbs 	skip_addr = 0;
537c5cb3888SJustin T. Gibbs 	if ((ifile = fopen(ifilename, "r")) == NULL) {
538c5cb3888SJustin T. Gibbs 		perror(ifilename);
539c5cb3888SJustin T. Gibbs 		stop(NULL, EX_DATAERR);
540c5cb3888SJustin T. Gibbs 	}
5411c147cc3SJustin T. Gibbs 
5421c147cc3SJustin T. Gibbs 	/*
5431c147cc3SJustin T. Gibbs 	 * Determine which options to apply to this listing.
5441c147cc3SJustin T. Gibbs 	 */
5453bafc9d4SJustin T. Gibbs 	for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
5463bafc9d4SJustin T. Gibbs 	    cur_func != NULL;
5473bafc9d4SJustin T. Gibbs 	    cur_func = SLIST_NEXT(cur_func, links))
5483bafc9d4SJustin T. Gibbs 		func_count++;
5491c147cc3SJustin T. Gibbs 
55032da3127SJustin T. Gibbs 	func_values = NULL;
5513bafc9d4SJustin T. Gibbs 	if (func_count != 0) {
5523bafc9d4SJustin T. Gibbs 		func_values = (int *)malloc(func_count * sizeof(int));
5533bafc9d4SJustin T. Gibbs 
5543bafc9d4SJustin T. Gibbs 		if (func_values == NULL)
5553bafc9d4SJustin T. Gibbs 			stop("Could not malloc", EX_OSERR);
5563bafc9d4SJustin T. Gibbs 
5573bafc9d4SJustin T. Gibbs 		func_values[0] = 0; /* FALSE func */
5583bafc9d4SJustin T. Gibbs 		func_count--;
5593bafc9d4SJustin T. Gibbs 
5603bafc9d4SJustin T. Gibbs 		/*
5613bafc9d4SJustin T. Gibbs 		 * Ask the user to fill in the return values for
5623bafc9d4SJustin T. Gibbs 		 * the rest of the functions.
5633bafc9d4SJustin T. Gibbs 		 */
5643bafc9d4SJustin T. Gibbs 
5653bafc9d4SJustin T. Gibbs 
5663bafc9d4SJustin T. Gibbs 		for (cur_func = SLIST_FIRST(&patch_functions);
5673bafc9d4SJustin T. Gibbs 		     cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
5683bafc9d4SJustin T. Gibbs 		     cur_func = SLIST_NEXT(cur_func, links), func_count--) {
5693bafc9d4SJustin T. Gibbs 			int input;
5703bafc9d4SJustin T. Gibbs 
5713bafc9d4SJustin T. Gibbs 			fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
5723bafc9d4SJustin T. Gibbs 			fprintf(stdout,
5733bafc9d4SJustin T. Gibbs 				"Enter the return value for "
5743bafc9d4SJustin T. Gibbs 				"this expression[T/F]:");
5753bafc9d4SJustin T. Gibbs 
5763bafc9d4SJustin T. Gibbs 			while (1) {
5773bafc9d4SJustin T. Gibbs 				input = getchar();
5783bafc9d4SJustin T. Gibbs 				input = toupper(input);
5793bafc9d4SJustin T. Gibbs 
5803bafc9d4SJustin T. Gibbs 				if (input == 'T') {
5813bafc9d4SJustin T. Gibbs 					func_values[func_count] = 1;
5823bafc9d4SJustin T. Gibbs 					break;
5833bafc9d4SJustin T. Gibbs 				} else if (input == 'F') {
5843bafc9d4SJustin T. Gibbs 					func_values[func_count] = 0;
5853bafc9d4SJustin T. Gibbs 					break;
5861c147cc3SJustin T. Gibbs 				}
5873bafc9d4SJustin T. Gibbs 			}
588e287abc8SJustin T. Gibbs 			if (isatty(fileno(stdin)) == 0)
589e287abc8SJustin T. Gibbs 				putchar(input);
5903bafc9d4SJustin T. Gibbs 		}
5913bafc9d4SJustin T. Gibbs 		fprintf(stdout, "\nThanks!\n");
5921c147cc3SJustin T. Gibbs 	}
5931c147cc3SJustin T. Gibbs 
5943bafc9d4SJustin T. Gibbs 	/* Now output the listing */
5953bafc9d4SJustin T. Gibbs 	cur_patch = STAILQ_FIRST(&patches);
5963bafc9d4SJustin T. Gibbs 	for (cur_instr = STAILQ_FIRST(&seq_program);
597c5cb3888SJustin T. Gibbs 	     cur_instr != NULL;
5983bafc9d4SJustin T. Gibbs 	     cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
5993bafc9d4SJustin T. Gibbs 		if (check_patch(&cur_patch, instrcount,
6003bafc9d4SJustin T. Gibbs 				&skip_addr, func_values) == 0) {
6011c147cc3SJustin T. Gibbs 			/* Don't count this instruction as it is in a patch
6021c147cc3SJustin T. Gibbs 			 * that was removed.
6031c147cc3SJustin T. Gibbs 			 */
6041c147cc3SJustin T. Gibbs                         continue;
6053bafc9d4SJustin T. Gibbs 		}
6061c147cc3SJustin T. Gibbs 
607c5cb3888SJustin T. Gibbs 		while (line < cur_instr->srcline) {
608c5cb3888SJustin T. Gibbs 			fgets(buf, sizeof(buf), ifile);
60991d00a4fSJustin T. Gibbs 				fprintf(listfile, "             \t%s", buf);
610c5cb3888SJustin T. Gibbs 				line++;
611c5cb3888SJustin T. Gibbs 		}
61291d00a4fSJustin T. Gibbs 		fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
613aa6dfd9dSJustin T. Gibbs #if BYTE_ORDER == LITTLE_ENDIAN
614c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[0],
615c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[1],
616c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[2],
617c5cb3888SJustin T. Gibbs 			cur_instr->format.bytes[3]);
618aa6dfd9dSJustin T. Gibbs #else
619aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[3],
620aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[2],
621aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[1],
622aa6dfd9dSJustin T. Gibbs 			cur_instr->format.bytes[0]);
623aa6dfd9dSJustin T. Gibbs #endif
62491d00a4fSJustin T. Gibbs 		/*
62591d00a4fSJustin T. Gibbs 		 * Macro expansions can cause several instructions
62691d00a4fSJustin T. Gibbs 		 * to be output for a single source line.  Only
62791d00a4fSJustin T. Gibbs 		 * advance the line once in these cases.
62891d00a4fSJustin T. Gibbs 		 */
62991d00a4fSJustin T. Gibbs 		if (line == cur_instr->srcline) {
630c5cb3888SJustin T. Gibbs 			fgets(buf, sizeof(buf), ifile);
6311c147cc3SJustin T. Gibbs 			fprintf(listfile, "\t%s", buf);
632c5cb3888SJustin T. Gibbs 			line++;
63391d00a4fSJustin T. Gibbs 		} else {
63491d00a4fSJustin T. Gibbs 			fprintf(listfile, "\n");
63591d00a4fSJustin T. Gibbs 		}
6361c147cc3SJustin T. Gibbs 		instrptr++;
637c5cb3888SJustin T. Gibbs 	}
63856d7cd7cSChristian Brueffer 	free(func_values);
63956d7cd7cSChristian Brueffer 
6401c147cc3SJustin T. Gibbs 	/* Dump the remainder of the file */
6411c147cc3SJustin T. Gibbs 	while(fgets(buf, sizeof(buf), ifile) != NULL)
64291d00a4fSJustin T. Gibbs 		fprintf(listfile, "             %s", buf);
6431c147cc3SJustin T. Gibbs 
644c5cb3888SJustin T. Gibbs 	fclose(ifile);
645c5cb3888SJustin T. Gibbs }
646c5cb3888SJustin T. Gibbs 
6473bafc9d4SJustin T. Gibbs static int
check_patch(patch_t ** start_patch,unsigned int start_instr,unsigned int * skip_addr,int * func_vals)648b18a2ef1SXin LI check_patch(patch_t **start_patch, unsigned int start_instr,
649b18a2ef1SXin LI 	    unsigned int *skip_addr, int *func_vals)
6501c147cc3SJustin T. Gibbs {
6513bafc9d4SJustin T. Gibbs 	patch_t *cur_patch;
6523bafc9d4SJustin T. Gibbs 
6533bafc9d4SJustin T. Gibbs 	cur_patch = *start_patch;
6543bafc9d4SJustin T. Gibbs 
6553bafc9d4SJustin T. Gibbs 	while (cur_patch != NULL && start_instr == cur_patch->begin) {
6563bafc9d4SJustin T. Gibbs 		if (func_vals[cur_patch->patch_func] == 0) {
6573bafc9d4SJustin T. Gibbs 			int skip;
6583bafc9d4SJustin T. Gibbs 
6593bafc9d4SJustin T. Gibbs 			/* Start rejecting code */
6603bafc9d4SJustin T. Gibbs 			*skip_addr = start_instr + cur_patch->skip_instr;
6613bafc9d4SJustin T. Gibbs 			for (skip = cur_patch->skip_patch;
6623bafc9d4SJustin T. Gibbs 			     skip > 0 && cur_patch != NULL;
6633bafc9d4SJustin T. Gibbs 			     skip--)
6643bafc9d4SJustin T. Gibbs 				cur_patch = STAILQ_NEXT(cur_patch, links);
6653bafc9d4SJustin T. Gibbs 		} else {
6663bafc9d4SJustin T. Gibbs 			/* Accepted this patch.  Advance to the next
667594c945aSPedro F. Giffuni 			 * one and wait for our instruction pointer to
6683bafc9d4SJustin T. Gibbs 			 * hit this point.
6691c147cc3SJustin T. Gibbs 			 */
6703bafc9d4SJustin T. Gibbs 			cur_patch = STAILQ_NEXT(cur_patch, links);
6711c147cc3SJustin T. Gibbs 		}
6723bafc9d4SJustin T. Gibbs 	}
6733bafc9d4SJustin T. Gibbs 
6743bafc9d4SJustin T. Gibbs 	*start_patch = cur_patch;
6753bafc9d4SJustin T. Gibbs 	if (start_instr < *skip_addr)
6763bafc9d4SJustin T. Gibbs 		/* Still skipping */
6773bafc9d4SJustin T. Gibbs 		return (0);
6783bafc9d4SJustin T. Gibbs 
6793bafc9d4SJustin T. Gibbs 	return (1);
6801c147cc3SJustin T. Gibbs }
6811c147cc3SJustin T. Gibbs 
682c5cb3888SJustin T. Gibbs /*
683c5cb3888SJustin T. Gibbs  * Print out error information if appropriate, and clean up before
684c5cb3888SJustin T. Gibbs  * terminating the program.
685c5cb3888SJustin T. Gibbs  */
686c5cb3888SJustin T. Gibbs void
stop(const char * string,int err_code)68732da3127SJustin T. Gibbs stop(const char *string, int err_code)
688c5cb3888SJustin T. Gibbs {
689c5cb3888SJustin T. Gibbs 	if (string != NULL) {
690c5cb3888SJustin T. Gibbs 		fprintf(stderr, "%s: ", appname);
691c5cb3888SJustin T. Gibbs 		if (yyfilename != NULL) {
692c5cb3888SJustin T. Gibbs 			fprintf(stderr, "Stopped at file %s, line %d - ",
693c5cb3888SJustin T. Gibbs 				yyfilename, yylineno);
694c5cb3888SJustin T. Gibbs 		}
695c5cb3888SJustin T. Gibbs 		fprintf(stderr, "%s\n", string);
696c5cb3888SJustin T. Gibbs 	}
697c5cb3888SJustin T. Gibbs 
698c5cb3888SJustin T. Gibbs 	if (ofile != NULL) {
699c5cb3888SJustin T. Gibbs 		fclose(ofile);
700c5cb3888SJustin T. Gibbs 		if (err_code != 0) {
701c5cb3888SJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
702c5cb3888SJustin T. Gibbs 				appname, ofilename);
703c5cb3888SJustin T. Gibbs 			unlink(ofilename);
7040ef8c301SJustin T. Gibbs 		}
7050ef8c301SJustin T. Gibbs 	}
7060ef8c301SJustin T. Gibbs 
707f68f348bSJustin T. Gibbs 	if (regfile != NULL) {
708f68f348bSJustin T. Gibbs 		fclose(regfile);
709f68f348bSJustin T. Gibbs 		if (err_code != 0) {
710f68f348bSJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
711f68f348bSJustin T. Gibbs 				appname, regfilename);
712f68f348bSJustin T. Gibbs 			unlink(regfilename);
713f68f348bSJustin T. Gibbs 		}
714f68f348bSJustin T. Gibbs 	}
715f68f348bSJustin T. Gibbs 
716f68f348bSJustin T. Gibbs 	if (listfile != NULL) {
717f68f348bSJustin T. Gibbs 		fclose(listfile);
718f68f348bSJustin T. Gibbs 		if (err_code != 0) {
719f68f348bSJustin T. Gibbs 			fprintf(stderr, "%s: Removing %s due to error\n",
720f68f348bSJustin T. Gibbs 				appname, listfilename);
721f68f348bSJustin T. Gibbs 			unlink(listfilename);
722f68f348bSJustin T. Gibbs 		}
723f68f348bSJustin T. Gibbs 	}
724f68f348bSJustin T. Gibbs 
7253bafc9d4SJustin T. Gibbs 	symlist_free(&patch_functions);
726c5cb3888SJustin T. Gibbs 	symtable_close();
727c5cb3888SJustin T. Gibbs 
728c5cb3888SJustin T. Gibbs 	exit(err_code);
729adf51647SJustin T. Gibbs }
730adf51647SJustin T. Gibbs 
731c5cb3888SJustin T. Gibbs struct instruction *
seq_alloc(void)73273c4bad0SEd Schouten seq_alloc(void)
733c5cb3888SJustin T. Gibbs {
734c5cb3888SJustin T. Gibbs 	struct instruction *new_instr;
735c5cb3888SJustin T. Gibbs 
736c5cb3888SJustin T. Gibbs 	new_instr = (struct instruction *)malloc(sizeof(struct instruction));
737c5cb3888SJustin T. Gibbs 	if (new_instr == NULL)
738c5cb3888SJustin T. Gibbs 		stop("Unable to malloc instruction object", EX_SOFTWARE);
739c5cb3888SJustin T. Gibbs 	memset(new_instr, 0, sizeof(*new_instr));
740c5cb3888SJustin T. Gibbs 	STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
741c5cb3888SJustin T. Gibbs 	new_instr->srcline = yylineno;
742c5cb3888SJustin T. Gibbs 	return new_instr;
743adf51647SJustin T. Gibbs }
744c5cb3888SJustin T. Gibbs 
745083d01f2SJustin T. Gibbs critical_section_t *
cs_alloc(void)74673c4bad0SEd Schouten cs_alloc(void)
747083d01f2SJustin T. Gibbs {
748083d01f2SJustin T. Gibbs 	critical_section_t *new_cs;
749083d01f2SJustin T. Gibbs 
750083d01f2SJustin T. Gibbs 	new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
751083d01f2SJustin T. Gibbs 	if (new_cs == NULL)
752083d01f2SJustin T. Gibbs 		stop("Unable to malloc critical_section object", EX_SOFTWARE);
753083d01f2SJustin T. Gibbs 	memset(new_cs, 0, sizeof(*new_cs));
754083d01f2SJustin T. Gibbs 
755083d01f2SJustin T. Gibbs 	TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
756083d01f2SJustin T. Gibbs 	return new_cs;
757083d01f2SJustin T. Gibbs }
758083d01f2SJustin T. Gibbs 
7593bafc9d4SJustin T. Gibbs scope_t *
scope_alloc(void)76073c4bad0SEd Schouten scope_alloc(void)
761c5cb3888SJustin T. Gibbs {
7623bafc9d4SJustin T. Gibbs 	scope_t *new_scope;
763c5cb3888SJustin T. Gibbs 
7643bafc9d4SJustin T. Gibbs 	new_scope = (scope_t *)malloc(sizeof(scope_t));
7653bafc9d4SJustin T. Gibbs 	if (new_scope == NULL)
7663bafc9d4SJustin T. Gibbs 		stop("Unable to malloc scope object", EX_SOFTWARE);
7673bafc9d4SJustin T. Gibbs 	memset(new_scope, 0, sizeof(*new_scope));
7683bafc9d4SJustin T. Gibbs 	TAILQ_INIT(&new_scope->inner_scope);
7693bafc9d4SJustin T. Gibbs 
7703bafc9d4SJustin T. Gibbs 	if (SLIST_FIRST(&scope_stack) != NULL) {
7713bafc9d4SJustin T. Gibbs 		TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
7723bafc9d4SJustin T. Gibbs 				  new_scope, scope_links);
7733bafc9d4SJustin T. Gibbs 	}
7743bafc9d4SJustin T. Gibbs 	/* This patch is now the current scope */
7753bafc9d4SJustin T. Gibbs 	SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
7763bafc9d4SJustin T. Gibbs 	return new_scope;
7773bafc9d4SJustin T. Gibbs }
7783bafc9d4SJustin T. Gibbs 
7793bafc9d4SJustin T. Gibbs void
process_scope(scope_t * scope)7803bafc9d4SJustin T. Gibbs process_scope(scope_t *scope)
7813bafc9d4SJustin T. Gibbs {
7823bafc9d4SJustin T. Gibbs 	/*
7833bafc9d4SJustin T. Gibbs 	 * We are "leaving" this scope.  We should now have
7843bafc9d4SJustin T. Gibbs 	 * enough information to process the lists of scopes
7853bafc9d4SJustin T. Gibbs 	 * we encapsulate.
7863bafc9d4SJustin T. Gibbs 	 */
7873bafc9d4SJustin T. Gibbs 	scope_t *cur_scope;
7883bafc9d4SJustin T. Gibbs 	u_int skip_patch_count;
7893bafc9d4SJustin T. Gibbs 	u_int skip_instr_count;
7903bafc9d4SJustin T. Gibbs 
7913bafc9d4SJustin T. Gibbs 	cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
7923bafc9d4SJustin T. Gibbs 	skip_patch_count = 0;
7933bafc9d4SJustin T. Gibbs 	skip_instr_count = 0;
7943bafc9d4SJustin T. Gibbs 	while (cur_scope != NULL) {
7953bafc9d4SJustin T. Gibbs 		u_int patch0_patch_skip;
7963bafc9d4SJustin T. Gibbs 
7973bafc9d4SJustin T. Gibbs 		patch0_patch_skip = 0;
7983bafc9d4SJustin T. Gibbs 		switch (cur_scope->type) {
7993bafc9d4SJustin T. Gibbs 		case SCOPE_IF:
8003bafc9d4SJustin T. Gibbs 		case SCOPE_ELSE_IF:
8013bafc9d4SJustin T. Gibbs 			if (skip_instr_count != 0) {
8023bafc9d4SJustin T. Gibbs 				/* Create a tail patch */
8033bafc9d4SJustin T. Gibbs 				patch0_patch_skip++;
8043bafc9d4SJustin T. Gibbs 				cur_scope->patches[1].skip_patch =
8053bafc9d4SJustin T. Gibbs 				    skip_patch_count + 1;
8063bafc9d4SJustin T. Gibbs 				cur_scope->patches[1].skip_instr =
8073bafc9d4SJustin T. Gibbs 				    skip_instr_count;
8083bafc9d4SJustin T. Gibbs 			}
8093bafc9d4SJustin T. Gibbs 
8103bafc9d4SJustin T. Gibbs 			/* Count Head patch */
8113bafc9d4SJustin T. Gibbs 			patch0_patch_skip++;
8123bafc9d4SJustin T. Gibbs 
8133bafc9d4SJustin T. Gibbs 			/* Count any patches contained in our inner scope */
8143bafc9d4SJustin T. Gibbs 			patch0_patch_skip += cur_scope->inner_scope_patches;
8153bafc9d4SJustin T. Gibbs 
8163bafc9d4SJustin T. Gibbs 			cur_scope->patches[0].skip_patch = patch0_patch_skip;
8173bafc9d4SJustin T. Gibbs 			cur_scope->patches[0].skip_instr =
8183bafc9d4SJustin T. Gibbs 			    cur_scope->end_addr - cur_scope->begin_addr;
8193bafc9d4SJustin T. Gibbs 
8203bafc9d4SJustin T. Gibbs 			skip_instr_count += cur_scope->patches[0].skip_instr;
8213bafc9d4SJustin T. Gibbs 
8223bafc9d4SJustin T. Gibbs 			skip_patch_count += patch0_patch_skip;
8233bafc9d4SJustin T. Gibbs 			if (cur_scope->type == SCOPE_IF) {
8243bafc9d4SJustin T. Gibbs 				scope->inner_scope_patches += skip_patch_count;
8253bafc9d4SJustin T. Gibbs 				skip_patch_count = 0;
8263bafc9d4SJustin T. Gibbs 			        skip_instr_count = 0;
8273bafc9d4SJustin T. Gibbs 			}
8283bafc9d4SJustin T. Gibbs 			break;
8293bafc9d4SJustin T. Gibbs 		case SCOPE_ELSE:
8303bafc9d4SJustin T. Gibbs 			/* Count any patches contained in our innter scope */
8313bafc9d4SJustin T. Gibbs 			skip_patch_count += cur_scope->inner_scope_patches;
8323bafc9d4SJustin T. Gibbs 
8333bafc9d4SJustin T. Gibbs 			skip_instr_count += cur_scope->end_addr
8343bafc9d4SJustin T. Gibbs 					  - cur_scope->begin_addr;
8353bafc9d4SJustin T. Gibbs 			break;
83695a5efc2SJustin T. Gibbs 		case SCOPE_ROOT:
83795a5efc2SJustin T. Gibbs 			stop("Unexpected scope type encountered", EX_SOFTWARE);
83895a5efc2SJustin T. Gibbs 			/* NOTREACHED */
8393bafc9d4SJustin T. Gibbs 		}
8403bafc9d4SJustin T. Gibbs 
8413bafc9d4SJustin T. Gibbs 		cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
8423bafc9d4SJustin T. Gibbs 	}
843adf51647SJustin T. Gibbs }
844