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