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(&registers);
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(&registers, 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(&registers, 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(&registers, 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(&registers, 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