aicasm_symbol.c revision 23925
1/* 2 * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation 3 * 4 * Copyright (c) 1997 Justin T. Gibbs. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice immediately at the beginning of the file, without modification, 12 * this list of conditions, and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Id$ 32 */ 33 34 35#include <sys/types.h> 36 37#include <db.h> 38#include <fcntl.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <sysexits.h> 43 44#include "symbol.h" 45#include "aic7xxx_asm.h" 46 47static DB *symtable; 48 49symbol_t * 50symbol_create(name) 51 char *name; 52{ 53 symbol_t *new_symbol; 54 55 new_symbol = (symbol_t *)malloc(sizeof(symbol_t)); 56 if (new_symbol == NULL) { 57 perror("Unable to create new symbol"); 58 exit(EX_SOFTWARE); 59 } 60 memset(new_symbol, 0, sizeof(*new_symbol)); 61 new_symbol->name = strdup(name); 62 new_symbol->type = UNINITIALIZED; 63 return (new_symbol); 64} 65 66void 67symbol_delete(symbol) 68 symbol_t *symbol; 69{ 70 if (symtable != NULL) { 71 DBT key; 72 73 key.data = symbol->name; 74 key.size = strlen(symbol->name); 75 symtable->del(symtable, &key, /*flags*/0); 76 } 77 switch(symbol->type) { 78 case SCBLOC: 79 case SRAMLOC: 80 case REGISTER: 81 if (symbol->info.rinfo != NULL) 82 free(symbol->info.rinfo); 83 break; 84 case ALIAS: 85 if (symbol->info.ainfo != NULL) 86 free(symbol->info.ainfo); 87 break; 88 case MASK: 89 case BIT: 90 if (symbol->info.minfo != NULL) { 91 symlist_free(&symbol->info.minfo->symrefs); 92 free(symbol->info.minfo); 93 } 94 break; 95 case CONST: 96 if (symbol->info.cinfo != NULL) 97 free(symbol->info.cinfo); 98 break; 99 case LABEL: 100 if (symbol->info.linfo != NULL) 101 free(symbol->info.linfo); 102 break; 103 case UNINITIALIZED: 104 default: 105 break; 106 } 107 free(symbol->name); 108 free(symbol); 109} 110 111void 112symtable_open() 113{ 114 symtable = dbopen(/*filename*/NULL, 115 O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH, 116 /*openinfo*/NULL); 117 118 if (symtable == NULL) { 119 perror("Symbol table creation failed"); 120 exit(EX_SOFTWARE); 121 /* NOTREACHED */ 122 } 123} 124 125void 126symtable_close() 127{ 128 if (symtable != NULL) { 129 DBT key; 130 DBT data; 131 132 while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) { 133 symbol_t *cursym; 134 135 cursym = *(symbol_t **)data.data; 136 symbol_delete(cursym); 137 } 138 symtable->close(symtable); 139 } 140} 141 142/* 143 * The semantics of get is to return an uninitialized symbol entry 144 * if a lookup fails. 145 */ 146symbol_t * 147symtable_get(name) 148 char *name; 149{ 150 DBT key; 151 DBT data; 152 int retval; 153 154 key.data = (void *)name; 155 key.size = strlen(name); 156 157 if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) { 158 if (retval == -1) { 159 perror("Symbol table get operation failed"); 160 exit(EX_SOFTWARE); 161 /* NOTREACHED */ 162 } else if (retval == 1) { 163 /* Symbol wasn't found, so create a new one */ 164 symbol_t *new_symbol; 165 166 new_symbol = symbol_create(name); 167 data.data = &new_symbol; 168 data.size = sizeof(new_symbol); 169 if (symtable->put(symtable, &key, &data, 170 /*flags*/0) !=0) { 171 perror("Symtable put failed"); 172 exit(EX_SOFTWARE); 173 } 174 return (new_symbol); 175 } else { 176 perror("Unexpected return value from db get routine"); 177 exit(EX_SOFTWARE); 178 /* NOTREACHED */ 179 } 180 } 181 return (*(symbol_t **)data.data); 182} 183 184symbol_node_t * 185symlist_search(symlist, symname) 186 symlist_t *symlist; 187 char *symname; 188{ 189 symbol_node_t *curnode; 190 191 curnode = symlist->slh_first; 192 while(curnode != NULL) { 193 if (strcmp(symname, curnode->symbol->name) == 0) 194 break; 195 curnode = curnode->links.sle_next; 196 } 197 return (curnode); 198} 199 200void 201symlist_add(symlist, symbol, how) 202 symlist_t *symlist; 203 symbol_t *symbol; 204 int how; 205{ 206 symbol_node_t *newnode; 207 208 newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t)); 209 if (newnode == NULL) { 210 stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE); 211 /* NOTREACHED */ 212 } 213 newnode->symbol = symbol; 214 if (how == SYMLIST_SORT) { 215 symbol_node_t *curnode; 216 int mask; 217 218 mask = FALSE; 219 switch(symbol->type) { 220 case REGISTER: 221 case SCBLOC: 222 case SRAMLOC: 223 break; 224 case BIT: 225 case MASK: 226 mask = TRUE; 227 break; 228 default: 229 stop("symlist_add: Invalid symbol type for sorting", 230 EX_SOFTWARE); 231 /* NOTREACHED */ 232 } 233 234 curnode = symlist->slh_first; 235 if (curnode == NULL 236 || (mask && (curnode->symbol->info.minfo->mask > 237 newnode->symbol->info.minfo->mask)) 238 || (!mask && (curnode->symbol->info.rinfo->address > 239 newnode->symbol->info.rinfo->address))) { 240 SLIST_INSERT_HEAD(symlist, newnode, links); 241 return; 242 } 243 244 while (1) { 245 if (curnode->links.sle_next == NULL) { 246 SLIST_INSERT_AFTER(curnode, newnode, 247 links); 248 break; 249 } else { 250 symbol_t *cursymbol; 251 252 cursymbol = curnode->links.sle_next->symbol; 253 if ((mask && (cursymbol->info.minfo->mask > 254 symbol->info.minfo->mask)) 255 || (!mask &&(cursymbol->info.rinfo->address > 256 symbol->info.rinfo->address))){ 257 SLIST_INSERT_AFTER(curnode, newnode, 258 links); 259 break; 260 } 261 } 262 curnode = curnode->links.sle_next; 263 } 264 } else { 265 SLIST_INSERT_HEAD(symlist, newnode, links); 266 } 267} 268 269void 270symlist_free(symlist) 271 symlist_t *symlist; 272{ 273 symbol_node_t *node1, *node2; 274 275 node1 = symlist->slh_first; 276 while (node1 != NULL) { 277 node2 = node1->links.sle_next; 278 free(node1); 279 node1 = node2; 280 } 281 SLIST_INIT(symlist); 282} 283 284void 285symlist_merge(symlist_dest, symlist_src1, symlist_src2) 286 symlist_t *symlist_dest; 287 symlist_t *symlist_src1; 288 symlist_t *symlist_src2; 289{ 290 symbol_node_t *node; 291 292 *symlist_dest = *symlist_src1; 293 while((node = symlist_src2->slh_first) != NULL) { 294 SLIST_REMOVE_HEAD(symlist_src2, links); 295 SLIST_INSERT_HEAD(symlist_dest, node, links); 296 } 297 298 /* These are now empty */ 299 SLIST_INIT(symlist_src1); 300 SLIST_INIT(symlist_src2); 301} 302 303void 304symtable_dump(ofile) 305 FILE *ofile; 306{ 307 /* 308 * Sort the registers by address with a simple insertion sort. 309 * Put bitmasks next to the first register that defines them. 310 * Put constants at the end. 311 */ 312 symlist_t registers; 313 symlist_t masks; 314 symlist_t constants; 315 symlist_t aliases; 316 317 SLIST_INIT(®isters); 318 SLIST_INIT(&masks); 319 SLIST_INIT(&constants); 320 SLIST_INIT(&aliases); 321 322 if (symtable != NULL) { 323 DBT key; 324 DBT data; 325 int flag = R_FIRST; 326 327 while (symtable->seq(symtable, &key, &data, flag) == 0) { 328 symbol_t *cursym; 329 330 cursym = *(symbol_t **)data.data; 331 switch(cursym->type) { 332 case REGISTER: 333 case SCBLOC: 334 case SRAMLOC: 335 symlist_add(®isters, cursym, SYMLIST_SORT); 336 break; 337 case MASK: 338 case BIT: 339 symlist_add(&masks, cursym, SYMLIST_SORT); 340 break; 341 case CONST: 342 if (cursym->info.cinfo->define == FALSE) { 343 symlist_add(&constants, cursym, 344 SYMLIST_INSERT_HEAD); 345 } 346 break; 347 case ALIAS: 348 symlist_add(&aliases, cursym, 349 SYMLIST_INSERT_HEAD); 350 default: 351 break; 352 } 353 flag = R_NEXT; 354 } 355 356 /* Put in the masks and bits */ 357 while (masks.slh_first != NULL) { 358 symbol_node_t *curnode; 359 symbol_node_t *regnode; 360 char *regname; 361 362 curnode = masks.slh_first; 363 SLIST_REMOVE_HEAD(&masks, links); 364 365 regnode = 366 curnode->symbol->info.minfo->symrefs.slh_first; 367 regname = regnode->symbol->name; 368 regnode = symlist_search(®isters, regname); 369 SLIST_INSERT_AFTER(regnode, curnode, links); 370 } 371 372 /* Add the aliases */ 373 while (aliases.slh_first != NULL) { 374 symbol_node_t *curnode; 375 symbol_node_t *regnode; 376 char *regname; 377 378 curnode = aliases.slh_first; 379 SLIST_REMOVE_HEAD(&aliases, links); 380 381 regname = curnode->symbol->info.ainfo->parent->name; 382 regnode = symlist_search(®isters, regname); 383 SLIST_INSERT_AFTER(regnode, curnode, links); 384 } 385 386 /* Output what we have */ 387 fprintf(ofile, 388"/* 389 * DO NOT EDIT - This file is automatically generated. 390 */\n"); 391 while (registers.slh_first != NULL) { 392 symbol_node_t *curnode; 393 u_int8_t value; 394 char *tab_str; 395 char *tab_str2; 396 397 curnode = registers.slh_first; 398 SLIST_REMOVE_HEAD(®isters, links); 399 switch(curnode->symbol->type) { 400 case REGISTER: 401 case SCBLOC: 402 case SRAMLOC: 403 fprintf(ofile, "\n"); 404 value = curnode->symbol->info.rinfo->address; 405 tab_str = "\t"; 406 tab_str2 = "\t\t"; 407 break; 408 case ALIAS: 409 { 410 symbol_t *parent; 411 412 parent = curnode->symbol->info.ainfo->parent; 413 value = parent->info.rinfo->address; 414 tab_str = "\t"; 415 tab_str2 = "\t\t"; 416 break; 417 } 418 case MASK: 419 case BIT: 420 value = curnode->symbol->info.minfo->mask; 421 tab_str = "\t\t"; 422 tab_str2 = "\t"; 423 break; 424 default: 425 value = 0; /* Quiet compiler */ 426 tab_str = NULL; 427 tab_str2 = NULL; 428 stop("symtable_dump: Invalid symbol type " 429 "encountered", EX_SOFTWARE); 430 break; 431 } 432 fprintf(ofile, "#define%s%-16s%s0x%02x\n", 433 tab_str, curnode->symbol->name, tab_str2, 434 value); 435 free(curnode); 436 } 437 fprintf(ofile, "\n\n"); 438 439 while (constants.slh_first != NULL) { 440 symbol_node_t *curnode; 441 442 curnode = constants.slh_first; 443 SLIST_REMOVE_HEAD(&constants, links); 444 fprintf(ofile, "#define\t%-8s\t0x%02x\n", 445 curnode->symbol->name, 446 curnode->symbol->info.cinfo->value); 447 free(curnode); 448 } 449 } 450} 451 452