]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/aic7xxx/aicasm/aicasm_symbol.c
This commit was generated by cvs2svn to compensate for changes in r51363,
[FreeBSD/FreeBSD.git] / sys / dev / aic7xxx / aicasm / aicasm_symbol.c
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, immediately at the beginning of the file.
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  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31
32 #include <sys/types.h>
33
34 #include <db.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sysexits.h>
40
41 #include "aicasm_symbol.h"
42 #include "aicasm.h"
43
44 static DB *symtable;
45
46 symbol_t *
47 symbol_create(name)
48         char *name;
49 {
50         symbol_t *new_symbol;
51
52         new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
53         if (new_symbol == NULL) {
54                 perror("Unable to create new symbol");
55                 exit(EX_SOFTWARE);
56         }
57         memset(new_symbol, 0, sizeof(*new_symbol));
58         new_symbol->name = strdup(name);
59         new_symbol->type = UNINITIALIZED;
60         return (new_symbol);
61 }
62
63 void
64 symbol_delete(symbol)
65         symbol_t *symbol;
66 {
67         if (symtable != NULL) {
68                 DBT      key;
69
70                 key.data = symbol->name;
71                 key.size = strlen(symbol->name);
72                 symtable->del(symtable, &key, /*flags*/0);
73         }
74         switch(symbol->type) {
75         case SCBLOC:
76         case SRAMLOC:
77         case REGISTER:
78                 if (symbol->info.rinfo != NULL)
79                         free(symbol->info.rinfo);
80                 break;
81         case ALIAS:
82                 if (symbol->info.ainfo != NULL)
83                         free(symbol->info.ainfo);
84                 break;
85         case MASK:
86         case BIT:
87                 if (symbol->info.minfo != NULL) {
88                         symlist_free(&symbol->info.minfo->symrefs);
89                         free(symbol->info.minfo);
90                 }
91                 break;
92         case DOWNLOAD_CONST:
93         case CONST:
94                 if (symbol->info.cinfo != NULL)
95                         free(symbol->info.cinfo);
96                 break;
97         case LABEL:
98                 if (symbol->info.linfo != NULL)
99                         free(symbol->info.linfo);
100                 break;
101         case UNINITIALIZED:
102         default:
103                 break;
104         }
105         free(symbol->name);
106         free(symbol);
107 }
108
109 void
110 symtable_open()
111 {
112         symtable = dbopen(/*filename*/NULL,
113                           O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
114                           /*openinfo*/NULL);
115
116         if (symtable == NULL) {
117                 perror("Symbol table creation failed");
118                 exit(EX_SOFTWARE);
119                 /* NOTREACHED */
120         }
121 }
122
123 void
124 symtable_close()
125 {
126         if (symtable != NULL) {
127                 DBT      key;
128                 DBT      data;
129
130                 while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
131                         symbol_t *stored_ptr;
132
133                         memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
134                         symbol_delete(stored_ptr);
135                 }
136                 symtable->close(symtable);
137         }
138 }
139
140 /*
141  * The semantics of get is to return an uninitialized symbol entry
142  * if a lookup fails.
143  */
144 symbol_t *
145 symtable_get(name)
146         char *name;
147 {
148         symbol_t *stored_ptr;
149         DBT       key;
150         DBT       data;
151         int       retval;
152
153         key.data = (void *)name;
154         key.size = strlen(name);
155
156         if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
157                 if (retval == -1) {
158                         perror("Symbol table get operation failed");
159                         exit(EX_SOFTWARE);
160                         /* NOTREACHED */
161                 } else if (retval == 1) {
162                         /* Symbol wasn't found, so create a new one */
163                         symbol_t *new_symbol;
164
165                         new_symbol = symbol_create(name);
166                         data.data = &new_symbol;
167                         data.size = sizeof(new_symbol);
168                         if (symtable->put(symtable, &key, &data,
169                                           /*flags*/0) !=0) {
170                                 perror("Symtable put failed");
171                                 exit(EX_SOFTWARE);
172                         }
173                         return (new_symbol);
174                 } else {
175                         perror("Unexpected return value from db get routine");
176                         exit(EX_SOFTWARE);
177                         /* NOTREACHED */
178                 }
179         }
180         memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
181         return (stored_ptr);
182 }
183
184 symbol_node_t *
185 symlist_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
200 void
201 symlist_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
269 void
270 symlist_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
284 void
285 symlist_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
303 void
304 symtable_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 download_constants;
316         symlist_t aliases;
317
318         SLIST_INIT(&registers);
319         SLIST_INIT(&masks);
320         SLIST_INIT(&constants);
321         SLIST_INIT(&download_constants);
322         SLIST_INIT(&aliases);
323
324         if (symtable != NULL) {
325                 DBT      key;
326                 DBT      data;
327                 int      flag = R_FIRST;
328
329                 while (symtable->seq(symtable, &key, &data, flag) == 0) {
330                         symbol_t *cursym;
331
332                         memcpy(&cursym, data.data, sizeof(cursym));
333                         switch(cursym->type) {
334                         case REGISTER:
335                         case SCBLOC:
336                         case SRAMLOC:
337                                 symlist_add(&registers, cursym, SYMLIST_SORT);
338                                 break;
339                         case MASK:
340                         case BIT:
341                                 symlist_add(&masks, cursym, SYMLIST_SORT);
342                                 break;
343                         case CONST:
344                                 if (cursym->info.cinfo->define == FALSE) {
345                                         symlist_add(&constants, cursym,
346                                                     SYMLIST_INSERT_HEAD);
347                                 }
348                                 break;
349                         case DOWNLOAD_CONST:
350                                 symlist_add(&download_constants, cursym,
351                                             SYMLIST_INSERT_HEAD);
352                                 break;
353                         case ALIAS:
354                                 symlist_add(&aliases, cursym,
355                                             SYMLIST_INSERT_HEAD);
356                                 break;
357                         default:
358                                 break;
359                         }
360                         flag = R_NEXT;
361                 }
362
363                 /* Put in the masks and bits */
364                 while (masks.slh_first != NULL) {
365                         symbol_node_t *curnode;
366                         symbol_node_t *regnode;
367                         char *regname;
368
369                         curnode = masks.slh_first;
370                         SLIST_REMOVE_HEAD(&masks, links);
371
372                         regnode =
373                             curnode->symbol->info.minfo->symrefs.slh_first;
374                         regname = regnode->symbol->name;
375                         regnode = symlist_search(&registers, regname);
376                         SLIST_INSERT_AFTER(regnode, curnode, links);
377                 }
378
379                 /* Add the aliases */
380                 while (aliases.slh_first != NULL) {
381                         symbol_node_t *curnode;
382                         symbol_node_t *regnode;
383                         char *regname;
384
385                         curnode = aliases.slh_first;
386                         SLIST_REMOVE_HEAD(&aliases, links);
387
388                         regname = curnode->symbol->info.ainfo->parent->name;
389                         regnode = symlist_search(&registers, regname);
390                         SLIST_INSERT_AFTER(regnode, curnode, links);
391                 }
392
393                 /* Output what we have */
394                 fprintf(ofile,
395 "/*
396   * DO NOT EDIT - This file is automatically generated.
397   */\n");
398                 while (registers.slh_first != NULL) {
399                         symbol_node_t *curnode;
400                         u_int8_t value;
401                         char *tab_str;
402                         char *tab_str2;
403
404                         curnode = registers.slh_first;
405                         SLIST_REMOVE_HEAD(&registers, links);
406                         switch(curnode->symbol->type) {
407                         case REGISTER:
408                         case SCBLOC:
409                         case SRAMLOC:
410                                 fprintf(ofile, "\n");
411                                 value = curnode->symbol->info.rinfo->address;
412                                 tab_str = "\t";
413                                 tab_str2 = "\t\t";
414                                 break;
415                         case ALIAS:
416                         {
417                                 symbol_t *parent;
418
419                                 parent = curnode->symbol->info.ainfo->parent;
420                                 value = parent->info.rinfo->address;
421                                 tab_str = "\t";
422                                 tab_str2 = "\t\t";
423                                 break;
424                         }
425                         case MASK:
426                         case BIT:
427                                 value = curnode->symbol->info.minfo->mask;
428                                 tab_str = "\t\t";
429                                 tab_str2 = "\t";
430                                 break;
431                         default:
432                                 value = 0; /* Quiet compiler */
433                                 tab_str = NULL;
434                                 tab_str2 = NULL;
435                                 stop("symtable_dump: Invalid symbol type "
436                                      "encountered", EX_SOFTWARE);
437                                 break;
438                         }
439                         fprintf(ofile, "#define%s%-16s%s0x%02x\n",
440                                 tab_str, curnode->symbol->name, tab_str2,
441                                 value);
442                         free(curnode);
443                 }
444                 fprintf(ofile, "\n\n");
445
446                 while (constants.slh_first != NULL) {
447                         symbol_node_t *curnode;
448
449                         curnode = constants.slh_first;
450                         SLIST_REMOVE_HEAD(&constants, links);
451                         fprintf(ofile, "#define\t%-8s\t0x%02x\n",
452                                 curnode->symbol->name,
453                                 curnode->symbol->info.cinfo->value);
454                         free(curnode);
455                 }
456
457                 
458                 fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
459
460                 while (download_constants.slh_first != NULL) {
461                         symbol_node_t *curnode;
462
463                         curnode = download_constants.slh_first;
464                         SLIST_REMOVE_HEAD(&download_constants, links);
465                         fprintf(ofile, "#define\t%-8s\t0x%02x\n",
466                                 curnode->symbol->name,
467                                 curnode->symbol->info.cinfo->value);
468                         free(curnode);
469                 }
470         }
471 }
472