162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Aic7xxx SCSI host adapter firmware assembler symbol table implementation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 1997 Justin T. Gibbs.
562306a36Sopenharmony_ci * Copyright (c) 2002 Adaptec Inc.
662306a36Sopenharmony_ci * All rights reserved.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
962306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1062306a36Sopenharmony_ci * are met:
1162306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
1262306a36Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
1362306a36Sopenharmony_ci *    without modification.
1462306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1562306a36Sopenharmony_ci *    substantially similar to the "NO WARRANTY" disclaimer below
1662306a36Sopenharmony_ci *    ("Disclaimer") and any redistribution must be conditioned upon
1762306a36Sopenharmony_ci *    including a substantially similar Disclaimer requirement for further
1862306a36Sopenharmony_ci *    binary redistribution.
1962306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names
2062306a36Sopenharmony_ci *    of any contributors may be used to endorse or promote products derived
2162306a36Sopenharmony_ci *    from this software without specific prior written permission.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
2462306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free
2562306a36Sopenharmony_ci * Software Foundation.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * NO WARRANTY
2862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2962306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3062306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3162306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3262306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3362306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3462306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3562306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3662306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3762306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3862306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#24 $
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * $FreeBSD$
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include <sys/types.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#include "aicdb.h"
4862306a36Sopenharmony_ci#include <fcntl.h>
4962306a36Sopenharmony_ci#include <inttypes.h>
5062306a36Sopenharmony_ci#include <regex.h>
5162306a36Sopenharmony_ci#include <stdio.h>
5262306a36Sopenharmony_ci#include <stdlib.h>
5362306a36Sopenharmony_ci#include <string.h>
5462306a36Sopenharmony_ci#include <sysexits.h>
5562306a36Sopenharmony_ci#include <ctype.h>
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#include "aicasm_symbol.h"
5862306a36Sopenharmony_ci#include "aicasm.h"
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic DB *symtable;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cisymbol_t *
6362306a36Sopenharmony_cisymbol_create(char *name)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	symbol_t *new_symbol;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
6862306a36Sopenharmony_ci	if (new_symbol == NULL) {
6962306a36Sopenharmony_ci		perror("Unable to create new symbol");
7062306a36Sopenharmony_ci		exit(EX_SOFTWARE);
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	memset(new_symbol, 0, sizeof(*new_symbol));
7362306a36Sopenharmony_ci	new_symbol->name = strdup(name);
7462306a36Sopenharmony_ci	if (new_symbol->name == NULL)
7562306a36Sopenharmony_ci		 stop("Unable to strdup symbol name", EX_SOFTWARE);
7662306a36Sopenharmony_ci	new_symbol->type = UNINITIALIZED;
7762306a36Sopenharmony_ci	new_symbol->count = 1;
7862306a36Sopenharmony_ci	return (new_symbol);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_civoid
8262306a36Sopenharmony_cisymbol_delete(symbol_t *symbol)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	if (symtable != NULL) {
8562306a36Sopenharmony_ci		DBT	 key;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci		key.data = symbol->name;
8862306a36Sopenharmony_ci		key.size = strlen(symbol->name);
8962306a36Sopenharmony_ci		symtable->del(symtable, &key, /*flags*/0);
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci	switch(symbol->type) {
9262306a36Sopenharmony_ci	case SCBLOC:
9362306a36Sopenharmony_ci	case SRAMLOC:
9462306a36Sopenharmony_ci	case REGISTER:
9562306a36Sopenharmony_ci		if (symbol->info.rinfo != NULL)
9662306a36Sopenharmony_ci			free(symbol->info.rinfo);
9762306a36Sopenharmony_ci		break;
9862306a36Sopenharmony_ci	case ALIAS:
9962306a36Sopenharmony_ci		if (symbol->info.ainfo != NULL)
10062306a36Sopenharmony_ci			free(symbol->info.ainfo);
10162306a36Sopenharmony_ci		break;
10262306a36Sopenharmony_ci	case MASK:
10362306a36Sopenharmony_ci	case FIELD:
10462306a36Sopenharmony_ci	case ENUM:
10562306a36Sopenharmony_ci	case ENUM_ENTRY:
10662306a36Sopenharmony_ci		if (symbol->info.finfo != NULL) {
10762306a36Sopenharmony_ci			symlist_free(&symbol->info.finfo->symrefs);
10862306a36Sopenharmony_ci			free(symbol->info.finfo);
10962306a36Sopenharmony_ci		}
11062306a36Sopenharmony_ci		break;
11162306a36Sopenharmony_ci	case DOWNLOAD_CONST:
11262306a36Sopenharmony_ci	case CONST:
11362306a36Sopenharmony_ci		if (symbol->info.cinfo != NULL)
11462306a36Sopenharmony_ci			free(symbol->info.cinfo);
11562306a36Sopenharmony_ci		break;
11662306a36Sopenharmony_ci	case LABEL:
11762306a36Sopenharmony_ci		if (symbol->info.linfo != NULL)
11862306a36Sopenharmony_ci			free(symbol->info.linfo);
11962306a36Sopenharmony_ci		break;
12062306a36Sopenharmony_ci	case UNINITIALIZED:
12162306a36Sopenharmony_ci	default:
12262306a36Sopenharmony_ci		break;
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci	free(symbol->name);
12562306a36Sopenharmony_ci	free(symbol);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_civoid
12962306a36Sopenharmony_cisymtable_open()
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	symtable = dbopen(/*filename*/NULL,
13262306a36Sopenharmony_ci			  O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
13362306a36Sopenharmony_ci			  /*openinfo*/NULL);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	if (symtable == NULL) {
13662306a36Sopenharmony_ci		perror("Symbol table creation failed");
13762306a36Sopenharmony_ci		exit(EX_SOFTWARE);
13862306a36Sopenharmony_ci		/* NOTREACHED */
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_civoid
14362306a36Sopenharmony_cisymtable_close()
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	if (symtable != NULL) {
14662306a36Sopenharmony_ci		DBT	 key;
14762306a36Sopenharmony_ci		DBT	 data;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
15062306a36Sopenharmony_ci			symbol_t *stored_ptr;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci			memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
15362306a36Sopenharmony_ci			symbol_delete(stored_ptr);
15462306a36Sopenharmony_ci		}
15562306a36Sopenharmony_ci		symtable->close(symtable);
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*
16062306a36Sopenharmony_ci * The semantics of get is to return an uninitialized symbol entry
16162306a36Sopenharmony_ci * if a lookup fails.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_cisymbol_t *
16462306a36Sopenharmony_cisymtable_get(char *name)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	symbol_t *stored_ptr;
16762306a36Sopenharmony_ci	DBT	  key;
16862306a36Sopenharmony_ci	DBT	  data;
16962306a36Sopenharmony_ci	int	  retval;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	key.data = (void *)name;
17262306a36Sopenharmony_ci	key.size = strlen(name);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
17562306a36Sopenharmony_ci		if (retval == -1) {
17662306a36Sopenharmony_ci			perror("Symbol table get operation failed");
17762306a36Sopenharmony_ci			exit(EX_SOFTWARE);
17862306a36Sopenharmony_ci			/* NOTREACHED */
17962306a36Sopenharmony_ci		} else if (retval == 1) {
18062306a36Sopenharmony_ci			/* Symbol wasn't found, so create a new one */
18162306a36Sopenharmony_ci			symbol_t *new_symbol;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci			new_symbol = symbol_create(name);
18462306a36Sopenharmony_ci			data.data = &new_symbol;
18562306a36Sopenharmony_ci			data.size = sizeof(new_symbol);
18662306a36Sopenharmony_ci			if (symtable->put(symtable, &key, &data,
18762306a36Sopenharmony_ci					  /*flags*/0) !=0) {
18862306a36Sopenharmony_ci				perror("Symtable put failed");
18962306a36Sopenharmony_ci				exit(EX_SOFTWARE);
19062306a36Sopenharmony_ci			}
19162306a36Sopenharmony_ci			return (new_symbol);
19262306a36Sopenharmony_ci		} else {
19362306a36Sopenharmony_ci			perror("Unexpected return value from db get routine");
19462306a36Sopenharmony_ci			exit(EX_SOFTWARE);
19562306a36Sopenharmony_ci			/* NOTREACHED */
19662306a36Sopenharmony_ci		}
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci	memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
19962306a36Sopenharmony_ci	stored_ptr->count++;
20062306a36Sopenharmony_ci	data.data = &stored_ptr;
20162306a36Sopenharmony_ci	if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
20262306a36Sopenharmony_ci		perror("Symtable put failed");
20362306a36Sopenharmony_ci		exit(EX_SOFTWARE);
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci	return (stored_ptr);
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cisymbol_node_t *
20962306a36Sopenharmony_cisymlist_search(symlist_t *symlist, char *symname)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	symbol_node_t *curnode;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	curnode = SLIST_FIRST(symlist);
21462306a36Sopenharmony_ci	while(curnode != NULL) {
21562306a36Sopenharmony_ci		if (strcmp(symname, curnode->symbol->name) == 0)
21662306a36Sopenharmony_ci			break;
21762306a36Sopenharmony_ci		curnode = SLIST_NEXT(curnode, links);
21862306a36Sopenharmony_ci	}
21962306a36Sopenharmony_ci	return (curnode);
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_civoid
22362306a36Sopenharmony_cisymlist_add(symlist_t *symlist, symbol_t *symbol, int how)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	symbol_node_t *newnode;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
22862306a36Sopenharmony_ci	if (newnode == NULL) {
22962306a36Sopenharmony_ci		stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
23062306a36Sopenharmony_ci		/* NOTREACHED */
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci	newnode->symbol = symbol;
23362306a36Sopenharmony_ci	if (how == SYMLIST_SORT) {
23462306a36Sopenharmony_ci		symbol_node_t *curnode;
23562306a36Sopenharmony_ci		int field;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		field = FALSE;
23862306a36Sopenharmony_ci		switch(symbol->type) {
23962306a36Sopenharmony_ci		case REGISTER:
24062306a36Sopenharmony_ci		case SCBLOC:
24162306a36Sopenharmony_ci		case SRAMLOC:
24262306a36Sopenharmony_ci			break;
24362306a36Sopenharmony_ci		case FIELD:
24462306a36Sopenharmony_ci		case MASK:
24562306a36Sopenharmony_ci		case ENUM:
24662306a36Sopenharmony_ci		case ENUM_ENTRY:
24762306a36Sopenharmony_ci			field = TRUE;
24862306a36Sopenharmony_ci			break;
24962306a36Sopenharmony_ci		default:
25062306a36Sopenharmony_ci			stop("symlist_add: Invalid symbol type for sorting",
25162306a36Sopenharmony_ci			     EX_SOFTWARE);
25262306a36Sopenharmony_ci			/* NOTREACHED */
25362306a36Sopenharmony_ci		}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci		curnode = SLIST_FIRST(symlist);
25662306a36Sopenharmony_ci		if (curnode == NULL
25762306a36Sopenharmony_ci		 || (field
25862306a36Sopenharmony_ci		  && (curnode->symbol->type > newnode->symbol->type
25962306a36Sopenharmony_ci		   || (curnode->symbol->type == newnode->symbol->type
26062306a36Sopenharmony_ci		    && (curnode->symbol->info.finfo->value >
26162306a36Sopenharmony_ci			newnode->symbol->info.finfo->value))))
26262306a36Sopenharmony_ci		 || (!field && (curnode->symbol->info.rinfo->address >
26362306a36Sopenharmony_ci				newnode->symbol->info.rinfo->address))) {
26462306a36Sopenharmony_ci			SLIST_INSERT_HEAD(symlist, newnode, links);
26562306a36Sopenharmony_ci			return;
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		while (1) {
26962306a36Sopenharmony_ci			if (SLIST_NEXT(curnode, links) == NULL) {
27062306a36Sopenharmony_ci				SLIST_INSERT_AFTER(curnode, newnode,
27162306a36Sopenharmony_ci						   links);
27262306a36Sopenharmony_ci				break;
27362306a36Sopenharmony_ci			} else {
27462306a36Sopenharmony_ci				symbol_t *cursymbol;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci				cursymbol = SLIST_NEXT(curnode, links)->symbol;
27762306a36Sopenharmony_ci				if ((field
27862306a36Sopenharmony_ci				  && (cursymbol->type > symbol->type
27962306a36Sopenharmony_ci				   || (cursymbol->type == symbol->type
28062306a36Sopenharmony_ci				    && (cursymbol->info.finfo->value >
28162306a36Sopenharmony_ci					symbol->info.finfo->value))))
28262306a36Sopenharmony_ci				 || (!field
28362306a36Sopenharmony_ci				   && (cursymbol->info.rinfo->address >
28462306a36Sopenharmony_ci				       symbol->info.rinfo->address))) {
28562306a36Sopenharmony_ci					SLIST_INSERT_AFTER(curnode, newnode,
28662306a36Sopenharmony_ci							   links);
28762306a36Sopenharmony_ci					break;
28862306a36Sopenharmony_ci				}
28962306a36Sopenharmony_ci			}
29062306a36Sopenharmony_ci			curnode = SLIST_NEXT(curnode, links);
29162306a36Sopenharmony_ci		}
29262306a36Sopenharmony_ci	} else {
29362306a36Sopenharmony_ci		SLIST_INSERT_HEAD(symlist, newnode, links);
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_civoid
29862306a36Sopenharmony_cisymlist_free(symlist_t *symlist)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	symbol_node_t *node1, *node2;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	node1 = SLIST_FIRST(symlist);
30362306a36Sopenharmony_ci	while (node1 != NULL) {
30462306a36Sopenharmony_ci		node2 = SLIST_NEXT(node1, links);
30562306a36Sopenharmony_ci		free(node1);
30662306a36Sopenharmony_ci		node1 = node2;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci	SLIST_INIT(symlist);
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_civoid
31262306a36Sopenharmony_cisymlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
31362306a36Sopenharmony_ci	      symlist_t *symlist_src2)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	symbol_node_t *node;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	*symlist_dest = *symlist_src1;
31862306a36Sopenharmony_ci	while((node = SLIST_FIRST(symlist_src2)) != NULL) {
31962306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(symlist_src2, links);
32062306a36Sopenharmony_ci		SLIST_INSERT_HEAD(symlist_dest, node, links);
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* These are now empty */
32462306a36Sopenharmony_ci	SLIST_INIT(symlist_src1);
32562306a36Sopenharmony_ci	SLIST_INIT(symlist_src2);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_civoid
32962306a36Sopenharmony_ciaic_print_file_prologue(FILE *ofile)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	if (ofile == NULL)
33362306a36Sopenharmony_ci		return;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	fprintf(ofile,
33662306a36Sopenharmony_ci"/*\n"
33762306a36Sopenharmony_ci" * DO NOT EDIT - This file is automatically generated\n"
33862306a36Sopenharmony_ci" *		 from the following source files:\n"
33962306a36Sopenharmony_ci" *\n"
34062306a36Sopenharmony_ci"%s */\n",
34162306a36Sopenharmony_ci		versions);
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_civoid
34562306a36Sopenharmony_ciaic_print_include(FILE *dfile, char *include_file)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	if (dfile == NULL)
34962306a36Sopenharmony_ci		return;
35062306a36Sopenharmony_ci	fprintf(dfile, "\n#include \"%s\"\n\n", include_file);
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_civoid
35462306a36Sopenharmony_ciaic_print_reg_dump_types(FILE *ofile)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	if (ofile == NULL)
35762306a36Sopenharmony_ci		return;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	fprintf(ofile,
36062306a36Sopenharmony_ci"typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
36162306a36Sopenharmony_ci"typedef struct %sreg_parse_entry {\n"
36262306a36Sopenharmony_ci"	char	*name;\n"
36362306a36Sopenharmony_ci"	uint8_t	 value;\n"
36462306a36Sopenharmony_ci"	uint8_t	 mask;\n"
36562306a36Sopenharmony_ci"} %sreg_parse_entry_t;\n"
36662306a36Sopenharmony_ci"\n",
36762306a36Sopenharmony_ci		prefix, prefix, prefix);
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic void
37162306a36Sopenharmony_ciaic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	if (dfile == NULL)
37462306a36Sopenharmony_ci		return;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	fprintf(dfile,
37762306a36Sopenharmony_ci"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
37862306a36Sopenharmony_ci		prefix,
37962306a36Sopenharmony_ci		regnode->symbol->name);
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_cistatic void
38362306a36Sopenharmony_ciaic_print_reg_dump_end(FILE *ofile, FILE *dfile,
38462306a36Sopenharmony_ci		       symbol_node_t *regnode, u_int num_entries)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	char *lower_name;
38762306a36Sopenharmony_ci	char *letter;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	lower_name = strdup(regnode->symbol->name);
39062306a36Sopenharmony_ci	if (lower_name == NULL)
39162306a36Sopenharmony_ci		 stop("Unable to strdup symbol name", EX_SOFTWARE);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	for (letter = lower_name; *letter != '\0'; letter++)
39462306a36Sopenharmony_ci		*letter = tolower(*letter);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	if (dfile != NULL) {
39762306a36Sopenharmony_ci		if (num_entries != 0)
39862306a36Sopenharmony_ci			fprintf(dfile,
39962306a36Sopenharmony_ci"\n"
40062306a36Sopenharmony_ci"};\n"
40162306a36Sopenharmony_ci"\n");
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		fprintf(dfile,
40462306a36Sopenharmony_ci"int\n"
40562306a36Sopenharmony_ci"%s%s_print(u_int regvalue, u_int *cur_col, u_int wrap)\n"
40662306a36Sopenharmony_ci"{\n"
40762306a36Sopenharmony_ci"	return (%sprint_register(%s%s, %d, \"%s\",\n"
40862306a36Sopenharmony_ci"	    0x%02x, regvalue, cur_col, wrap));\n"
40962306a36Sopenharmony_ci"}\n"
41062306a36Sopenharmony_ci"\n",
41162306a36Sopenharmony_ci			prefix,
41262306a36Sopenharmony_ci			lower_name,
41362306a36Sopenharmony_ci			prefix,
41462306a36Sopenharmony_ci			num_entries != 0 ? regnode->symbol->name : "NULL",
41562306a36Sopenharmony_ci			num_entries != 0 ? "_parse_table" : "",
41662306a36Sopenharmony_ci			num_entries,
41762306a36Sopenharmony_ci			regnode->symbol->name,
41862306a36Sopenharmony_ci			regnode->symbol->info.rinfo->address);
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	fprintf(ofile,
42262306a36Sopenharmony_ci"#if AIC_DEBUG_REGISTERS\n"
42362306a36Sopenharmony_ci"%sreg_print_t %s%s_print;\n"
42462306a36Sopenharmony_ci"#else\n"
42562306a36Sopenharmony_ci"#define %s%s_print(regvalue, cur_col, wrap) \\\n"
42662306a36Sopenharmony_ci"    %sprint_register(NULL, 0, \"%s\", 0x%02x, regvalue, cur_col, wrap)\n"
42762306a36Sopenharmony_ci"#endif\n"
42862306a36Sopenharmony_ci"\n",
42962306a36Sopenharmony_ci		prefix,
43062306a36Sopenharmony_ci		prefix,
43162306a36Sopenharmony_ci		lower_name,
43262306a36Sopenharmony_ci		prefix,
43362306a36Sopenharmony_ci		lower_name,
43462306a36Sopenharmony_ci		prefix,
43562306a36Sopenharmony_ci		regnode->symbol->name,
43662306a36Sopenharmony_ci		regnode->symbol->info.rinfo->address);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic void
44062306a36Sopenharmony_ciaic_print_reg_dump_entry(FILE *dfile, symbol_node_t *curnode)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	int num_tabs;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (dfile == NULL)
44562306a36Sopenharmony_ci		return;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	fprintf(dfile,
44862306a36Sopenharmony_ci"	{ \"%s\",",
44962306a36Sopenharmony_ci		curnode->symbol->name);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	num_tabs = 3 - (strlen(curnode->symbol->name) + 5) / 8;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	while (num_tabs-- > 0)
45462306a36Sopenharmony_ci		fputc('\t', dfile);
45562306a36Sopenharmony_ci	fprintf(dfile, "0x%02x, 0x%02x }",
45662306a36Sopenharmony_ci		curnode->symbol->info.finfo->value,
45762306a36Sopenharmony_ci		curnode->symbol->info.finfo->mask);
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_civoid
46162306a36Sopenharmony_cisymtable_dump(FILE *ofile, FILE *dfile)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	/*
46462306a36Sopenharmony_ci	 * Sort the registers by address with a simple insertion sort.
46562306a36Sopenharmony_ci	 * Put bitmasks next to the first register that defines them.
46662306a36Sopenharmony_ci	 * Put constants at the end.
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci	symlist_t	 registers;
46962306a36Sopenharmony_ci	symlist_t	 masks;
47062306a36Sopenharmony_ci	symlist_t	 constants;
47162306a36Sopenharmony_ci	symlist_t	 download_constants;
47262306a36Sopenharmony_ci	symlist_t	 aliases;
47362306a36Sopenharmony_ci	symlist_t	 exported_labels;
47462306a36Sopenharmony_ci	symbol_node_t	*curnode;
47562306a36Sopenharmony_ci	symbol_node_t	*regnode;
47662306a36Sopenharmony_ci	DBT		 key;
47762306a36Sopenharmony_ci	DBT		 data;
47862306a36Sopenharmony_ci	int		 flag;
47962306a36Sopenharmony_ci	int		 reg_count = 0, reg_used = 0;
48062306a36Sopenharmony_ci	u_int		 i;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	if (symtable == NULL)
48362306a36Sopenharmony_ci		return;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	SLIST_INIT(&registers);
48662306a36Sopenharmony_ci	SLIST_INIT(&masks);
48762306a36Sopenharmony_ci	SLIST_INIT(&constants);
48862306a36Sopenharmony_ci	SLIST_INIT(&download_constants);
48962306a36Sopenharmony_ci	SLIST_INIT(&aliases);
49062306a36Sopenharmony_ci	SLIST_INIT(&exported_labels);
49162306a36Sopenharmony_ci	flag = R_FIRST;
49262306a36Sopenharmony_ci	while (symtable->seq(symtable, &key, &data, flag) == 0) {
49362306a36Sopenharmony_ci		symbol_t *cursym;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci		memcpy(&cursym, data.data, sizeof(cursym));
49662306a36Sopenharmony_ci		switch(cursym->type) {
49762306a36Sopenharmony_ci		case REGISTER:
49862306a36Sopenharmony_ci		case SCBLOC:
49962306a36Sopenharmony_ci		case SRAMLOC:
50062306a36Sopenharmony_ci			symlist_add(&registers, cursym, SYMLIST_SORT);
50162306a36Sopenharmony_ci			break;
50262306a36Sopenharmony_ci		case MASK:
50362306a36Sopenharmony_ci		case FIELD:
50462306a36Sopenharmony_ci		case ENUM:
50562306a36Sopenharmony_ci		case ENUM_ENTRY:
50662306a36Sopenharmony_ci			symlist_add(&masks, cursym, SYMLIST_SORT);
50762306a36Sopenharmony_ci			break;
50862306a36Sopenharmony_ci		case CONST:
50962306a36Sopenharmony_ci			symlist_add(&constants, cursym,
51062306a36Sopenharmony_ci				    SYMLIST_INSERT_HEAD);
51162306a36Sopenharmony_ci			break;
51262306a36Sopenharmony_ci		case DOWNLOAD_CONST:
51362306a36Sopenharmony_ci			symlist_add(&download_constants, cursym,
51462306a36Sopenharmony_ci				    SYMLIST_INSERT_HEAD);
51562306a36Sopenharmony_ci			break;
51662306a36Sopenharmony_ci		case ALIAS:
51762306a36Sopenharmony_ci			symlist_add(&aliases, cursym,
51862306a36Sopenharmony_ci				    SYMLIST_INSERT_HEAD);
51962306a36Sopenharmony_ci			break;
52062306a36Sopenharmony_ci		case LABEL:
52162306a36Sopenharmony_ci			if (cursym->info.linfo->exported == 0)
52262306a36Sopenharmony_ci				break;
52362306a36Sopenharmony_ci			symlist_add(&exported_labels, cursym,
52462306a36Sopenharmony_ci				    SYMLIST_INSERT_HEAD);
52562306a36Sopenharmony_ci			break;
52662306a36Sopenharmony_ci		default:
52762306a36Sopenharmony_ci			break;
52862306a36Sopenharmony_ci		}
52962306a36Sopenharmony_ci		flag = R_NEXT;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* Register dianostic functions/declarations first. */
53362306a36Sopenharmony_ci	aic_print_file_prologue(ofile);
53462306a36Sopenharmony_ci	aic_print_reg_dump_types(ofile);
53562306a36Sopenharmony_ci	aic_print_file_prologue(dfile);
53662306a36Sopenharmony_ci	aic_print_include(dfile, stock_include_file);
53762306a36Sopenharmony_ci	SLIST_FOREACH(curnode, &registers, links) {
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		if (curnode->symbol->dont_generate_debug_code)
54062306a36Sopenharmony_ci			continue;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci		switch(curnode->symbol->type) {
54362306a36Sopenharmony_ci		case REGISTER:
54462306a36Sopenharmony_ci		case SCBLOC:
54562306a36Sopenharmony_ci		case SRAMLOC:
54662306a36Sopenharmony_ci		{
54762306a36Sopenharmony_ci			symlist_t	*fields;
54862306a36Sopenharmony_ci			symbol_node_t	*fieldnode;
54962306a36Sopenharmony_ci			int		 num_entries;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci			num_entries = 0;
55262306a36Sopenharmony_ci			reg_count++;
55362306a36Sopenharmony_ci			if (curnode->symbol->count == 1)
55462306a36Sopenharmony_ci				break;
55562306a36Sopenharmony_ci			fields = &curnode->symbol->info.rinfo->fields;
55662306a36Sopenharmony_ci			SLIST_FOREACH(fieldnode, fields, links) {
55762306a36Sopenharmony_ci				if (num_entries == 0)
55862306a36Sopenharmony_ci					aic_print_reg_dump_start(dfile,
55962306a36Sopenharmony_ci								 curnode);
56062306a36Sopenharmony_ci				else if (dfile != NULL)
56162306a36Sopenharmony_ci					fputs(",\n", dfile);
56262306a36Sopenharmony_ci				num_entries++;
56362306a36Sopenharmony_ci				aic_print_reg_dump_entry(dfile, fieldnode);
56462306a36Sopenharmony_ci			}
56562306a36Sopenharmony_ci			aic_print_reg_dump_end(ofile, dfile,
56662306a36Sopenharmony_ci					       curnode, num_entries);
56762306a36Sopenharmony_ci			reg_used++;
56862306a36Sopenharmony_ci		}
56962306a36Sopenharmony_ci		default:
57062306a36Sopenharmony_ci			break;
57162306a36Sopenharmony_ci		}
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci	fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
57462306a36Sopenharmony_ci		reg_used, reg_count);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	/* Fold in the masks and bits */
57762306a36Sopenharmony_ci	while (SLIST_FIRST(&masks) != NULL) {
57862306a36Sopenharmony_ci		char *regname;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci		curnode = SLIST_FIRST(&masks);
58162306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&masks, links);
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);
58462306a36Sopenharmony_ci		regname = regnode->symbol->name;
58562306a36Sopenharmony_ci		regnode = symlist_search(&registers, regname);
58662306a36Sopenharmony_ci		SLIST_INSERT_AFTER(regnode, curnode, links);
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	/* Add the aliases */
59062306a36Sopenharmony_ci	while (SLIST_FIRST(&aliases) != NULL) {
59162306a36Sopenharmony_ci		char *regname;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		curnode = SLIST_FIRST(&aliases);
59462306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&aliases, links);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci		regname = curnode->symbol->info.ainfo->parent->name;
59762306a36Sopenharmony_ci		regnode = symlist_search(&registers, regname);
59862306a36Sopenharmony_ci		SLIST_INSERT_AFTER(regnode, curnode, links);
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/* Output generated #defines. */
60262306a36Sopenharmony_ci	while (SLIST_FIRST(&registers) != NULL) {
60362306a36Sopenharmony_ci		symbol_node_t *curnode;
60462306a36Sopenharmony_ci		u_int value;
60562306a36Sopenharmony_ci		char *tab_str;
60662306a36Sopenharmony_ci		char *tab_str2;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		curnode = SLIST_FIRST(&registers);
60962306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&registers, links);
61062306a36Sopenharmony_ci		switch(curnode->symbol->type) {
61162306a36Sopenharmony_ci		case REGISTER:
61262306a36Sopenharmony_ci		case SCBLOC:
61362306a36Sopenharmony_ci		case SRAMLOC:
61462306a36Sopenharmony_ci			fprintf(ofile, "\n");
61562306a36Sopenharmony_ci			value = curnode->symbol->info.rinfo->address;
61662306a36Sopenharmony_ci			tab_str = "\t";
61762306a36Sopenharmony_ci			tab_str2 = "\t\t";
61862306a36Sopenharmony_ci			break;
61962306a36Sopenharmony_ci		case ALIAS:
62062306a36Sopenharmony_ci		{
62162306a36Sopenharmony_ci			symbol_t *parent;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci			parent = curnode->symbol->info.ainfo->parent;
62462306a36Sopenharmony_ci			value = parent->info.rinfo->address;
62562306a36Sopenharmony_ci			tab_str = "\t";
62662306a36Sopenharmony_ci			tab_str2 = "\t\t";
62762306a36Sopenharmony_ci			break;
62862306a36Sopenharmony_ci		}
62962306a36Sopenharmony_ci		case MASK:
63062306a36Sopenharmony_ci		case FIELD:
63162306a36Sopenharmony_ci		case ENUM:
63262306a36Sopenharmony_ci		case ENUM_ENTRY:
63362306a36Sopenharmony_ci			value = curnode->symbol->info.finfo->value;
63462306a36Sopenharmony_ci			tab_str = "\t\t";
63562306a36Sopenharmony_ci			tab_str2 = "\t";
63662306a36Sopenharmony_ci			break;
63762306a36Sopenharmony_ci		default:
63862306a36Sopenharmony_ci			value = 0; /* Quiet compiler */
63962306a36Sopenharmony_ci			tab_str = NULL;
64062306a36Sopenharmony_ci			tab_str2 = NULL;
64162306a36Sopenharmony_ci			stop("symtable_dump: Invalid symbol type "
64262306a36Sopenharmony_ci			     "encountered", EX_SOFTWARE);
64362306a36Sopenharmony_ci			break;
64462306a36Sopenharmony_ci		}
64562306a36Sopenharmony_ci		fprintf(ofile, "#define%s%-16s%s0x%02x\n",
64662306a36Sopenharmony_ci			tab_str, curnode->symbol->name, tab_str2,
64762306a36Sopenharmony_ci			value);
64862306a36Sopenharmony_ci		free(curnode);
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci	fprintf(ofile, "\n\n");
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	while (SLIST_FIRST(&constants) != NULL) {
65362306a36Sopenharmony_ci		symbol_node_t *curnode;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci		curnode = SLIST_FIRST(&constants);
65662306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&constants, links);
65762306a36Sopenharmony_ci		fprintf(ofile, "#define\t%-8s\t0x%02x\n",
65862306a36Sopenharmony_ci			curnode->symbol->name,
65962306a36Sopenharmony_ci			curnode->symbol->info.cinfo->value);
66062306a36Sopenharmony_ci		free(curnode);
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
66662306a36Sopenharmony_ci		symbol_node_t *curnode;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci		curnode = SLIST_FIRST(&download_constants);
66962306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&download_constants, links);
67062306a36Sopenharmony_ci		fprintf(ofile, "#define\t%-8s\t0x%02x\n",
67162306a36Sopenharmony_ci			curnode->symbol->name,
67262306a36Sopenharmony_ci			curnode->symbol->info.cinfo->value);
67362306a36Sopenharmony_ci		free(curnode);
67462306a36Sopenharmony_ci	}
67562306a36Sopenharmony_ci	fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	fprintf(ofile, "\n\n/* Exported Labels */\n");
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	while (SLIST_FIRST(&exported_labels) != NULL) {
68062306a36Sopenharmony_ci		symbol_node_t *curnode;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci		curnode = SLIST_FIRST(&exported_labels);
68362306a36Sopenharmony_ci		SLIST_REMOVE_HEAD(&exported_labels, links);
68462306a36Sopenharmony_ci		fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",
68562306a36Sopenharmony_ci			curnode->symbol->name,
68662306a36Sopenharmony_ci			curnode->symbol->info.linfo->address);
68762306a36Sopenharmony_ci		free(curnode);
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
691