aicasm_symbol.c revision 1.2
1/*	$NetBSD: aicasm_symbol.c,v 1.2 2002/06/02 01:20:36 lukem 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
46static DB *symtable;
47
48symbol_t *
49symbol_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
65void
66symbol_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
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 *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 */
146symbol_t *
147symtable_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
186symbol_node_t *
187symlist_search(symlist, symname)
188	symlist_t *symlist;
189	char	  *symname;
190{
191	symbol_node_t *curnode;
192
193	curnode = SLIST_FIRST(symlist);
194	while(curnode != NULL) {
195		if (strcmp(symname, curnode->symbol->name) == 0)
196			break;
197		curnode = SLIST_NEXT(curnode, links);
198	}
199	return (curnode);
200}
201
202void
203symlist_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 = SLIST_FIRST(symlist);
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 (SLIST_NEXT(curnode, links) == NULL) {
248				SLIST_INSERT_AFTER(curnode, newnode,
249						   links);
250				break;
251			} else {
252				symbol_t *cursymbol;
253
254				cursymbol = SLIST_NEXT(curnode, links)->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 = SLIST_NEXT(curnode, links);
265		}
266	} else {
267		SLIST_INSERT_HEAD(symlist, newnode, links);
268	}
269}
270
271void
272symlist_free(symlist)
273	symlist_t *symlist;
274{
275	symbol_node_t *node1, *node2;
276
277	node1 = SLIST_FIRST(symlist);
278	while (node1 != NULL) {
279		node2 = SLIST_NEXT(node1, links);
280		free(node1);
281		node1 = node2;
282	}
283	SLIST_INIT(symlist);
284}
285
286void
287symlist_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 = SLIST_FIRST(symlist_src2)) != 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
305void
306symtable_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(&registers);
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(&registers, 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 (! SLIST_EMPTY(&masks)) {
367			symbol_node_t *curnode;
368			symbol_node_t *regnode;
369			char *regname;
370
371			curnode = SLIST_FIRST(&masks);
372			SLIST_REMOVE_HEAD(&masks, links);
373
374			regnode =
375			    SLIST_FIRST(&curnode->symbol->info.minfo->symrefs);
376			regname = regnode->symbol->name;
377			regnode = symlist_search(&registers, regname);
378			SLIST_INSERT_AFTER(regnode, curnode, links);
379		}
380
381		/* Add the aliases */
382		while (! SLIST_EMPTY(&aliases)) {
383			symbol_node_t *curnode;
384			symbol_node_t *regnode;
385			char *regname;
386
387			curnode = SLIST_FIRST(&aliases);
388			SLIST_REMOVE_HEAD(&aliases, links);
389
390			regname = curnode->symbol->info.ainfo->parent->name;
391			regnode = symlist_search(&registers, 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 (! SLIST_EMPTY(&registers)) {
401			symbol_node_t *curnode;
402			u_int8_t value;
403			char *tab_str;
404			char *tab_str2;
405
406			curnode = SLIST_FIRST(&registers);
407			SLIST_REMOVE_HEAD(&registers, 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 (! SLIST_EMPTY(&constants)) {
449			symbol_node_t *curnode;
450
451			curnode = SLIST_FIRST(&constants);
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 (! SLIST_EMPTY(&download_constants)) {
463			symbol_node_t *curnode;
464
465			curnode = SLIST_FIRST(&download_constants);
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