Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Aic7xxx SCSI host adapter firmware assembler symbol table implementation
0003  *
0004  * Copyright (c) 1997 Justin T. Gibbs.
0005  * Copyright (c) 2002 Adaptec Inc.
0006  * All rights reserved.
0007  *
0008  * Redistribution and use in source and binary forms, with or without
0009  * modification, are permitted provided that the following conditions
0010  * are met:
0011  * 1. Redistributions of source code must retain the above copyright
0012  *    notice, this list of conditions, and the following disclaimer,
0013  *    without modification.
0014  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0015  *    substantially similar to the "NO WARRANTY" disclaimer below
0016  *    ("Disclaimer") and any redistribution must be conditioned upon
0017  *    including a substantially similar Disclaimer requirement for further
0018  *    binary redistribution.
0019  * 3. Neither the names of the above-listed copyright holders nor the names
0020  *    of any contributors may be used to endorse or promote products derived
0021  *    from this software without specific prior written permission.
0022  *
0023  * Alternatively, this software may be distributed under the terms of the
0024  * GNU General Public License ("GPL") version 2 as published by the Free
0025  * Software Foundation.
0026  *
0027  * NO WARRANTY
0028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
0031  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0033  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0034  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0035  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0036  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0037  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0038  * POSSIBILITY OF SUCH DAMAGES.
0039  *
0040  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#24 $
0041  *
0042  * $FreeBSD$
0043  */
0044 
0045 #include <sys/types.h>
0046 
0047 #include "aicdb.h"
0048 #include <fcntl.h>
0049 #include <inttypes.h>
0050 #include <regex.h>
0051 #include <stdio.h>
0052 #include <stdlib.h>
0053 #include <string.h>
0054 #include <sysexits.h>
0055 
0056 #include "aicasm_symbol.h"
0057 #include "aicasm.h"
0058 
0059 static DB *symtable;
0060 
0061 symbol_t *
0062 symbol_create(char *name)
0063 {
0064     symbol_t *new_symbol;
0065 
0066     new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
0067     if (new_symbol == NULL) {
0068         perror("Unable to create new symbol");
0069         exit(EX_SOFTWARE);
0070     }
0071     memset(new_symbol, 0, sizeof(*new_symbol));
0072     new_symbol->name = strdup(name);
0073     if (new_symbol->name == NULL)
0074          stop("Unable to strdup symbol name", EX_SOFTWARE);
0075     new_symbol->type = UNINITIALIZED;
0076     new_symbol->count = 1;
0077     return (new_symbol);
0078 }
0079 
0080 void
0081 symbol_delete(symbol_t *symbol)
0082 {
0083     if (symtable != NULL) {
0084         DBT  key;
0085 
0086         key.data = symbol->name;
0087         key.size = strlen(symbol->name);
0088         symtable->del(symtable, &key, /*flags*/0);
0089     }
0090     switch(symbol->type) {
0091     case SCBLOC:
0092     case SRAMLOC:
0093     case REGISTER:
0094         if (symbol->info.rinfo != NULL)
0095             free(symbol->info.rinfo);
0096         break;
0097     case ALIAS:
0098         if (symbol->info.ainfo != NULL)
0099             free(symbol->info.ainfo);
0100         break;
0101     case MASK:
0102     case FIELD:
0103     case ENUM:
0104     case ENUM_ENTRY:
0105         if (symbol->info.finfo != NULL) {
0106             symlist_free(&symbol->info.finfo->symrefs);
0107             free(symbol->info.finfo);
0108         }
0109         break;
0110     case DOWNLOAD_CONST:
0111     case CONST:
0112         if (symbol->info.cinfo != NULL)
0113             free(symbol->info.cinfo);
0114         break;
0115     case LABEL:
0116         if (symbol->info.linfo != NULL)
0117             free(symbol->info.linfo);
0118         break;
0119     case UNINITIALIZED:
0120     default:
0121         break;
0122     }
0123     free(symbol->name);
0124     free(symbol);
0125 }
0126 
0127 void
0128 symtable_open()
0129 {
0130     symtable = dbopen(/*filename*/NULL,
0131               O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
0132               /*openinfo*/NULL);
0133 
0134     if (symtable == NULL) {
0135         perror("Symbol table creation failed");
0136         exit(EX_SOFTWARE);
0137         /* NOTREACHED */
0138     }
0139 }
0140 
0141 void
0142 symtable_close()
0143 {
0144     if (symtable != NULL) {
0145         DBT  key;
0146         DBT  data;
0147 
0148         while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
0149             symbol_t *stored_ptr;
0150 
0151             memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
0152             symbol_delete(stored_ptr);
0153         }
0154         symtable->close(symtable);
0155     }
0156 }
0157 
0158 /*
0159  * The semantics of get is to return an uninitialized symbol entry
0160  * if a lookup fails.
0161  */
0162 symbol_t *
0163 symtable_get(char *name)
0164 {
0165     symbol_t *stored_ptr;
0166     DBT   key;
0167     DBT   data;
0168     int   retval;
0169 
0170     key.data = (void *)name;
0171     key.size = strlen(name);
0172 
0173     if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
0174         if (retval == -1) {
0175             perror("Symbol table get operation failed");
0176             exit(EX_SOFTWARE);
0177             /* NOTREACHED */
0178         } else if (retval == 1) {
0179             /* Symbol wasn't found, so create a new one */
0180             symbol_t *new_symbol;
0181 
0182             new_symbol = symbol_create(name);
0183             data.data = &new_symbol;
0184             data.size = sizeof(new_symbol);
0185             if (symtable->put(symtable, &key, &data,
0186                       /*flags*/0) !=0) {
0187                 perror("Symtable put failed");
0188                 exit(EX_SOFTWARE);
0189             }
0190             return (new_symbol);
0191         } else {
0192             perror("Unexpected return value from db get routine");
0193             exit(EX_SOFTWARE);
0194             /* NOTREACHED */
0195         }
0196     }
0197     memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
0198     stored_ptr->count++;
0199     data.data = &stored_ptr;
0200     if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
0201         perror("Symtable put failed");
0202         exit(EX_SOFTWARE);
0203     }
0204     return (stored_ptr);
0205 }
0206 
0207 symbol_node_t *
0208 symlist_search(symlist_t *symlist, char *symname)
0209 {
0210     symbol_node_t *curnode;
0211 
0212     curnode = SLIST_FIRST(symlist);
0213     while(curnode != NULL) {
0214         if (strcmp(symname, curnode->symbol->name) == 0)
0215             break;
0216         curnode = SLIST_NEXT(curnode, links);
0217     }
0218     return (curnode);
0219 }
0220 
0221 void
0222 symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
0223 {
0224     symbol_node_t *newnode;
0225 
0226     newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
0227     if (newnode == NULL) {
0228         stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
0229         /* NOTREACHED */
0230     }
0231     newnode->symbol = symbol;
0232     if (how == SYMLIST_SORT) {
0233         symbol_node_t *curnode;
0234         int field;
0235 
0236         field = FALSE;
0237         switch(symbol->type) {
0238         case REGISTER:
0239         case SCBLOC:
0240         case SRAMLOC:
0241             break;
0242         case FIELD:
0243         case MASK:
0244         case ENUM:
0245         case ENUM_ENTRY:
0246             field = TRUE;
0247             break;
0248         default:
0249             stop("symlist_add: Invalid symbol type for sorting",
0250                  EX_SOFTWARE);
0251             /* NOTREACHED */
0252         }
0253 
0254         curnode = SLIST_FIRST(symlist);
0255         if (curnode == NULL
0256          || (field
0257           && (curnode->symbol->type > newnode->symbol->type
0258            || (curnode->symbol->type == newnode->symbol->type
0259             && (curnode->symbol->info.finfo->value >
0260             newnode->symbol->info.finfo->value))))
0261          || (!field && (curnode->symbol->info.rinfo->address >
0262                 newnode->symbol->info.rinfo->address))) {
0263             SLIST_INSERT_HEAD(symlist, newnode, links);
0264             return;
0265         }
0266 
0267         while (1) {
0268             if (SLIST_NEXT(curnode, links) == NULL) {
0269                 SLIST_INSERT_AFTER(curnode, newnode,
0270                            links);
0271                 break;
0272             } else {
0273                 symbol_t *cursymbol;
0274 
0275                 cursymbol = SLIST_NEXT(curnode, links)->symbol;
0276                 if ((field
0277                   && (cursymbol->type > symbol->type
0278                    || (cursymbol->type == symbol->type
0279                     && (cursymbol->info.finfo->value >
0280                     symbol->info.finfo->value))))
0281                  || (!field
0282                    && (cursymbol->info.rinfo->address >
0283                        symbol->info.rinfo->address))) {
0284                     SLIST_INSERT_AFTER(curnode, newnode,
0285                                links);
0286                     break;
0287                 }
0288             }
0289             curnode = SLIST_NEXT(curnode, links);
0290         }
0291     } else {
0292         SLIST_INSERT_HEAD(symlist, newnode, links);
0293     }
0294 }
0295 
0296 void
0297 symlist_free(symlist_t *symlist)
0298 {
0299     symbol_node_t *node1, *node2;
0300 
0301     node1 = SLIST_FIRST(symlist);
0302     while (node1 != NULL) {
0303         node2 = SLIST_NEXT(node1, links);
0304         free(node1);
0305         node1 = node2;
0306     }
0307     SLIST_INIT(symlist);
0308 }
0309 
0310 void
0311 symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
0312           symlist_t *symlist_src2)
0313 {
0314     symbol_node_t *node;
0315 
0316     *symlist_dest = *symlist_src1;
0317     while((node = SLIST_FIRST(symlist_src2)) != NULL) {
0318         SLIST_REMOVE_HEAD(symlist_src2, links);
0319         SLIST_INSERT_HEAD(symlist_dest, node, links);
0320     }
0321 
0322     /* These are now empty */
0323     SLIST_INIT(symlist_src1);
0324     SLIST_INIT(symlist_src2);
0325 }
0326 
0327 void
0328 aic_print_file_prologue(FILE *ofile)
0329 {
0330 
0331     if (ofile == NULL)
0332         return;
0333 
0334     fprintf(ofile,
0335 "/*\n"
0336 " * DO NOT EDIT - This file is automatically generated\n"
0337 " *      from the following source files:\n"
0338 " *\n"
0339 "%s */\n",
0340         versions);
0341 }
0342 
0343 void
0344 aic_print_include(FILE *dfile, char *include_file)
0345 {
0346 
0347     if (dfile == NULL)
0348         return;
0349     fprintf(dfile, "\n#include \"%s\"\n\n", include_file);
0350 }
0351 
0352 void
0353 aic_print_reg_dump_types(FILE *ofile)
0354 {
0355     if (ofile == NULL)
0356         return;
0357 
0358     fprintf(ofile,
0359 "typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
0360 "typedef struct %sreg_parse_entry {\n"
0361 "   char    *name;\n"
0362 "   uint8_t  value;\n"
0363 "   uint8_t  mask;\n"
0364 "} %sreg_parse_entry_t;\n"
0365 "\n",
0366         prefix, prefix, prefix);
0367 }
0368 
0369 static void
0370 aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
0371 {
0372     if (dfile == NULL)
0373         return;
0374 
0375     fprintf(dfile,
0376 "static const %sreg_parse_entry_t %s_parse_table[] = {\n",
0377         prefix,
0378         regnode->symbol->name);
0379 }
0380 
0381 static void
0382 aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
0383                symbol_node_t *regnode, u_int num_entries)
0384 {
0385     char *lower_name;
0386     char *letter;
0387 
0388     lower_name = strdup(regnode->symbol->name);
0389     if (lower_name == NULL)
0390          stop("Unable to strdup symbol name", EX_SOFTWARE);
0391 
0392     for (letter = lower_name; *letter != '\0'; letter++)
0393         *letter = tolower(*letter);
0394 
0395     if (dfile != NULL) {
0396         if (num_entries != 0)
0397             fprintf(dfile,
0398 "\n"
0399 "};\n"
0400 "\n");
0401 
0402         fprintf(dfile,
0403 "int\n"
0404 "%s%s_print(u_int regvalue, u_int *cur_col, u_int wrap)\n"
0405 "{\n"
0406 "   return (%sprint_register(%s%s, %d, \"%s\",\n"
0407 "       0x%02x, regvalue, cur_col, wrap));\n"
0408 "}\n"
0409 "\n",
0410             prefix,
0411             lower_name,
0412             prefix,
0413             num_entries != 0 ? regnode->symbol->name : "NULL",
0414             num_entries != 0 ? "_parse_table" : "",
0415             num_entries,
0416             regnode->symbol->name,
0417             regnode->symbol->info.rinfo->address);
0418     }
0419 
0420     fprintf(ofile,
0421 "#if AIC_DEBUG_REGISTERS\n"
0422 "%sreg_print_t %s%s_print;\n"
0423 "#else\n"
0424 "#define %s%s_print(regvalue, cur_col, wrap) \\\n"
0425 "    %sprint_register(NULL, 0, \"%s\", 0x%02x, regvalue, cur_col, wrap)\n"
0426 "#endif\n"
0427 "\n",
0428         prefix,
0429         prefix,
0430         lower_name,
0431         prefix,
0432         lower_name,
0433         prefix,
0434         regnode->symbol->name,
0435         regnode->symbol->info.rinfo->address);
0436 }
0437 
0438 static void
0439 aic_print_reg_dump_entry(FILE *dfile, symbol_node_t *curnode)
0440 {
0441     int num_tabs;
0442 
0443     if (dfile == NULL)
0444         return;
0445 
0446     fprintf(dfile,
0447 "   { \"%s\",",
0448         curnode->symbol->name);
0449 
0450     num_tabs = 3 - (strlen(curnode->symbol->name) + 5) / 8;
0451 
0452     while (num_tabs-- > 0)
0453         fputc('\t', dfile);
0454     fprintf(dfile, "0x%02x, 0x%02x }",
0455         curnode->symbol->info.finfo->value,
0456         curnode->symbol->info.finfo->mask);
0457 }
0458 
0459 void
0460 symtable_dump(FILE *ofile, FILE *dfile)
0461 {
0462     /*
0463      * Sort the registers by address with a simple insertion sort.
0464      * Put bitmasks next to the first register that defines them.
0465      * Put constants at the end.
0466      */
0467     symlist_t    registers;
0468     symlist_t    masks;
0469     symlist_t    constants;
0470     symlist_t    download_constants;
0471     symlist_t    aliases;
0472     symlist_t    exported_labels;
0473     symbol_node_t   *curnode;
0474     symbol_node_t   *regnode;
0475     DBT      key;
0476     DBT      data;
0477     int      flag;
0478     int      reg_count = 0, reg_used = 0;
0479     u_int        i;
0480 
0481     if (symtable == NULL)
0482         return;
0483 
0484     SLIST_INIT(&registers);
0485     SLIST_INIT(&masks);
0486     SLIST_INIT(&constants);
0487     SLIST_INIT(&download_constants);
0488     SLIST_INIT(&aliases);
0489     SLIST_INIT(&exported_labels);
0490     flag = R_FIRST;
0491     while (symtable->seq(symtable, &key, &data, flag) == 0) {
0492         symbol_t *cursym;
0493 
0494         memcpy(&cursym, data.data, sizeof(cursym));
0495         switch(cursym->type) {
0496         case REGISTER:
0497         case SCBLOC:
0498         case SRAMLOC:
0499             symlist_add(&registers, cursym, SYMLIST_SORT);
0500             break;
0501         case MASK:
0502         case FIELD:
0503         case ENUM:
0504         case ENUM_ENTRY:
0505             symlist_add(&masks, cursym, SYMLIST_SORT);
0506             break;
0507         case CONST:
0508             symlist_add(&constants, cursym,
0509                     SYMLIST_INSERT_HEAD);
0510             break;
0511         case DOWNLOAD_CONST:
0512             symlist_add(&download_constants, cursym,
0513                     SYMLIST_INSERT_HEAD);
0514             break;
0515         case ALIAS:
0516             symlist_add(&aliases, cursym,
0517                     SYMLIST_INSERT_HEAD);
0518             break;
0519         case LABEL:
0520             if (cursym->info.linfo->exported == 0)
0521                 break;
0522             symlist_add(&exported_labels, cursym,
0523                     SYMLIST_INSERT_HEAD);
0524             break;
0525         default:
0526             break;
0527         }
0528         flag = R_NEXT;
0529     }
0530 
0531     /* Register dianostic functions/declarations first. */
0532     aic_print_file_prologue(ofile);
0533     aic_print_reg_dump_types(ofile);
0534     aic_print_file_prologue(dfile);
0535     aic_print_include(dfile, stock_include_file);
0536     SLIST_FOREACH(curnode, &registers, links) {
0537 
0538         if (curnode->symbol->dont_generate_debug_code)
0539             continue;
0540 
0541         switch(curnode->symbol->type) {
0542         case REGISTER:
0543         case SCBLOC:
0544         case SRAMLOC:
0545         {
0546             symlist_t   *fields;
0547             symbol_node_t   *fieldnode;
0548             int      num_entries;
0549 
0550             num_entries = 0;
0551             reg_count++;
0552             if (curnode->symbol->count == 1)
0553                 break;
0554             fields = &curnode->symbol->info.rinfo->fields;
0555             SLIST_FOREACH(fieldnode, fields, links) {
0556                 if (num_entries == 0)
0557                     aic_print_reg_dump_start(dfile,
0558                                  curnode);
0559                 else if (dfile != NULL)
0560                     fputs(",\n", dfile);
0561                 num_entries++;
0562                 aic_print_reg_dump_entry(dfile, fieldnode);
0563             }
0564             aic_print_reg_dump_end(ofile, dfile,
0565                            curnode, num_entries);
0566             reg_used++;
0567         }
0568         default:
0569             break;
0570         }
0571     }
0572     fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
0573         reg_used, reg_count);
0574 
0575     /* Fold in the masks and bits */
0576     while (SLIST_FIRST(&masks) != NULL) {
0577         char *regname;
0578 
0579         curnode = SLIST_FIRST(&masks);
0580         SLIST_REMOVE_HEAD(&masks, links);
0581 
0582         regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);
0583         regname = regnode->symbol->name;
0584         regnode = symlist_search(&registers, regname);
0585         SLIST_INSERT_AFTER(regnode, curnode, links);
0586     }
0587 
0588     /* Add the aliases */
0589     while (SLIST_FIRST(&aliases) != NULL) {
0590         char *regname;
0591 
0592         curnode = SLIST_FIRST(&aliases);
0593         SLIST_REMOVE_HEAD(&aliases, links);
0594 
0595         regname = curnode->symbol->info.ainfo->parent->name;
0596         regnode = symlist_search(&registers, regname);
0597         SLIST_INSERT_AFTER(regnode, curnode, links);
0598     }
0599 
0600     /* Output generated #defines. */
0601     while (SLIST_FIRST(&registers) != NULL) {
0602         symbol_node_t *curnode;
0603         u_int value;
0604         char *tab_str;
0605         char *tab_str2;
0606 
0607         curnode = SLIST_FIRST(&registers);
0608         SLIST_REMOVE_HEAD(&registers, links);
0609         switch(curnode->symbol->type) {
0610         case REGISTER:
0611         case SCBLOC:
0612         case SRAMLOC:
0613             fprintf(ofile, "\n");
0614             value = curnode->symbol->info.rinfo->address;
0615             tab_str = "\t";
0616             tab_str2 = "\t\t";
0617             break;
0618         case ALIAS:
0619         {
0620             symbol_t *parent;
0621 
0622             parent = curnode->symbol->info.ainfo->parent;
0623             value = parent->info.rinfo->address;
0624             tab_str = "\t";
0625             tab_str2 = "\t\t";
0626             break;
0627         }
0628         case MASK:
0629         case FIELD:
0630         case ENUM:
0631         case ENUM_ENTRY:
0632             value = curnode->symbol->info.finfo->value;
0633             tab_str = "\t\t";
0634             tab_str2 = "\t";
0635             break;
0636         default:
0637             value = 0; /* Quiet compiler */
0638             tab_str = NULL;
0639             tab_str2 = NULL;
0640             stop("symtable_dump: Invalid symbol type "
0641                  "encountered", EX_SOFTWARE);
0642             break;
0643         }
0644         fprintf(ofile, "#define%s%-16s%s0x%02x\n",
0645             tab_str, curnode->symbol->name, tab_str2,
0646             value);
0647         free(curnode);
0648     }
0649     fprintf(ofile, "\n\n");
0650 
0651     while (SLIST_FIRST(&constants) != NULL) {
0652         symbol_node_t *curnode;
0653 
0654         curnode = SLIST_FIRST(&constants);
0655         SLIST_REMOVE_HEAD(&constants, links);
0656         fprintf(ofile, "#define\t%-8s\t0x%02x\n",
0657             curnode->symbol->name,
0658             curnode->symbol->info.cinfo->value);
0659         free(curnode);
0660     }
0661 
0662     fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
0663 
0664     for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
0665         symbol_node_t *curnode;
0666 
0667         curnode = SLIST_FIRST(&download_constants);
0668         SLIST_REMOVE_HEAD(&download_constants, links);
0669         fprintf(ofile, "#define\t%-8s\t0x%02x\n",
0670             curnode->symbol->name,
0671             curnode->symbol->info.cinfo->value);
0672         free(curnode);
0673     }
0674     fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);
0675 
0676     fprintf(ofile, "\n\n/* Exported Labels */\n");
0677 
0678     while (SLIST_FIRST(&exported_labels) != NULL) {
0679         symbol_node_t *curnode;
0680 
0681         curnode = SLIST_FIRST(&exported_labels);
0682         SLIST_REMOVE_HEAD(&exported_labels, links);
0683         fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",
0684             curnode->symbol->name,
0685             curnode->symbol->info.linfo->address);
0686         free(curnode);
0687     }
0688 }
0689