aicasm_symbol.c revision 79873
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#7 $
32 *
33 * $FreeBSD: head/sys/dev/aic7xxx/aicasm/aicasm_symbol.c 79873 2001-07-18 21:03:32Z gibbs $
34 */
35
36#include <sys/types.h>
37
38#ifdef __linux__
39#include "aicdb.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
52static DB *symtable;
53
54symbol_t *
55symbol_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
70void
71symbol_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
115void
116symtable_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
129void
130symtable_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 */
150symbol_t *
151symtable_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
189symbol_node_t *
190symlist_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
203void
204symlist_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
269void
270symlist_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
283void
284symlist_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
300void
301symtable_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(&registers);
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(&registers, 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(&registers, 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(&registers, 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 *		 from the following source files:
394 *
395%s */\n", versions);
396		while (SLIST_FIRST(&registers) != NULL) {
397			symbol_node_t *curnode;
398			u_int8_t value;
399			char *tab_str;
400			char *tab_str2;
401
402			curnode = SLIST_FIRST(&registers);
403			SLIST_REMOVE_HEAD(&registers, links);
404			switch(curnode->symbol->type) {
405			case REGISTER:
406			case SCBLOC:
407			case SRAMLOC:
408				fprintf(ofile, "\n");
409				value = curnode->symbol->info.rinfo->address;
410				tab_str = "\t";
411				tab_str2 = "\t\t";
412				break;
413			case ALIAS:
414			{
415				symbol_t *parent;
416
417				parent = curnode->symbol->info.ainfo->parent;
418				value = parent->info.rinfo->address;
419				tab_str = "\t";
420				tab_str2 = "\t\t";
421				break;
422			}
423			case MASK:
424			case BIT:
425				value = curnode->symbol->info.minfo->mask;
426				tab_str = "\t\t";
427				tab_str2 = "\t";
428				break;
429			default:
430				value = 0; /* Quiet compiler */
431				tab_str = NULL;
432				tab_str2 = NULL;
433				stop("symtable_dump: Invalid symbol type "
434				     "encountered", EX_SOFTWARE);
435				break;
436			}
437			fprintf(ofile, "#define%s%-16s%s0x%02x\n",
438				tab_str, curnode->symbol->name, tab_str2,
439				value);
440			free(curnode);
441		}
442		fprintf(ofile, "\n\n");
443
444		while (SLIST_FIRST(&constants) != NULL) {
445			symbol_node_t *curnode;
446
447			curnode = SLIST_FIRST(&constants);
448			SLIST_REMOVE_HEAD(&constants, links);
449			fprintf(ofile, "#define\t%-8s\t0x%02x\n",
450				curnode->symbol->name,
451				curnode->symbol->info.cinfo->value);
452			free(curnode);
453		}
454
455
456		fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
457
458		while (SLIST_FIRST(&download_constants) != NULL) {
459			symbol_node_t *curnode;
460
461			curnode = SLIST_FIRST(&download_constants);
462			SLIST_REMOVE_HEAD(&download_constants, links);
463			fprintf(ofile, "#define\t%-8s\t0x%02x\n",
464				curnode->symbol->name,
465				curnode->symbol->info.cinfo->value);
466			free(curnode);
467		}
468	}
469}
470
471