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