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, this list of conditions, and the following disclaimer, 12 * without modification. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * Alternatively, this software may be distributed under the terms of the 17 * GNU Public License ("GPL"). 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: //depot/src/aic7xxx/aicasm/aicasm_symbol.c#4 $ 32 * 33 * $FreeBSD$ 34 */ 35 36 #include <sys/types.h> 37 38 #ifdef __linux__ 39 #include <db1/db.h> 40 #else 41 #include <db.h> 42 #endif 43 #include <fcntl.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <sysexits.h> 48 49 #include "aicasm_symbol.h" 50 #include "aicasm.h" 51 52 static DB *symtable; 53 54 symbol_t * 55 symbol_create(char *name) 56 { 57 symbol_t *new_symbol; 58 59 new_symbol = (symbol_t *)malloc(sizeof(symbol_t)); 60 if (new_symbol == NULL) { 61 perror("Unable to create new symbol"); 62 exit(EX_SOFTWARE); 63 } 64 memset(new_symbol, 0, sizeof(*new_symbol)); 65 new_symbol->name = strdup(name); 66 new_symbol->type = UNINITIALIZED; 67 return (new_symbol); 68 } 69 70 void 71 symbol_delete(symbol_t *symbol) 72 { 73 if (symtable != NULL) { 74 DBT key; 75 76 key.data = symbol->name; 77 key.size = strlen(symbol->name); 78 symtable->del(symtable, &key, /*flags*/0); 79 } 80 switch(symbol->type) { 81 case SCBLOC: 82 case SRAMLOC: 83 case REGISTER: 84 if (symbol->info.rinfo != NULL) 85 free(symbol->info.rinfo); 86 break; 87 case ALIAS: 88 if (symbol->info.ainfo != NULL) 89 free(symbol->info.ainfo); 90 break; 91 case MASK: 92 case BIT: 93 if (symbol->info.minfo != NULL) { 94 symlist_free(&symbol->info.minfo->symrefs); 95 free(symbol->info.minfo); 96 } 97 break; 98 case DOWNLOAD_CONST: 99 case CONST: 100 if (symbol->info.cinfo != NULL) 101 free(symbol->info.cinfo); 102 break; 103 case LABEL: 104 if (symbol->info.linfo != NULL) 105 free(symbol->info.linfo); 106 break; 107 case UNINITIALIZED: 108 default: 109 break; 110 } 111 free(symbol->name); 112 free(symbol); 113 } 114 115 void 116 symtable_open() 117 { 118 symtable = dbopen(/*filename*/NULL, 119 O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH, 120 /*openinfo*/NULL); 121 122 if (symtable == NULL) { 123 perror("Symbol table creation failed"); 124 exit(EX_SOFTWARE); 125 /* NOTREACHED */ 126 } 127 } 128 129 void 130 symtable_close() 131 { 132 if (symtable != NULL) { 133 DBT key; 134 DBT data; 135 136 while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) { 137 symbol_t *stored_ptr; 138 139 memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); 140 symbol_delete(stored_ptr); 141 } 142 symtable->close(symtable); 143 } 144 } 145 146 /* 147 * The semantics of get is to return an uninitialized symbol entry 148 * if a lookup fails. 149 */ 150 symbol_t * 151 symtable_get(char *name) 152 { 153 symbol_t *stored_ptr; 154 DBT key; 155 DBT data; 156 int retval; 157 158 key.data = (void *)name; 159 key.size = strlen(name); 160 161 if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) { 162 if (retval == -1) { 163 perror("Symbol table get operation failed"); 164 exit(EX_SOFTWARE); 165 /* NOTREACHED */ 166 } else if (retval == 1) { 167 /* Symbol wasn't found, so create a new one */ 168 symbol_t *new_symbol; 169 170 new_symbol = symbol_create(name); 171 data.data = &new_symbol; 172 data.size = sizeof(new_symbol); 173 if (symtable->put(symtable, &key, &data, 174 /*flags*/0) !=0) { 175 perror("Symtable put failed"); 176 exit(EX_SOFTWARE); 177 } 178 return (new_symbol); 179 } else { 180 perror("Unexpected return value from db get routine"); 181 exit(EX_SOFTWARE); 182 /* NOTREACHED */ 183 } 184 } 185 memcpy(&stored_ptr, data.data, sizeof(stored_ptr)); 186 return (stored_ptr); 187 } 188 189 symbol_node_t * 190 symlist_search(symlist_t *symlist, char *symname) 191 { 192 symbol_node_t *curnode; 193 194 curnode = SLIST_FIRST(symlist); 195 while(curnode != NULL) { 196 if (strcmp(symname, curnode->symbol->name) == 0) 197 break; 198 curnode = SLIST_NEXT(curnode, links); 199 } 200 return (curnode); 201 } 202 203 void 204 symlist_add(symlist_t *symlist, symbol_t *symbol, 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 = SLIST_FIRST(symlist); 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 (SLIST_NEXT(curnode, links) == NULL) { 246 SLIST_INSERT_AFTER(curnode, newnode, 247 links); 248 break; 249 } else { 250 symbol_t *cursymbol; 251 252 cursymbol = SLIST_NEXT(curnode, links)->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 = SLIST_NEXT(curnode, links); 263 } 264 } else { 265 SLIST_INSERT_HEAD(symlist, newnode, links); 266 } 267 } 268 269 void 270 symlist_free(symlist_t *symlist) 271 { 272 symbol_node_t *node1, *node2; 273 274 node1 = SLIST_FIRST(symlist); 275 while (node1 != NULL) { 276 node2 = SLIST_NEXT(node1, links); 277 free(node1); 278 node1 = node2; 279 } 280 SLIST_INIT(symlist); 281 } 282 283 void 284 symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1, 285 symlist_t *symlist_src2) 286 { 287 symbol_node_t *node; 288 289 *symlist_dest = *symlist_src1; 290 while((node = SLIST_FIRST(symlist_src2)) != NULL) { 291 SLIST_REMOVE_HEAD(symlist_src2, links); 292 SLIST_INSERT_HEAD(symlist_dest, node, links); 293 } 294 295 /* These are now empty */ 296 SLIST_INIT(symlist_src1); 297 SLIST_INIT(symlist_src2); 298 } 299 300 void 301 symtable_dump(FILE *ofile) 302 { 303 /* 304 * Sort the registers by address with a simple insertion sort. 305 * Put bitmasks next to the first register that defines them. 306 * Put constants at the end. 307 */ 308 symlist_t registers; 309 symlist_t masks; 310 symlist_t constants; 311 symlist_t download_constants; 312 symlist_t aliases; 313 314 SLIST_INIT(®isters); 315 SLIST_INIT(&masks); 316 SLIST_INIT(&constants); 317 SLIST_INIT(&download_constants); 318 SLIST_INIT(&aliases); 319 320 if (symtable != NULL) { 321 DBT key; 322 DBT data; 323 int flag = R_FIRST; 324 325 while (symtable->seq(symtable, &key, &data, flag) == 0) { 326 symbol_t *cursym; 327 328 memcpy(&cursym, data.data, sizeof(cursym)); 329 switch(cursym->type) { 330 case REGISTER: 331 case SCBLOC: 332 case SRAMLOC: 333 symlist_add(®isters, cursym, SYMLIST_SORT); 334 break; 335 case MASK: 336 case BIT: 337 symlist_add(&masks, cursym, SYMLIST_SORT); 338 break; 339 case CONST: 340 if (cursym->info.cinfo->define == FALSE) { 341 symlist_add(&constants, cursym, 342 SYMLIST_INSERT_HEAD); 343 } 344 break; 345 case DOWNLOAD_CONST: 346 symlist_add(&download_constants, cursym, 347 SYMLIST_INSERT_HEAD); 348 break; 349 case ALIAS: 350 symlist_add(&aliases, cursym, 351 SYMLIST_INSERT_HEAD); 352 break; 353 default: 354 break; 355 } 356 flag = R_NEXT; 357 } 358 359 /* Put in the masks and bits */ 360 while (SLIST_FIRST(&masks) != NULL) { 361 symbol_node_t *curnode; 362 symbol_node_t *regnode; 363 char *regname; 364 365 curnode = SLIST_FIRST(&masks); 366 SLIST_REMOVE_HEAD(&masks, links); 367 368 regnode = 369 SLIST_FIRST(&curnode->symbol->info.minfo->symrefs); 370 regname = regnode->symbol->name; 371 regnode = symlist_search(®isters, regname); 372 SLIST_INSERT_AFTER(regnode, curnode, links); 373 } 374 375 /* Add the aliases */ 376 while (SLIST_FIRST(&aliases) != NULL) { 377 symbol_node_t *curnode; 378 symbol_node_t *regnode; 379 char *regname; 380 381 curnode = SLIST_FIRST(&aliases); 382 SLIST_REMOVE_HEAD(&aliases, links); 383 384 regname = curnode->symbol->info.ainfo->parent->name; 385 regnode = symlist_search(®isters, regname); 386 SLIST_INSERT_AFTER(regnode, curnode, links); 387 } 388 389 /* Output what we have */ 390 fprintf(ofile, 391 "/* 392 * DO NOT EDIT - This file is automatically generated. 393 */\n"); 394 while (SLIST_FIRST(®isters) != NULL) { 395 symbol_node_t *curnode; 396 u_int8_t value; 397 char *tab_str; 398 char *tab_str2; 399 400 curnode = SLIST_FIRST(®isters); 401 SLIST_REMOVE_HEAD(®isters, links); 402 switch(curnode->symbol->type) { 403 case REGISTER: 404 case SCBLOC: 405 case SRAMLOC: 406 fprintf(ofile, "\n"); 407 value = curnode->symbol->info.rinfo->address; 408 tab_str = "\t"; 409 tab_str2 = "\t\t"; 410 break; 411 case ALIAS: 412 { 413 symbol_t *parent; 414 415 parent = curnode->symbol->info.ainfo->parent; 416 value = parent->info.rinfo->address; 417 tab_str = "\t"; 418 tab_str2 = "\t\t"; 419 break; 420 } 421 case MASK: 422 case BIT: 423 value = curnode->symbol->info.minfo->mask; 424 tab_str = "\t\t"; 425 tab_str2 = "\t"; 426 break; 427 default: 428 value = 0; /* Quiet compiler */ 429 tab_str = NULL; 430 tab_str2 = NULL; 431 stop("symtable_dump: Invalid symbol type " 432 "encountered", EX_SOFTWARE); 433 break; 434 } 435 fprintf(ofile, "#define%s%-16s%s0x%02x\n", 436 tab_str, curnode->symbol->name, tab_str2, 437 value); 438 free(curnode); 439 } 440 fprintf(ofile, "\n\n"); 441 442 while (SLIST_FIRST(&constants) != NULL) { 443 symbol_node_t *curnode; 444 445 curnode = SLIST_FIRST(&constants); 446 SLIST_REMOVE_HEAD(&constants, links); 447 fprintf(ofile, "#define\t%-8s\t0x%02x\n", 448 curnode->symbol->name, 449 curnode->symbol->info.cinfo->value); 450 free(curnode); 451 } 452 453 454 fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n"); 455 456 while (SLIST_FIRST(&download_constants) != NULL) { 457 symbol_node_t *curnode; 458 459 curnode = SLIST_FIRST(&download_constants); 460 SLIST_REMOVE_HEAD(&download_constants, links); 461 fprintf(ofile, "#define\t%-8s\t0x%02x\n", 462 curnode->symbol->name, 463 curnode->symbol->info.cinfo->value); 464 free(curnode); 465 } 466 } 467 } 468 469