11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 242b2aa86c6670347a2a07e6d7af0e0ecc8fdbff9Justin P. Mattock * Aic7xxx SCSI host adapter firmware assembler 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2001, 2002 Adaptec Inc. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Redistribution and use in source and binary forms, with or without 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modification, are permitted provided that the following conditions 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are met: 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Redistributions of source code must retain the above copyright 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * notice, this list of conditions, and the following disclaimer, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without modification. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. Redistributions in binary form must reproduce at minimum a disclaimer 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * substantially similar to the "NO WARRANTY" disclaimer below 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ("Disclaimer") and any redistribution must be conditioned upon 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * including a substantially similar Disclaimer requirement for further 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * binary redistribution. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. Neither the names of the above-listed copyright holders nor the names 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of any contributors may be used to endorse or promote products derived 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from this software without specific prior written permission. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternatively, this software may be distributed under the terms of the 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License ("GPL") version 2 as published by the Free 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software Foundation. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NO WARRANTY 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * POSSIBILITY OF SUCH DAMAGES. 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 402628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $FreeBSD$ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/types.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/mman.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <ctype.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <inttypes.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <regex.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdio.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdlib.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sysexits.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <unistd.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if linux 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <endian.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <machine/endian.h> 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aicasm.h" 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aicasm_symbol.h" 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aicasm_insformat.h" 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct patch { 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STAILQ_ENTRY(patch) links; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int patch_func; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int begin; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int skip_instr; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int skip_patch; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} patch_t; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSTAILQ_HEAD(patch_list, patch) patches; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void usage(void); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void back_patch(void); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void output_code(void); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void output_listing(char *ifilename); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dump_scope(scope_t *scope); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void emit_patch(scope_t *scope, int patch); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_patch(patch_t **start_patch, int start_instr, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int *skip_addr, int *func_vals); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct path_list search_path; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint includes_search_curdir; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *appname; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *stock_include_file; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFILE *ofile; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *ofilename; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *regfilename; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFILE *regfile; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *listfilename; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFILE *listfile; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *regdiagfilename; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFILE *regdiagfile; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint src_mode; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint dst_mode; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic STAILQ_HEAD(,instruction) seq_program; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cs_tailq cs_tailq; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct scope_list scope_stack; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssymlist_t patch_functions; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int yy_flex_debug; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int mm_flex_debug; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int yydebug; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int mmdebug; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern FILE *yyin; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int yyparse(void); 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint main(int argc, char *argv[]); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmain(int argc, char *argv[]) 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern char *optarg; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern int optind; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ch; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *inputfilename; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scope_t *sentinal; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STAILQ_INIT(&patches); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SLIST_INIT(&search_path); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STAILQ_INIT(&seq_program); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TAILQ_INIT(&cs_tailq); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SLIST_INIT(&scope_stack); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set Sentinal scope node */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sentinal = scope_alloc(); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sentinal->type = SCOPE_ROOT; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds includes_search_curdir = 1; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname = *argv; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regfile = NULL; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds listfile = NULL; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yy_flex_debug = 0; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mm_flex_debug = 0; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yydebug = 0; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmdebug = 0; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:")) != -1) { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(ch) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'd': 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp(optarg, "s") == 0) { 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yy_flex_debug = 1; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mm_flex_debug = 1; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (strcmp(optarg, "p") == 0) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yydebug = 1; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mmdebug = 1; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: -d Requires either an " 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "'s' or 'p' argument\n", appname); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usage(); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("-d: Assembler not built with debugging " 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "information", EX_SOFTWARE); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'i': 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stock_include_file = optarg; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'l': 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create a program listing */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((listfile = fopen(optarg, "w")) == NULL) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_CANTCREAT); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds listfilename = optarg; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'n': 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't complain about the -nostdinc directrive */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp(optarg, "ostdinc")) { 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: Unknown option -%c%s\n", 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname, ch, optarg); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usage(); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'o': 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ofile = fopen(optarg, "w")) == NULL) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_CANTCREAT); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofilename = optarg; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'p': 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create Register Diagnostic "printing" Functions */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((regdiagfile = fopen(optarg, "w")) == NULL) { 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_CANTCREAT); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regdiagfilename = optarg; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'r': 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((regfile = fopen(optarg, "w")) == NULL) { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_CANTCREAT); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regfilename = optarg; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'I': 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds path_entry_t include_dir; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp(optarg, "-") == 0) { 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (includes_search_curdir == 0) { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: Warning - '-I-' " 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified multiple " 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "times\n", appname); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds includes_search_curdir = 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (include_dir = SLIST_FIRST(&search_path); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir != NULL; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir = SLIST_NEXT(include_dir, 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds links)) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All entries before a '-I-' only 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * apply to includes specified with 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * quotes instead of "<>". 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir->quoted_includes_only = 1; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir = 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (path_entry_t)malloc(sizeof(*include_dir)); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (include_dir == NULL) { 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_OSERR); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir->directory = strdup(optarg); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (include_dir->directory == NULL) { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(optarg); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_OSERR); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_dir->quoted_includes_only = 0; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SLIST_INSERT_HEAD(&search_path, include_dir, 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds links); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '?': 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usage(); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds argc -= optind; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds argv += optind; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (argc != 1) { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: No input file specifiled\n", appname); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usage(); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regdiagfile != NULL 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (regfile == NULL || stock_include_file == NULL)) { 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s: The -p option requires the -r and -i options.\n", 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usage(); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symtable_open(); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inputfilename = *argv; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds include_file(*argv, SOURCE_FILE); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = yyparse(); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval == 0) { 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SLIST_FIRST(&scope_stack) == NULL 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) { 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Unterminated conditional expression", EX_DATAERR); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Process outmost scope */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds process_scope(SLIST_FIRST(&scope_stack)); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Decend the tree of scopes and insert/emit 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * patches as appropriate. We perform a depth first 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tranversal, recursively handling each scope. 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* start at the root scope */ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dump_scope(SLIST_FIRST(&scope_stack)); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Patch up forward jump addresses */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds back_patch(); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ofile != NULL) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds output_code(); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regfile != NULL) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symtable_dump(regfile, regdiagfile); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (listfile != NULL) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds output_listing(inputfilename); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, 0); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsusage() 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (void)fprintf(stderr, 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]\n" 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" [-r register_output_file [-p register_diag_file -i includefile]]\n" 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" [-l program_list_file]\n" 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" input_file\n", appname); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(EX_USAGE); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsback_patch() 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct instruction *cur_instr; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_instr = STAILQ_FIRST(&seq_program); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr != NULL; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr = STAILQ_NEXT(cur_instr, links)) { 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cur_instr->patch_label != NULL) { 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ins_format3 *f3_instr; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int address; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cur_instr->patch_label->type != LABEL) { 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[255]; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(buf, sizeof(buf), 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Undefined label %s", 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->patch_label->name); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(buf, EX_DATAERR); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f3_instr = &cur_instr->format.format3; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds address = f3_instr->address; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds address += cur_instr->patch_label->info.linfo->address; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f3_instr->address = address; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutput_code() 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct instruction *cur_instr; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_t *cur_patch; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds critical_section_t *cs; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symbol_node_t *cur_node; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int instrcount; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instrcount = 0; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"/*\n" 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" * DO NOT EDIT - This file is automatically generated\n" 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" * from the following source files:\n" 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" *\n" 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"%s */\n", versions); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3653dbd10f3d8b00dad35d3fac95e91c066ae71d9a8Hannes Reinecke fprintf(ofile, "static const uint8_t seqprog[] = {\n"); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_instr = STAILQ_FIRST(&seq_program); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr != NULL; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr = STAILQ_NEXT(cur_instr, links)) { 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", 372f7c80c9f77b0e8a59a19506fd3caf323408a5166Olaf Hering#ifdef __LITTLE_ENDIAN 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[0], 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[1], 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[2], 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[3]); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[3], 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[2], 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[1], 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[0]); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instrcount++; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "\n};\n\n"); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (patch_arg_list == NULL) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Patch argument list not defined", 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EX_DATAERR); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Output patch information. Patch functions first. 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_node = SLIST_FIRST(&patch_functions); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_node != NULL; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_node = SLIST_NEXT(cur_node,links)) { 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"static %spatch_func_t %spatch%d_func;\n" 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"\n" 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"static int\n" 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"%spatch%d_func(%s)\n" 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"{\n" 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" return (%s);\n" 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"}\n\n", 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prefix, 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prefix, 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_node->symbol->info.condinfo->func_num, 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prefix, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_node->symbol->info.condinfo->func_num, 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_arg_list, 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_node->symbol->name); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 4183dbd10f3d8b00dad35d3fac95e91c066ae71d9a8Hannes Reinecke"static const struct patch {\n" 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" %spatch_func_t *patch_func;\n" 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" uint32_t begin :10,\n" 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" skip_instr :10,\n" 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" skip_patch :12;\n" 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"} patches[] = {\n", prefix); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_patch = STAILQ_FIRST(&patches); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch != NULL; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch = STAILQ_NEXT(cur_patch,links)) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }", 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n", 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prefix, 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch->patch_func, cur_patch->begin, 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch->skip_instr, cur_patch->skip_patch); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "\n};\n\n"); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 4383dbd10f3d8b00dad35d3fac95e91c066ae71d9a8Hannes Reinecke"static const struct cs {\n" 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" uint16_t begin;\n" 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" uint16_t end;\n" 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"} critical_sections[] = {\n"); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cs = TAILQ_FIRST(&cs_tailq); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs != NULL; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs = TAILQ_NEXT(cs, links)) { 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "%s\t{ %d, %d }", 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n", 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->begin_addr, cs->end_addr); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, "\n};\n\n"); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(ofile, 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"static const int num_critical_sections = sizeof(critical_sections)\n" 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" / sizeof(*critical_sections);\n"); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: %d instructions used\n", appname, instrcount); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdump_scope(scope_t *scope) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scope_t *cur_scope; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Emit the first patch for this scope 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds emit_patch(scope, 0); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dump each scope within this one. 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope = TAILQ_FIRST(&scope->inner_scope); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (cur_scope != NULL) { 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dump_scope(cur_scope); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope = TAILQ_NEXT(cur_scope, scope_links); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Emit the second, closing, patch for this scope 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds emit_patch(scope, 1); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsemit_patch(scope_t *scope, int patch) 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_info_t *pinfo; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_t *new_patch; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pinfo = &scope->patches[patch]; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pinfo->skip_instr == 0) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No-Op patch */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch = (patch_t *)malloc(sizeof(*new_patch)); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_patch == NULL) 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Could not malloc patch structure", EX_OSERR); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(new_patch, 0, sizeof(*new_patch)); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (patch == 0) { 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->patch_func = scope->func_num; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->begin = scope->begin_addr; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->patch_func = 0; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->begin = scope->end_addr; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->skip_instr = pinfo->skip_instr; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_patch->skip_patch = pinfo->skip_patch; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STAILQ_INSERT_TAIL(&patches, new_patch, links); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutput_listing(char *ifilename) 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[1024]; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FILE *ifile; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct instruction *cur_instr; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_t *cur_patch; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symbol_node_t *cur_func; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int *func_values; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int instrcount; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int instrptr; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int line; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int func_count; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int skip_addr; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instrcount = 0; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instrptr = 0; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds line = 1; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_addr = 0; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ifile = fopen(ifilename, "r")) == NULL) { 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror(ifilename); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop(NULL, EX_DATAERR); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine which options to apply to this listing. 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_func != NULL; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_func = SLIST_NEXT(cur_func, links)) 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_count++; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_values = NULL; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_count != 0) { 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_values = (int *)malloc(func_count * sizeof(int)); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_values == NULL) 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Could not malloc", EX_OSERR); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_values[0] = 0; /* FALSE func */ 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_count--; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ask the user to fill in the return values for 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the rest of the functions. 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_func = SLIST_FIRST(&patch_functions); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_func = SLIST_NEXT(cur_func, links), func_count--) { 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int input; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stdout, "\n(%s)\n", cur_func->symbol->name); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stdout, 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Enter the return value for " 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "this expression[T/F]:"); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (1) { 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds input = getchar(); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds input = toupper(input); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (input == 'T') { 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_values[func_count] = 1; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (input == 'F') { 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_values[func_count] = 0; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (isatty(fileno(stdin)) == 0) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds putchar(input); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stdout, "\nThanks!\n"); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now output the listing */ 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch = STAILQ_FIRST(&patches); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cur_instr = STAILQ_FIRST(&seq_program); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr != NULL; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) { 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (check_patch(&cur_patch, instrcount, 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &skip_addr, func_values) == 0) { 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't count this instruction as it is in a patch 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that was removed. 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (line < cur_instr->srcline) { 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fgets(buf, sizeof(buf), ifile); 6122628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fprintf(listfile, " \t%s", buf); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds line++; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6152628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr, 616f7c80c9f77b0e8a59a19506fd3caf323408a5166Olaf Hering#ifdef __LITTLE_ENDIAN 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[0], 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[1], 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[2], 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[3]); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[3], 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[2], 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[1], 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_instr->format.bytes[0]); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6272628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke /* 6282628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke * Macro expansions can cause several instructions 6292628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke * to be output for a single source line. Only 6302628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke * advance the line once in these cases. 6312628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke */ 6322628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke if (line == cur_instr->srcline) { 6332628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fgets(buf, sizeof(buf), ifile); 6342628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fprintf(listfile, "\t%s", buf); 6352628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke line++; 6362628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke } else { 6372628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fprintf(listfile, "\n"); 6382628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke } 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instrptr++; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Dump the remainder of the file */ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(fgets(buf, sizeof(buf), ifile) != NULL) 6432628ed2b1aa3fd115bb8e14925e180e9ecd07055Hannes Reinecke fprintf(listfile, " %s", buf); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclose(ifile); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscheck_patch(patch_t **start_patch, int start_instr, 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int *skip_addr, int *func_vals) 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch_t *cur_patch; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch = *start_patch; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (cur_patch != NULL && start_instr == cur_patch->begin) { 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_vals[cur_patch->patch_func] == 0) { 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int skip; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start rejecting code */ 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *skip_addr = start_instr + cur_patch->skip_instr; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (skip = cur_patch->skip_patch; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip > 0 && cur_patch != NULL; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip--) 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch = STAILQ_NEXT(cur_patch, links); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accepted this patch. Advance to the next 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one and wait for our intruction pointer to 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hit this point. 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_patch = STAILQ_NEXT(cur_patch, links); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start_patch = cur_patch; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (start_instr < *skip_addr) 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Still skipping */ 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (1); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Print out error information if appropriate, and clean up before 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * terminating the program. 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstop(const char *string, int err_code) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (string != NULL) { 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: ", appname); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (yyfilename != NULL) { 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Stopped at file %s, line %d - ", 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yyfilename, yylineno); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s\n", string); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ofile != NULL) { 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclose(ofile); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_code != 0) { 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: Removing %s due to error\n", 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname, ofilename); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlink(ofilename); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regfile != NULL) { 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclose(regfile); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_code != 0) { 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: Removing %s due to error\n", 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname, regfilename); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlink(regfilename); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (listfile != NULL) { 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fclose(listfile); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_code != 0) { 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "%s: Removing %s due to error\n", 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appname, listfilename); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlink(listfilename); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symlist_free(&patch_functions); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symtable_close(); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(err_code); 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct instruction * 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsseq_alloc() 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct instruction *new_instr; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_instr = (struct instruction *)malloc(sizeof(struct instruction)); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_instr == NULL) 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Unable to malloc instruction object", EX_SOFTWARE); 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(new_instr, 0, sizeof(*new_instr)); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STAILQ_INSERT_TAIL(&seq_program, new_instr, links); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_instr->srcline = yylineno; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return new_instr; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscritical_section_t * 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscs_alloc() 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds critical_section_t *new_cs; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_cs= (critical_section_t *)malloc(sizeof(critical_section_t)); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_cs == NULL) 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Unable to malloc critical_section object", EX_SOFTWARE); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(new_cs, 0, sizeof(*new_cs)); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return new_cs; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsscope_t * 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsscope_alloc() 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scope_t *new_scope; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_scope = (scope_t *)malloc(sizeof(scope_t)); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_scope == NULL) 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Unable to malloc scope object", EX_SOFTWARE); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(new_scope, 0, sizeof(*new_scope)); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TAILQ_INIT(&new_scope->inner_scope); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SLIST_FIRST(&scope_stack) != NULL) { 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope, 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_scope, scope_links); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This patch is now the current scope */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return new_scope; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsprocess_scope(scope_t *scope) 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We are "leaving" this scope. We should now have 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enough information to process the lists of scopes 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we encapsulate. 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scope_t *cur_scope; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int skip_patch_count; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int skip_instr_count; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_patch_count = 0; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_instr_count = 0; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (cur_scope != NULL) { 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int patch0_patch_skip; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch0_patch_skip = 0; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cur_scope->type) { 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCOPE_IF: 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCOPE_ELSE_IF: 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skip_instr_count != 0) { 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create a tail patch */ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch0_patch_skip++; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope->patches[1].skip_patch = 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_patch_count + 1; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope->patches[1].skip_instr = 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_instr_count; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Count Head patch */ 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch0_patch_skip++; 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Count any patches contained in our inner scope */ 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds patch0_patch_skip += cur_scope->inner_scope_patches; 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope->patches[0].skip_patch = patch0_patch_skip; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope->patches[0].skip_instr = 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope->end_addr - cur_scope->begin_addr; 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_instr_count += cur_scope->patches[0].skip_instr; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_patch_count += patch0_patch_skip; 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cur_scope->type == SCOPE_IF) { 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scope->inner_scope_patches += skip_patch_count; 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_patch_count = 0; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_instr_count = 0; 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCOPE_ELSE: 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Count any patches contained in our innter scope */ 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_patch_count += cur_scope->inner_scope_patches; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skip_instr_count += cur_scope->end_addr 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - cur_scope->begin_addr; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCOPE_ROOT: 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop("Unexpected scope type encountered", EX_SOFTWARE); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTREACHED */ 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 845