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