add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
PROG= aicasm
.SUFFIXES= .l .y .c .h
CSRCS= aicasm.c aicasm_symbol.c
YSRCS= aicasm_gram.y aicasm_macro_gram.y
LSRCS= aicasm_scan.l aicasm_macro_scan.l
GENHDRS= aicdb.h $(YSRCS:.y=.h)
GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c)
SRCS= ${CSRCS} ${GENSRCS}
LIBS= -ldb
clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG)
# Override default kernel CFLAGS. This is a userland app.
AICASM_CFLAGS:= -I/usr/include -I.
LEX= flex
YACC= bison
YFLAGS= -d
NOMAN= noman
ifneq ($(HOSTCC),)
AICASM_CC= $(HOSTCC)
else
AICASM_CC= $(CC)
endif
ifdef DEBUG
CFLAGS+= -DDEBUG -g
YFLAGS+= -t -v
LFLAGS= -d
endif
$(PROG): ${GENHDRS} $(SRCS)
$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
aicdb.h:
@if [ -e "/usr/include/db4/db_185.h" ]; then \
echo "#include <db4/db_185.h>" > aicdb.h; \
elif [ -e "/usr/include/db3/db_185.h" ]; then \
echo "#include <db3/db_185.h>" > aicdb.h; \
elif [ -e "/usr/include/db2/db_185.h" ]; then \
echo "#include <db2/db_185.h>" > aicdb.h; \
elif [ -e "/usr/include/db1/db_185.h" ]; then \
echo "#include <db1/db_185.h>" > aicdb.h; \
elif [ -e "/usr/include/db/db_185.h" ]; then \
echo "#include <db/db_185.h>" > aicdb.h; \
elif [ -e "/usr/include/db_185.h" ]; then \
echo "#include <db_185.h>" > aicdb.h; \
else \
echo "*** Install db development libraries"; \
fi
clean:
rm -f $(clean-files)
# Create a dependency chain in generated files
# to avoid concurrent invocations of the single
# rule that builds them all.
aicasm_gram.c: aicasm_gram.h
aicasm_gram.c aicasm_gram.h: aicasm_gram.y
$(YACC) $(YFLAGS) -b $(<:.y=) $<
mv $(<:.y=).tab.c $(<:.y=.c)
mv $(<:.y=).tab.h $(<:.y=.h)
# Create a dependency chain in generated files
# to avoid concurrent invocations of the single
# rule that builds them all.
aicasm_macro_gram.c: aicasm_macro_gram.h
aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y
$(YACC) $(YFLAGS) -b $(<:.y=) -p mm $<
mv $(<:.y=).tab.c $(<:.y=.c)
mv $(<:.y=).tab.h $(<:.y=.h)
aicasm_scan.c: aicasm_scan.l
$(LEX) $(LFLAGS) -o$@ $<
aicasm_macro_scan.c: aicasm_macro_scan.l
$(LEX) $(LFLAGS) -Pmm -o$@ $<

View File

@@ -0,0 +1,844 @@
/*
* Aic7xxx SCSI host adapter firmware asssembler
*
* Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
* Copyright (c) 2001, 2002 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <ctype.h>
#include <inttypes.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#if linux
#include <endian.h>
#else
#include <machine/endian.h>
#endif
#include "aicasm.h"
#include "aicasm_symbol.h"
#include "aicasm_insformat.h"
typedef struct patch {
STAILQ_ENTRY(patch) links;
int patch_func;
u_int begin;
u_int skip_instr;
u_int skip_patch;
} patch_t;
STAILQ_HEAD(patch_list, patch) patches;
static void usage(void);
static void back_patch(void);
static void output_code(void);
static void output_listing(char *ifilename);
static void dump_scope(scope_t *scope);
static void emit_patch(scope_t *scope, int patch);
static int check_patch(patch_t **start_patch, int start_instr,
int *skip_addr, int *func_vals);
struct path_list search_path;
int includes_search_curdir;
char *appname;
char *stock_include_file;
FILE *ofile;
char *ofilename;
char *regfilename;
FILE *regfile;
char *listfilename;
FILE *listfile;
char *regdiagfilename;
FILE *regdiagfile;
int src_mode;
int dst_mode;
static STAILQ_HEAD(,instruction) seq_program;
struct cs_tailq cs_tailq;
struct scope_list scope_stack;
symlist_t patch_functions;
#if DEBUG
extern int yy_flex_debug;
extern int mm_flex_debug;
extern int yydebug;
extern int mmdebug;
#endif
extern FILE *yyin;
extern int yyparse(void);
int main(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
int ch;
int retval;
char *inputfilename;
scope_t *sentinal;
STAILQ_INIT(&patches);
SLIST_INIT(&search_path);
STAILQ_INIT(&seq_program);
TAILQ_INIT(&cs_tailq);
SLIST_INIT(&scope_stack);
/* Set Sentinal scope node */
sentinal = scope_alloc();
sentinal->type = SCOPE_ROOT;
includes_search_curdir = 1;
appname = *argv;
regfile = NULL;
listfile = NULL;
#if DEBUG
yy_flex_debug = 0;
mm_flex_debug = 0;
yydebug = 0;
mmdebug = 0;
#endif
while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:")) != -1) {
switch(ch) {
case 'd':
#if DEBUG
if (strcmp(optarg, "s") == 0) {
yy_flex_debug = 1;
mm_flex_debug = 1;
} else if (strcmp(optarg, "p") == 0) {
yydebug = 1;
mmdebug = 1;
} else {
fprintf(stderr, "%s: -d Requires either an "
"'s' or 'p' argument\n", appname);
usage();
}
#else
stop("-d: Assembler not built with debugging "
"information", EX_SOFTWARE);
#endif
break;
case 'i':
stock_include_file = optarg;
break;
case 'l':
/* Create a program listing */
if ((listfile = fopen(optarg, "w")) == NULL) {
perror(optarg);
stop(NULL, EX_CANTCREAT);
}
listfilename = optarg;
break;
case 'n':
/* Don't complain about the -nostdinc directrive */
if (strcmp(optarg, "ostdinc")) {
fprintf(stderr, "%s: Unknown option -%c%s\n",
appname, ch, optarg);
usage();
/* NOTREACHED */
}
break;
case 'o':
if ((ofile = fopen(optarg, "w")) == NULL) {
perror(optarg);
stop(NULL, EX_CANTCREAT);
}
ofilename = optarg;
break;
case 'p':
/* Create Register Diagnostic "printing" Functions */
if ((regdiagfile = fopen(optarg, "w")) == NULL) {
perror(optarg);
stop(NULL, EX_CANTCREAT);
}
regdiagfilename = optarg;
break;
case 'r':
if ((regfile = fopen(optarg, "w")) == NULL) {
perror(optarg);
stop(NULL, EX_CANTCREAT);
}
regfilename = optarg;
break;
case 'I':
{
path_entry_t include_dir;
if (strcmp(optarg, "-") == 0) {
if (includes_search_curdir == 0) {
fprintf(stderr, "%s: Warning - '-I-' "
"specified multiple "
"times\n", appname);
}
includes_search_curdir = 0;
for (include_dir = SLIST_FIRST(&search_path);
include_dir != NULL;
include_dir = SLIST_NEXT(include_dir,
links))
/*
* All entries before a '-I-' only
* apply to includes specified with
* quotes instead of "<>".
*/
include_dir->quoted_includes_only = 1;
} else {
include_dir =
(path_entry_t)malloc(sizeof(*include_dir));
if (include_dir == NULL) {
perror(optarg);
stop(NULL, EX_OSERR);
}
include_dir->directory = strdup(optarg);
if (include_dir->directory == NULL) {
perror(optarg);
stop(NULL, EX_OSERR);
}
include_dir->quoted_includes_only = 0;
SLIST_INSERT_HEAD(&search_path, include_dir,
links);
}
break;
}
case '?':
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (argc != 1) {
fprintf(stderr, "%s: No input file specifiled\n", appname);
usage();
/* NOTREACHED */
}
if (regdiagfile != NULL
&& (regfile == NULL || stock_include_file == NULL)) {
fprintf(stderr,
"%s: The -p option requires the -r and -i options.\n",
appname);
usage();
/* NOTREACHED */
}
symtable_open();
inputfilename = *argv;
include_file(*argv, SOURCE_FILE);
retval = yyparse();
if (retval == 0) {
if (SLIST_FIRST(&scope_stack) == NULL
|| SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
stop("Unterminated conditional expression", EX_DATAERR);
/* NOTREACHED */
}
/* Process outmost scope */
process_scope(SLIST_FIRST(&scope_stack));
/*
* Decend the tree of scopes and insert/emit
* patches as appropriate. We perform a depth first
* tranversal, recursively handling each scope.
*/
/* start at the root scope */
dump_scope(SLIST_FIRST(&scope_stack));
/* Patch up forward jump addresses */
back_patch();
if (ofile != NULL)
output_code();
if (regfile != NULL)
symtable_dump(regfile, regdiagfile);
if (listfile != NULL)
output_listing(inputfilename);
}
stop(NULL, 0);
/* NOTREACHED */
return (0);
}
static void
usage()
{
(void)fprintf(stderr,
"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]\n"
" [-r register_output_file [-p register_diag_file -i includefile]]\n"
" [-l program_list_file]\n"
" input_file\n", appname);
exit(EX_USAGE);
}
static void
back_patch()
{
struct instruction *cur_instr;
for (cur_instr = STAILQ_FIRST(&seq_program);
cur_instr != NULL;
cur_instr = STAILQ_NEXT(cur_instr, links)) {
if (cur_instr->patch_label != NULL) {
struct ins_format3 *f3_instr;
u_int address;
if (cur_instr->patch_label->type != LABEL) {
char buf[255];
snprintf(buf, sizeof(buf),
"Undefined label %s",
cur_instr->patch_label->name);
stop(buf, EX_DATAERR);
/* NOTREACHED */
}
f3_instr = &cur_instr->format.format3;
address = f3_instr->address;
address += cur_instr->patch_label->info.linfo->address;
f3_instr->address = address;
}
}
}
static void
output_code()
{
struct instruction *cur_instr;
patch_t *cur_patch;
critical_section_t *cs;
symbol_node_t *cur_node;
int instrcount;
instrcount = 0;
fprintf(ofile,
"/*\n"
" * DO NOT EDIT - This file is automatically generated\n"
" * from the following source files:\n"
" *\n"
"%s */\n", versions);
fprintf(ofile, "static const uint8_t seqprog[] = {\n");
for (cur_instr = STAILQ_FIRST(&seq_program);
cur_instr != NULL;
cur_instr = STAILQ_NEXT(cur_instr, links)) {
fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
#ifdef __LITTLE_ENDIAN
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
cur_instr->format.bytes[2],
cur_instr->format.bytes[3]);
#else
cur_instr->format.bytes[3],
cur_instr->format.bytes[2],
cur_instr->format.bytes[1],
cur_instr->format.bytes[0]);
#endif
instrcount++;
}
fprintf(ofile, "\n};\n\n");
if (patch_arg_list == NULL)
stop("Patch argument list not defined",
EX_DATAERR);
/*
* Output patch information. Patch functions first.
*/
fprintf(ofile,
"typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
for (cur_node = SLIST_FIRST(&patch_functions);
cur_node != NULL;
cur_node = SLIST_NEXT(cur_node,links)) {
fprintf(ofile,
"static %spatch_func_t %spatch%d_func;\n"
"\n"
"static int\n"
"%spatch%d_func(%s)\n"
"{\n"
" return (%s);\n"
"}\n\n",
prefix,
prefix,
cur_node->symbol->info.condinfo->func_num,
prefix,
cur_node->symbol->info.condinfo->func_num,
patch_arg_list,
cur_node->symbol->name);
}
fprintf(ofile,
"static const struct patch {\n"
" %spatch_func_t *patch_func;\n"
" uint32_t begin :10,\n"
" skip_instr :10,\n"
" skip_patch :12;\n"
"} patches[] = {\n", prefix);
for (cur_patch = STAILQ_FIRST(&patches);
cur_patch != NULL;
cur_patch = STAILQ_NEXT(cur_patch,links)) {
fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
prefix,
cur_patch->patch_func, cur_patch->begin,
cur_patch->skip_instr, cur_patch->skip_patch);
}
fprintf(ofile, "\n};\n\n");
fprintf(ofile,
"static const struct cs {\n"
" uint16_t begin;\n"
" uint16_t end;\n"
"} critical_sections[] = {\n");
for (cs = TAILQ_FIRST(&cs_tailq);
cs != NULL;
cs = TAILQ_NEXT(cs, links)) {
fprintf(ofile, "%s\t{ %d, %d }",
cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
cs->begin_addr, cs->end_addr);
}
fprintf(ofile, "\n};\n\n");
fprintf(ofile,
"static const int num_critical_sections = sizeof(critical_sections)\n"
" / sizeof(*critical_sections);\n");
fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
}
static void
dump_scope(scope_t *scope)
{
scope_t *cur_scope;
/*
* Emit the first patch for this scope
*/
emit_patch(scope, 0);
/*
* Dump each scope within this one.
*/
cur_scope = TAILQ_FIRST(&scope->inner_scope);
while (cur_scope != NULL) {
dump_scope(cur_scope);
cur_scope = TAILQ_NEXT(cur_scope, scope_links);
}
/*
* Emit the second, closing, patch for this scope
*/
emit_patch(scope, 1);
}
void
emit_patch(scope_t *scope, int patch)
{
patch_info_t *pinfo;
patch_t *new_patch;
pinfo = &scope->patches[patch];
if (pinfo->skip_instr == 0)
/* No-Op patch */
return;
new_patch = (patch_t *)malloc(sizeof(*new_patch));
if (new_patch == NULL)
stop("Could not malloc patch structure", EX_OSERR);
memset(new_patch, 0, sizeof(*new_patch));
if (patch == 0) {
new_patch->patch_func = scope->func_num;
new_patch->begin = scope->begin_addr;
} else {
new_patch->patch_func = 0;
new_patch->begin = scope->end_addr;
}
new_patch->skip_instr = pinfo->skip_instr;
new_patch->skip_patch = pinfo->skip_patch;
STAILQ_INSERT_TAIL(&patches, new_patch, links);
}
void
output_listing(char *ifilename)
{
char buf[1024];
FILE *ifile;
struct instruction *cur_instr;
patch_t *cur_patch;
symbol_node_t *cur_func;
int *func_values;
int instrcount;
int instrptr;
int line;
int func_count;
int skip_addr;
instrcount = 0;
instrptr = 0;
line = 1;
skip_addr = 0;
if ((ifile = fopen(ifilename, "r")) == NULL) {
perror(ifilename);
stop(NULL, EX_DATAERR);
}
/*
* Determine which options to apply to this listing.
*/
for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
cur_func != NULL;
cur_func = SLIST_NEXT(cur_func, links))
func_count++;
func_values = NULL;
if (func_count != 0) {
func_values = (int *)malloc(func_count * sizeof(int));
if (func_values == NULL)
stop("Could not malloc", EX_OSERR);
func_values[0] = 0; /* FALSE func */
func_count--;
/*
* Ask the user to fill in the return values for
* the rest of the functions.
*/
for (cur_func = SLIST_FIRST(&patch_functions);
cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
cur_func = SLIST_NEXT(cur_func, links), func_count--) {
int input;
fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
fprintf(stdout,
"Enter the return value for "
"this expression[T/F]:");
while (1) {
input = getchar();
input = toupper(input);
if (input == 'T') {
func_values[func_count] = 1;
break;
} else if (input == 'F') {
func_values[func_count] = 0;
break;
}
}
if (isatty(fileno(stdin)) == 0)
putchar(input);
}
fprintf(stdout, "\nThanks!\n");
}
/* Now output the listing */
cur_patch = STAILQ_FIRST(&patches);
for (cur_instr = STAILQ_FIRST(&seq_program);
cur_instr != NULL;
cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
if (check_patch(&cur_patch, instrcount,
&skip_addr, func_values) == 0) {
/* Don't count this instruction as it is in a patch
* that was removed.
*/
continue;
}
while (line < cur_instr->srcline) {
fgets(buf, sizeof(buf), ifile);
fprintf(listfile, " \t%s", buf);
line++;
}
fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
#ifdef __LITTLE_ENDIAN
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
cur_instr->format.bytes[2],
cur_instr->format.bytes[3]);
#else
cur_instr->format.bytes[3],
cur_instr->format.bytes[2],
cur_instr->format.bytes[1],
cur_instr->format.bytes[0]);
#endif
/*
* Macro expansions can cause several instructions
* to be output for a single source line. Only
* advance the line once in these cases.
*/
if (line == cur_instr->srcline) {
fgets(buf, sizeof(buf), ifile);
fprintf(listfile, "\t%s", buf);
line++;
} else {
fprintf(listfile, "\n");
}
instrptr++;
}
/* Dump the remainder of the file */
while(fgets(buf, sizeof(buf), ifile) != NULL)
fprintf(listfile, " %s", buf);
fclose(ifile);
}
static int
check_patch(patch_t **start_patch, int start_instr,
int *skip_addr, int *func_vals)
{
patch_t *cur_patch;
cur_patch = *start_patch;
while (cur_patch != NULL && start_instr == cur_patch->begin) {
if (func_vals[cur_patch->patch_func] == 0) {
int skip;
/* Start rejecting code */
*skip_addr = start_instr + cur_patch->skip_instr;
for (skip = cur_patch->skip_patch;
skip > 0 && cur_patch != NULL;
skip--)
cur_patch = STAILQ_NEXT(cur_patch, links);
} else {
/* Accepted this patch. Advance to the next
* one and wait for our intruction pointer to
* hit this point.
*/
cur_patch = STAILQ_NEXT(cur_patch, links);
}
}
*start_patch = cur_patch;
if (start_instr < *skip_addr)
/* Still skipping */
return (0);
return (1);
}
/*
* Print out error information if appropriate, and clean up before
* terminating the program.
*/
void
stop(const char *string, int err_code)
{
if (string != NULL) {
fprintf(stderr, "%s: ", appname);
if (yyfilename != NULL) {
fprintf(stderr, "Stopped at file %s, line %d - ",
yyfilename, yylineno);
}
fprintf(stderr, "%s\n", string);
}
if (ofile != NULL) {
fclose(ofile);
if (err_code != 0) {
fprintf(stderr, "%s: Removing %s due to error\n",
appname, ofilename);
unlink(ofilename);
}
}
if (regfile != NULL) {
fclose(regfile);
if (err_code != 0) {
fprintf(stderr, "%s: Removing %s due to error\n",
appname, regfilename);
unlink(regfilename);
}
}
if (listfile != NULL) {
fclose(listfile);
if (err_code != 0) {
fprintf(stderr, "%s: Removing %s due to error\n",
appname, listfilename);
unlink(listfilename);
}
}
symlist_free(&patch_functions);
symtable_close();
exit(err_code);
}
struct instruction *
seq_alloc()
{
struct instruction *new_instr;
new_instr = (struct instruction *)malloc(sizeof(struct instruction));
if (new_instr == NULL)
stop("Unable to malloc instruction object", EX_SOFTWARE);
memset(new_instr, 0, sizeof(*new_instr));
STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
new_instr->srcline = yylineno;
return new_instr;
}
critical_section_t *
cs_alloc()
{
critical_section_t *new_cs;
new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
if (new_cs == NULL)
stop("Unable to malloc critical_section object", EX_SOFTWARE);
memset(new_cs, 0, sizeof(*new_cs));
TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
return new_cs;
}
scope_t *
scope_alloc()
{
scope_t *new_scope;
new_scope = (scope_t *)malloc(sizeof(scope_t));
if (new_scope == NULL)
stop("Unable to malloc scope object", EX_SOFTWARE);
memset(new_scope, 0, sizeof(*new_scope));
TAILQ_INIT(&new_scope->inner_scope);
if (SLIST_FIRST(&scope_stack) != NULL) {
TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
new_scope, scope_links);
}
/* This patch is now the current scope */
SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
return new_scope;
}
void
process_scope(scope_t *scope)
{
/*
* We are "leaving" this scope. We should now have
* enough information to process the lists of scopes
* we encapsulate.
*/
scope_t *cur_scope;
u_int skip_patch_count;
u_int skip_instr_count;
cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
skip_patch_count = 0;
skip_instr_count = 0;
while (cur_scope != NULL) {
u_int patch0_patch_skip;
patch0_patch_skip = 0;
switch (cur_scope->type) {
case SCOPE_IF:
case SCOPE_ELSE_IF:
if (skip_instr_count != 0) {
/* Create a tail patch */
patch0_patch_skip++;
cur_scope->patches[1].skip_patch =
skip_patch_count + 1;
cur_scope->patches[1].skip_instr =
skip_instr_count;
}
/* Count Head patch */
patch0_patch_skip++;
/* Count any patches contained in our inner scope */
patch0_patch_skip += cur_scope->inner_scope_patches;
cur_scope->patches[0].skip_patch = patch0_patch_skip;
cur_scope->patches[0].skip_instr =
cur_scope->end_addr - cur_scope->begin_addr;
skip_instr_count += cur_scope->patches[0].skip_instr;
skip_patch_count += patch0_patch_skip;
if (cur_scope->type == SCOPE_IF) {
scope->inner_scope_patches += skip_patch_count;
skip_patch_count = 0;
skip_instr_count = 0;
}
break;
case SCOPE_ELSE:
/* Count any patches contained in our innter scope */
skip_patch_count += cur_scope->inner_scope_patches;
skip_instr_count += cur_scope->end_addr
- cur_scope->begin_addr;
break;
case SCOPE_ROOT:
stop("Unexpected scope type encountered", EX_SOFTWARE);
/* NOTREACHED */
}
cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Assembler for the sequencer program downloaded to Aic7xxx SCSI host adapters
*
* Copyright (c) 1997 Justin T. Gibbs.
* Copyright (c) 2001, 2002 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.h#14 $
*
* $FreeBSD$
*/
#ifdef __linux__
#include "../queue.h"
#else
#include <sys/queue.h>
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef struct path_entry {
char *directory;
int quoted_includes_only;
SLIST_ENTRY(path_entry) links;
} *path_entry_t;
typedef enum {
QUOTED_INCLUDE,
BRACKETED_INCLUDE,
SOURCE_FILE
} include_type;
SLIST_HEAD(path_list, path_entry);
extern struct path_list search_path;
extern struct cs_tailq cs_tailq;
extern struct scope_list scope_stack;
extern struct symlist patch_functions;
extern int includes_search_curdir; /* False if we've seen -I- */
extern char *appname;
extern char *stock_include_file;
extern int yylineno;
extern char *yyfilename;
extern char *prefix;
extern char *patch_arg_list;
extern char *versions;
extern int src_mode;
extern int dst_mode;
struct symbol;
void stop(const char *errstring, int err_code);
void include_file(char *file_name, include_type type);
void expand_macro(struct symbol *macro_symbol);
struct instruction *seq_alloc(void);
struct critical_section *cs_alloc(void);
struct scope *scope_alloc(void);
void process_scope(struct scope *);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,219 @@
/*
* Instruction formats for the sequencer program downloaded to
* Aic7xxx SCSI host adapters
*
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $
*
* $FreeBSD$
*/
#include <asm/byteorder.h>
/* 8bit ALU logic operations */
struct ins_format1 {
#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
source : 9,
destination : 9,
ret : 1,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
ret : 1,
destination : 9,
source : 9,
immediate : 8;
#endif
};
/* 8bit ALU shift/rotate operations */
struct ins_format2 {
#ifdef __LITTLE_ENDIAN
uint32_t shift_control : 8,
source : 9,
destination : 9,
ret : 1,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
ret : 1,
destination : 9,
source : 9,
shift_control : 8;
#endif
};
/* 8bit branch control operations */
struct ins_format3 {
#ifdef __LITTLE_ENDIAN
uint32_t immediate : 8,
source : 9,
address : 10,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
address : 10,
source : 9,
immediate : 8;
#endif
};
/* 16bit ALU logic operations */
struct ins_format4 {
#ifdef __LITTLE_ENDIAN
uint32_t opcode_ext : 8,
source : 9,
destination : 9,
ret : 1,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
ret : 1,
destination : 9,
source : 9,
opcode_ext : 8;
#endif
};
/* 16bit branch control operations */
struct ins_format5 {
#ifdef __LITTLE_ENDIAN
uint32_t opcode_ext : 8,
source : 9,
address : 10,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
address : 10,
source : 9,
opcode_ext : 8;
#endif
};
/* Far branch operations */
struct ins_format6 {
#ifdef __LITTLE_ENDIAN
uint32_t page : 3,
opcode_ext : 5,
source : 9,
address : 10,
opcode : 4,
parity : 1;
#else
uint32_t parity : 1,
opcode : 4,
address : 10,
source : 9,
opcode_ext : 5,
page : 3;
#endif
};
union ins_formats {
struct ins_format1 format1;
struct ins_format2 format2;
struct ins_format3 format3;
struct ins_format4 format4;
struct ins_format5 format5;
struct ins_format6 format6;
uint8_t bytes[4];
uint32_t integer;
};
struct instruction {
union ins_formats format;
u_int srcline;
struct symbol *patch_label;
STAILQ_ENTRY(instruction) links;
};
#define AIC_OP_OR 0x0
#define AIC_OP_AND 0x1
#define AIC_OP_XOR 0x2
#define AIC_OP_ADD 0x3
#define AIC_OP_ADC 0x4
#define AIC_OP_ROL 0x5
#define AIC_OP_BMOV 0x6
#define AIC_OP_MVI16 0x7
#define AIC_OP_JMP 0x8
#define AIC_OP_JC 0x9
#define AIC_OP_JNC 0xa
#define AIC_OP_CALL 0xb
#define AIC_OP_JNE 0xc
#define AIC_OP_JNZ 0xd
#define AIC_OP_JE 0xe
#define AIC_OP_JZ 0xf
/* Pseudo Ops */
#define AIC_OP_SHL 0x10
#define AIC_OP_SHR 0x20
#define AIC_OP_ROR 0x30
/* 16bit Ops. Low byte main opcode. High byte extended opcode. */
#define AIC_OP_OR16 0x8005
#define AIC_OP_AND16 0x8105
#define AIC_OP_XOR16 0x8205
#define AIC_OP_ADD16 0x8305
#define AIC_OP_ADC16 0x8405
#define AIC_OP_JNE16 0x8805
#define AIC_OP_JNZ16 0x8905
#define AIC_OP_JE16 0x8C05
#define AIC_OP_JZ16 0x8B05
#define AIC_OP_JMP16 0x9005
#define AIC_OP_JC16 0x9105
#define AIC_OP_JNC16 0x9205
#define AIC_OP_CALL16 0x9305
#define AIC_OP_CALL16 0x9305
/* Page extension is low three bits of second opcode byte. */
#define AIC_OP_JMPF 0xA005
#define AIC_OP_CALLF 0xB005
#define AIC_OP_JCF 0xC005
#define AIC_OP_JNCF 0xD005
#define AIC_OP_CMPXCHG 0xE005

View File

@@ -0,0 +1,165 @@
%{
/*
* Sub-parser for macro invocation in the Aic7xxx SCSI
* Host adapter sequencer assembler.
*
* Copyright (c) 2001 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_gram.y#5 $
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <inttypes.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#ifdef __linux__
#include "../queue.h"
#else
#include <sys/queue.h>
#endif
#include "aicasm.h"
#include "aicasm_symbol.h"
#include "aicasm_insformat.h"
static symbol_t *macro_symbol;
static void add_macro_arg(const char *argtext, int position);
void mmerror(const char *string);
%}
%union {
int value;
char *str;
symbol_t *sym;
}
%token <str> T_ARG
%token <sym> T_SYMBOL
%type <value> macro_arglist
%%
macrocall:
T_SYMBOL '('
{
macro_symbol = $1;
}
macro_arglist ')'
{
if (macro_symbol->info.macroinfo->narg != $4) {
printf("Narg == %d", macro_symbol->info.macroinfo->narg);
stop("Too few arguments for macro invocation",
EX_DATAERR);
/* NOTREACHED */
}
macro_symbol = NULL;
YYACCEPT;
}
;
macro_arglist:
{
/* Macros can take 0 arguments */
$$ = 0;
}
| T_ARG
{
$$ = 1;
add_macro_arg($1, 1);
}
| macro_arglist ',' T_ARG
{
if ($1 == 0) {
stop("Comma without preceeding argument in arg list",
EX_DATAERR);
/* NOTREACHED */
}
$$ = $1 + 1;
add_macro_arg($3, $$);
}
;
%%
static void
add_macro_arg(const char *argtext, int argnum)
{
struct macro_arg *marg;
int i;
if (macro_symbol == NULL || macro_symbol->type != MACRO) {
stop("Invalid current symbol for adding macro arg",
EX_SOFTWARE);
/* NOTREACHED */
}
/*
* Macro Invocation. Find the appropriate argument and fill
* in the replace ment text for this call.
*/
i = 0;
STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
i++;
if (i == argnum)
break;
}
if (marg == NULL) {
stop("Too many arguments for macro invocation", EX_DATAERR);
/* NOTREACHED */
}
marg->replacement_text = strdup(argtext);
if (marg->replacement_text == NULL) {
stop("Unable to replicate replacement text", EX_SOFTWARE);
/* NOTREACHED */
}
}
void
mmerror(const char *string)
{
stop(string, EX_DATAERR);
}

View File

@@ -0,0 +1,157 @@
%{
/*
* Sub-Lexical Analyzer for macro invokation in
* the Aic7xxx SCSI Host adapter sequencer assembler.
*
* Copyright (c) 2001 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#8 $
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <inttypes.h>
#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#ifdef __linux__
#include "../queue.h"
#else
#include <sys/queue.h>
#endif
#include "aicasm.h"
#include "aicasm_symbol.h"
#include "aicasm_macro_gram.h"
#define MAX_STR_CONST 4096
static char string_buf[MAX_STR_CONST];
static char *string_buf_ptr;
static int parren_count;
static char buf[255];
int mmlineno;
%}
WORD [A-Za-z_][-A-Za-z_0-9]*
SPACE [ \t]+
MCARG [^(), \t]+
%x ARGLIST
%%
\n {
++mmlineno;
}
\r ;
<ARGLIST>{SPACE} ;
<ARGLIST>\( {
parren_count++;
if (parren_count == 1) {
string_buf_ptr = string_buf;
return ('(');
}
*string_buf_ptr++ = '(';
}
<ARGLIST>\) {
if (parren_count == 1) {
if (string_buf_ptr != string_buf) {
/*
* Return an argument and
* rescan this parren so we
* can return it as well.
*/
*string_buf_ptr = '\0';
mmlval.str = string_buf;
string_buf_ptr = string_buf;
unput(')');
return T_ARG;
}
BEGIN INITIAL;
return (')');
}
parren_count--;
*string_buf_ptr++ = ')';
}
<ARGLIST>{MCARG} {
char *yptr;
yptr = mmtext;
while (*yptr)
*string_buf_ptr++ = *yptr++;
}
<ARGLIST>\, {
if (string_buf_ptr != string_buf) {
/*
* Return an argument and
* rescan this comma so we
* can return it as well.
*/
*string_buf_ptr = '\0';
mmlval.str = string_buf;
string_buf_ptr = string_buf;
unput(',');
return T_ARG;
}
return ',';
}
{WORD}[(] {
/* May be a symbol or a macro invocation. */
mmlval.sym = symtable_get(mmtext);
if (mmlval.sym->type != MACRO) {
stop("Expecting Macro Name",
EX_DATAERR);
}
unput('(');
parren_count = 0;
BEGIN ARGLIST;
return T_SYMBOL;
}
. {
snprintf(buf, sizeof(buf), "Invalid character "
"'%c'", mmtext[0]);
stop(buf, EX_DATAERR);
}
%%
int
mmwrap()
{
stop("EOF encountered in macro call", EX_DATAERR);
}

View File

@@ -0,0 +1,622 @@
%{
/*
* Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
*
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
* Copyright (c) 2001, 2002 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <inttypes.h>
#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#ifdef __linux__
#include "../queue.h"
#else
#include <sys/queue.h>
#endif
#include "aicasm.h"
#include "aicasm_symbol.h"
#include "aicasm_gram.h"
/* This is used for macro body capture too, so err on the large size. */
#define MAX_STR_CONST 4096
static char string_buf[MAX_STR_CONST];
static char *string_buf_ptr;
static int parren_count;
static int quote_count;
static char buf[255];
%}
PATH ([/]*[-A-Za-z0-9_.])+
WORD [A-Za-z_][-A-Za-z_0-9]*
SPACE [ \t]+
MCARG [^(), \t]+
MBODY ((\\[^\n])*[^\n\\]*)+
%x COMMENT
%x CEXPR
%x INCLUDE
%x STRING
%x MACRODEF
%x MACROARGLIST
%x MACROCALLARGS
%x MACROBODY
%%
\n { ++yylineno; }
\r ;
"/*" { BEGIN COMMENT; /* Enter comment eating state */ }
<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); }
<COMMENT>\n { ++yylineno; }
<COMMENT>[^*/\n]* ;
<COMMENT>"*"+[^*/\n]* ;
<COMMENT>"/"+[^*/\n]* ;
<COMMENT>"*"+"/" { BEGIN INITIAL; }
if[ \t]*\( {
string_buf_ptr = string_buf;
parren_count = 1;
BEGIN CEXPR;
return T_IF;
}
<CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; }
<CEXPR>\) {
parren_count--;
if (parren_count == 0) {
/* All done */
BEGIN INITIAL;
*string_buf_ptr = '\0';
yylval.sym = symtable_get(string_buf);
return T_CEXPR;
} else {
*string_buf_ptr++ = ')';
}
}
<CEXPR>\n { ++yylineno; }
<CEXPR>\r ;
<CEXPR>[^()\n]+ {
char *yptr;
yptr = yytext;
while (*yptr != '\0') {
/* Remove duplicate spaces */
if (*yptr == '\t')
*yptr = ' ';
if (*yptr == ' '
&& string_buf_ptr != string_buf
&& string_buf_ptr[-1] == ' ')
yptr++;
else
*string_buf_ptr++ = *yptr++;
}
}
else { return T_ELSE; }
VERSION { return T_VERSION; }
PREFIX { return T_PREFIX; }
PATCH_ARG_LIST { return T_PATCH_ARG_LIST; }
\" {
string_buf_ptr = string_buf;
BEGIN STRING;
}
<STRING>[^"]+ {
char *yptr;
yptr = yytext;
while (*yptr)
*string_buf_ptr++ = *yptr++;
}
<STRING>\" {
/* All done */
BEGIN INITIAL;
*string_buf_ptr = '\0';
yylval.str = string_buf;
return T_STRING;
}
{SPACE} ;
/* Register/SCB/SRAM definition keywords */
export { return T_EXPORT; }
register { return T_REGISTER; }
const { yylval.value = FALSE; return T_CONST; }
download { return T_DOWNLOAD; }
address { return T_ADDRESS; }
count { return T_COUNT; }
access_mode { return T_ACCESS_MODE; }
dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
modes { return T_MODES; }
RW|RO|WO {
if (strcmp(yytext, "RW") == 0)
yylval.value = RW;
else if (strcmp(yytext, "RO") == 0)
yylval.value = RO;
else
yylval.value = WO;
return T_MODE;
}
field { return T_FIELD; }
enum { return T_ENUM; }
mask { return T_MASK; }
alias { return T_ALIAS; }
size { return T_SIZE; }
scb { return T_SCB; }
scratch_ram { return T_SRAM; }
accumulator { return T_ACCUM; }
mode_pointer { return T_MODE_PTR; }
allones { return T_ALLONES; }
allzeros { return T_ALLZEROS; }
none { return T_NONE; }
sindex { return T_SINDEX; }
A { return T_A; }
/* Instruction Formatting */
PAD_PAGE { return T_PAD_PAGE; }
BEGIN_CRITICAL { return T_BEGIN_CS; }
END_CRITICAL { return T_END_CS; }
SET_SRC_MODE { return T_SET_SRC_MODE; }
SET_DST_MODE { return T_SET_DST_MODE; }
/* Opcodes */
shl { return T_SHL; }
shr { return T_SHR; }
ror { return T_ROR; }
rol { return T_ROL; }
mvi { return T_MVI; }
mov { return T_MOV; }
clr { return T_CLR; }
jmp { return T_JMP; }
jc { return T_JC; }
jnc { return T_JNC; }
je { return T_JE; }
jne { return T_JNE; }
jz { return T_JZ; }
jnz { return T_JNZ; }
call { return T_CALL; }
add { return T_ADD; }
adc { return T_ADC; }
bmov { return T_BMOV; }
inc { return T_INC; }
dec { return T_DEC; }
stc { return T_STC; }
clc { return T_CLC; }
cmp { return T_CMP; }
not { return T_NOT; }
xor { return T_XOR; }
test { return T_TEST;}
and { return T_AND; }
or { return T_OR; }
ret { return T_RET; }
nop { return T_NOP; }
/* ARP2 16bit extensions */
/* or16 { return T_OR16; } */
/* and16 { return T_AND16; }*/
/* xor16 { return T_XOR16; }*/
/* add16 { return T_ADD16; }*/
/* adc16 { return T_ADC16; }*/
/* mvi16 { return T_MVI16; }*/
/* test16 { return T_TEST16; }*/
/* cmp16 { return T_CMP16; }*/
/* cmpxchg { return T_CMPXCHG; }*/
/* Allowed Symbols */
\<\< { return T_EXPR_LSHIFT; }
\>\> { return T_EXPR_RSHIFT; }
[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
/* Number processing */
0[0-7]* {
yylval.value = strtol(yytext, NULL, 8);
return T_NUMBER;
}
0[xX][0-9a-fA-F]+ {
yylval.value = strtoul(yytext + 2, NULL, 16);
return T_NUMBER;
}
[1-9][0-9]* {
yylval.value = strtol(yytext, NULL, 10);
return T_NUMBER;
}
/* Include Files */
#include{SPACE} {
BEGIN INCLUDE;
quote_count = 0;
return T_INCLUDE;
}
<INCLUDE>[<] { return yytext[0]; }
<INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; }
<INCLUDE>[\"] {
if (quote_count != 0)
BEGIN INITIAL;
quote_count++;
return yytext[0];
}
<INCLUDE>{PATH} {
char *yptr;
yptr = yytext;
string_buf_ptr = string_buf;
while (*yptr)
*string_buf_ptr++ = *yptr++;
yylval.str = string_buf;
*string_buf_ptr = '\0';
return T_PATH;
}
<INCLUDE>. { stop("Invalid include line", EX_DATAERR); }
#define{SPACE} {
BEGIN MACRODEF;
return T_DEFINE;
}
<MACRODEF>{WORD}{SPACE} {
char *yptr;
/* Strip space and return as a normal symbol */
yptr = yytext;
while (*yptr != ' ' && *yptr != '\t')
yptr++;
*yptr = '\0';
yylval.sym = symtable_get(yytext);
string_buf_ptr = string_buf;
BEGIN MACROBODY;
return T_SYMBOL;
}
<MACRODEF>{WORD}\( {
/*
* We store the symbol with its opening
* parren so we can differentiate macros
* that take args from macros with the
* same name that do not take args as
* is allowed in C.
*/
BEGIN MACROARGLIST;
yylval.sym = symtable_get(yytext);
unput('(');
return T_SYMBOL;
}
<MACROARGLIST>{WORD} {
yylval.str = yytext;
return T_ARG;
}
<MACROARGLIST>{SPACE} ;
<MACROARGLIST>[(,] {
return yytext[0];
}
<MACROARGLIST>[)] {
string_buf_ptr = string_buf;
BEGIN MACROBODY;
return ')';
}
<MACROARGLIST>. {
snprintf(buf, sizeof(buf), "Invalid character "
"'%c' in macro argument list",
yytext[0]);
stop(buf, EX_DATAERR);
}
<MACROCALLARGS>{SPACE} ;
<MACROCALLARGS>\( {
parren_count++;
if (parren_count == 1)
return ('(');
*string_buf_ptr++ = '(';
}
<MACROCALLARGS>\) {
parren_count--;
if (parren_count == 0) {
BEGIN INITIAL;
return (')');
}
*string_buf_ptr++ = ')';
}
<MACROCALLARGS>{MCARG} {
char *yptr;
yptr = yytext;
while (*yptr)
*string_buf_ptr++ = *yptr++;
}
<MACROCALLARGS>\, {
if (string_buf_ptr != string_buf) {
/*
* Return an argument and
* rescan this comma so we
* can return it as well.
*/
*string_buf_ptr = '\0';
yylval.str = string_buf;
string_buf_ptr = string_buf;
unput(',');
return T_ARG;
}
return ',';
}
<MACROBODY>\\\n {
/* Eat escaped newlines. */
++yylineno;
}
<MACROBODY>\r ;
<MACROBODY>\n {
/* Macros end on the first unescaped newline. */
BEGIN INITIAL;
*string_buf_ptr = '\0';
yylval.str = string_buf;
++yylineno;
return T_MACROBODY;
}
<MACROBODY>{MBODY} {
char *yptr;
char c;
yptr = yytext;
while (c = *yptr++) {
/*
* Strip carriage returns.
*/
if (c == '\r')
continue;
*string_buf_ptr++ = c;
}
}
{WORD}\( {
char *yptr;
char *ycopy;
/* May be a symbol or a macro invocation. */
yylval.sym = symtable_get(yytext);
if (yylval.sym->type == MACRO) {
YY_BUFFER_STATE old_state;
YY_BUFFER_STATE temp_state;
ycopy = strdup(yytext);
yptr = ycopy + yyleng;
while (yptr > ycopy)
unput(*--yptr);
old_state = YY_CURRENT_BUFFER;
temp_state =
yy_create_buffer(stdin,
YY_BUF_SIZE);
yy_switch_to_buffer(temp_state);
mm_switch_to_buffer(old_state);
mmparse();
mm_switch_to_buffer(temp_state);
yy_switch_to_buffer(old_state);
mm_delete_buffer(temp_state);
expand_macro(yylval.sym);
} else {
if (yylval.sym->type == UNINITIALIZED) {
/* Try without the '(' */
symbol_delete(yylval.sym);
yytext[yyleng-1] = '\0';
yylval.sym =
symtable_get(yytext);
}
unput('(');
return T_SYMBOL;
}
}
{WORD} {
yylval.sym = symtable_get(yytext);
if (yylval.sym->type == MACRO) {
expand_macro(yylval.sym);
} else {
return T_SYMBOL;
}
}
. {
snprintf(buf, sizeof(buf), "Invalid character "
"'%c'", yytext[0]);
stop(buf, EX_DATAERR);
}
%%
typedef struct include {
YY_BUFFER_STATE buffer;
int lineno;
char *filename;
SLIST_ENTRY(include) links;
}include_t;
SLIST_HEAD(, include) include_stack;
void
include_file(char *file_name, include_type type)
{
FILE *newfile;
include_t *include;
newfile = NULL;
/* Try the current directory first */
if (includes_search_curdir != 0 || type == SOURCE_FILE)
newfile = fopen(file_name, "r");
if (newfile == NULL && type != SOURCE_FILE) {
path_entry_t include_dir;
for (include_dir = search_path.slh_first;
include_dir != NULL;
include_dir = include_dir->links.sle_next) {
char fullname[PATH_MAX];
if ((include_dir->quoted_includes_only == TRUE)
&& (type != QUOTED_INCLUDE))
continue;
snprintf(fullname, sizeof(fullname),
"%s/%s", include_dir->directory, file_name);
if ((newfile = fopen(fullname, "r")) != NULL)
break;
}
}
if (newfile == NULL) {
perror(file_name);
stop("Unable to open input file", EX_SOFTWARE);
/* NOTREACHED */
}
if (type != SOURCE_FILE) {
include = (include_t *)malloc(sizeof(include_t));
if (include == NULL) {
stop("Unable to allocate include stack entry",
EX_SOFTWARE);
/* NOTREACHED */
}
include->buffer = YY_CURRENT_BUFFER;
include->lineno = yylineno;
include->filename = yyfilename;
SLIST_INSERT_HEAD(&include_stack, include, links);
}
yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
yylineno = 1;
yyfilename = strdup(file_name);
}
static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
const char **next_match,
struct macro_arg **match_marg, regmatch_t *match);
void
expand_macro(struct symbol *macro_symbol)
{
struct macro_arg *marg;
struct macro_arg *match_marg;
const char *body_head;
const char *body_pos;
const char *next_match;
/*
* Due to the nature of unput, we must work
* backwards through the macro body performing
* any expansions.
*/
body_head = macro_symbol->info.macroinfo->body;
body_pos = body_head + strlen(body_head);
while (body_pos > body_head) {
regmatch_t match;
next_match = body_head;
match_marg = NULL;
next_substitution(macro_symbol, body_pos, &next_match,
&match_marg, &match);
/* Put back everything up until the replacement. */
while (body_pos > next_match)
unput(*--body_pos);
/* Perform the replacement. */
if (match_marg != NULL) {
const char *strp;
next_match = match_marg->replacement_text;
strp = next_match + strlen(next_match);
while (strp > next_match)
unput(*--strp);
/* Skip past the unexpanded macro arg. */
body_pos -= match.rm_eo - match.rm_so;
}
}
/* Cleanup replacement text. */
STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
free(marg->replacement_text);
}
}
/*
* Find the next substitution in the macro working backwards from
* body_pos until the beginning of the macro buffer. next_match
* should be initialized to the beginning of the macro buffer prior
* to calling this routine.
*/
static void
next_substitution(struct symbol *mac_symbol, const char *body_pos,
const char **next_match, struct macro_arg **match_marg,
regmatch_t *match)
{
regmatch_t matches[2];
struct macro_arg *marg;
const char *search_pos;
int retval;
do {
search_pos = *next_match;
STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
retval = regexec(&marg->arg_regex, search_pos, 2,
matches, 0);
if (retval == 0
&& (matches[1].rm_eo + search_pos) <= body_pos
&& (matches[1].rm_eo + search_pos) > *next_match) {
*match = matches[1];
*next_match = match->rm_eo + search_pos;
*match_marg = marg;
}
}
} while (search_pos != *next_match);
}
int
yywrap()
{
include_t *include;
yy_delete_buffer(YY_CURRENT_BUFFER);
(void)fclose(yyin);
if (yyfilename != NULL)
free(yyfilename);
yyfilename = NULL;
include = include_stack.slh_first;
if (include != NULL) {
yy_switch_to_buffer(include->buffer);
yylineno = include->lineno;
yyfilename = include->filename;
SLIST_REMOVE_HEAD(&include_stack, links);
free(include);
return (0);
}
return (1);
}

View File

@@ -0,0 +1,693 @@
/*
* Aic7xxx SCSI host adapter firmware asssembler symbol table implementation
*
* Copyright (c) 1997 Justin T. Gibbs.
* Copyright (c) 2002 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.c#24 $
*
* $FreeBSD$
*/
#include <sys/types.h>
#ifdef __linux__
#include "aicdb.h"
#else
#include <db.h>
#endif
#include <fcntl.h>
#include <inttypes.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include "aicasm_symbol.h"
#include "aicasm.h"
static DB *symtable;
symbol_t *
symbol_create(char *name)
{
symbol_t *new_symbol;
new_symbol = (symbol_t *)malloc(sizeof(symbol_t));
if (new_symbol == NULL) {
perror("Unable to create new symbol");
exit(EX_SOFTWARE);
}
memset(new_symbol, 0, sizeof(*new_symbol));
new_symbol->name = strdup(name);
if (new_symbol->name == NULL)
stop("Unable to strdup symbol name", EX_SOFTWARE);
new_symbol->type = UNINITIALIZED;
new_symbol->count = 1;
return (new_symbol);
}
void
symbol_delete(symbol_t *symbol)
{
if (symtable != NULL) {
DBT key;
key.data = symbol->name;
key.size = strlen(symbol->name);
symtable->del(symtable, &key, /*flags*/0);
}
switch(symbol->type) {
case SCBLOC:
case SRAMLOC:
case REGISTER:
if (symbol->info.rinfo != NULL)
free(symbol->info.rinfo);
break;
case ALIAS:
if (symbol->info.ainfo != NULL)
free(symbol->info.ainfo);
break;
case MASK:
case FIELD:
case ENUM:
case ENUM_ENTRY:
if (symbol->info.finfo != NULL) {
symlist_free(&symbol->info.finfo->symrefs);
free(symbol->info.finfo);
}
break;
case DOWNLOAD_CONST:
case CONST:
if (symbol->info.cinfo != NULL)
free(symbol->info.cinfo);
break;
case LABEL:
if (symbol->info.linfo != NULL)
free(symbol->info.linfo);
break;
case UNINITIALIZED:
default:
break;
}
free(symbol->name);
free(symbol);
}
void
symtable_open()
{
symtable = dbopen(/*filename*/NULL,
O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH,
/*openinfo*/NULL);
if (symtable == NULL) {
perror("Symbol table creation failed");
exit(EX_SOFTWARE);
/* NOTREACHED */
}
}
void
symtable_close()
{
if (symtable != NULL) {
DBT key;
DBT data;
while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
symbol_t *stored_ptr;
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
symbol_delete(stored_ptr);
}
symtable->close(symtable);
}
}
/*
* The semantics of get is to return an uninitialized symbol entry
* if a lookup fails.
*/
symbol_t *
symtable_get(char *name)
{
symbol_t *stored_ptr;
DBT key;
DBT data;
int retval;
key.data = (void *)name;
key.size = strlen(name);
if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) {
if (retval == -1) {
perror("Symbol table get operation failed");
exit(EX_SOFTWARE);
/* NOTREACHED */
} else if (retval == 1) {
/* Symbol wasn't found, so create a new one */
symbol_t *new_symbol;
new_symbol = symbol_create(name);
data.data = &new_symbol;
data.size = sizeof(new_symbol);
if (symtable->put(symtable, &key, &data,
/*flags*/0) !=0) {
perror("Symtable put failed");
exit(EX_SOFTWARE);
}
return (new_symbol);
} else {
perror("Unexpected return value from db get routine");
exit(EX_SOFTWARE);
/* NOTREACHED */
}
}
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
stored_ptr->count++;
data.data = &stored_ptr;
if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
perror("Symtable put failed");
exit(EX_SOFTWARE);
}
return (stored_ptr);
}
symbol_node_t *
symlist_search(symlist_t *symlist, char *symname)
{
symbol_node_t *curnode;
curnode = SLIST_FIRST(symlist);
while(curnode != NULL) {
if (strcmp(symname, curnode->symbol->name) == 0)
break;
curnode = SLIST_NEXT(curnode, links);
}
return (curnode);
}
void
symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
{
symbol_node_t *newnode;
newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t));
if (newnode == NULL) {
stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE);
/* NOTREACHED */
}
newnode->symbol = symbol;
if (how == SYMLIST_SORT) {
symbol_node_t *curnode;
int field;
field = FALSE;
switch(symbol->type) {
case REGISTER:
case SCBLOC:
case SRAMLOC:
break;
case FIELD:
case MASK:
case ENUM:
case ENUM_ENTRY:
field = TRUE;
break;
default:
stop("symlist_add: Invalid symbol type for sorting",
EX_SOFTWARE);
/* NOTREACHED */
}
curnode = SLIST_FIRST(symlist);
if (curnode == NULL
|| (field
&& (curnode->symbol->type > newnode->symbol->type
|| (curnode->symbol->type == newnode->symbol->type
&& (curnode->symbol->info.finfo->value >
newnode->symbol->info.finfo->value))))
|| (!field && (curnode->symbol->info.rinfo->address >
newnode->symbol->info.rinfo->address))) {
SLIST_INSERT_HEAD(symlist, newnode, links);
return;
}
while (1) {
if (SLIST_NEXT(curnode, links) == NULL) {
SLIST_INSERT_AFTER(curnode, newnode,
links);
break;
} else {
symbol_t *cursymbol;
cursymbol = SLIST_NEXT(curnode, links)->symbol;
if ((field
&& (cursymbol->type > symbol->type
|| (cursymbol->type == symbol->type
&& (cursymbol->info.finfo->value >
symbol->info.finfo->value))))
|| (!field
&& (cursymbol->info.rinfo->address >
symbol->info.rinfo->address))) {
SLIST_INSERT_AFTER(curnode, newnode,
links);
break;
}
}
curnode = SLIST_NEXT(curnode, links);
}
} else {
SLIST_INSERT_HEAD(symlist, newnode, links);
}
}
void
symlist_free(symlist_t *symlist)
{
symbol_node_t *node1, *node2;
node1 = SLIST_FIRST(symlist);
while (node1 != NULL) {
node2 = SLIST_NEXT(node1, links);
free(node1);
node1 = node2;
}
SLIST_INIT(symlist);
}
void
symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
symlist_t *symlist_src2)
{
symbol_node_t *node;
*symlist_dest = *symlist_src1;
while((node = SLIST_FIRST(symlist_src2)) != NULL) {
SLIST_REMOVE_HEAD(symlist_src2, links);
SLIST_INSERT_HEAD(symlist_dest, node, links);
}
/* These are now empty */
SLIST_INIT(symlist_src1);
SLIST_INIT(symlist_src2);
}
void
aic_print_file_prologue(FILE *ofile)
{
if (ofile == NULL)
return;
fprintf(ofile,
"/*\n"
" * DO NOT EDIT - This file is automatically generated\n"
" * from the following source files:\n"
" *\n"
"%s */\n",
versions);
}
void
aic_print_include(FILE *dfile, char *include_file)
{
if (dfile == NULL)
return;
fprintf(dfile, "\n#include \"%s\"\n\n", include_file);
}
void
aic_print_reg_dump_types(FILE *ofile)
{
if (ofile == NULL)
return;
fprintf(ofile,
"typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
"typedef struct %sreg_parse_entry {\n"
" char *name;\n"
" uint8_t value;\n"
" uint8_t mask;\n"
"} %sreg_parse_entry_t;\n"
"\n",
prefix, prefix, prefix);
}
static void
aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
{
if (dfile == NULL)
return;
fprintf(dfile,
"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
prefix,
regnode->symbol->name);
}
static void
aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
symbol_node_t *regnode, u_int num_entries)
{
char *lower_name;
char *letter;
lower_name = strdup(regnode->symbol->name);
if (lower_name == NULL)
stop("Unable to strdup symbol name", EX_SOFTWARE);
for (letter = lower_name; *letter != '\0'; letter++)
*letter = tolower(*letter);
if (dfile != NULL) {
if (num_entries != 0)
fprintf(dfile,
"\n"
"};\n"
"\n");
fprintf(dfile,
"int\n"
"%s%s_print(u_int regvalue, u_int *cur_col, u_int wrap)\n"
"{\n"
" return (%sprint_register(%s%s, %d, \"%s\",\n"
" 0x%02x, regvalue, cur_col, wrap));\n"
"}\n"
"\n",
prefix,
lower_name,
prefix,
num_entries != 0 ? regnode->symbol->name : "NULL",
num_entries != 0 ? "_parse_table" : "",
num_entries,
regnode->symbol->name,
regnode->symbol->info.rinfo->address);
}
fprintf(ofile,
"#if AIC_DEBUG_REGISTERS\n"
"%sreg_print_t %s%s_print;\n"
"#else\n"
"#define %s%s_print(regvalue, cur_col, wrap) \\\n"
" %sprint_register(NULL, 0, \"%s\", 0x%02x, regvalue, cur_col, wrap)\n"
"#endif\n"
"\n",
prefix,
prefix,
lower_name,
prefix,
lower_name,
prefix,
regnode->symbol->name,
regnode->symbol->info.rinfo->address);
}
static void
aic_print_reg_dump_entry(FILE *dfile, symbol_node_t *curnode)
{
int num_tabs;
if (dfile == NULL)
return;
fprintf(dfile,
" { \"%s\",",
curnode->symbol->name);
num_tabs = 3 - (strlen(curnode->symbol->name) + 5) / 8;
while (num_tabs-- > 0)
fputc('\t', dfile);
fprintf(dfile, "0x%02x, 0x%02x }",
curnode->symbol->info.finfo->value,
curnode->symbol->info.finfo->mask);
}
void
symtable_dump(FILE *ofile, FILE *dfile)
{
/*
* Sort the registers by address with a simple insertion sort.
* Put bitmasks next to the first register that defines them.
* Put constants at the end.
*/
symlist_t registers;
symlist_t masks;
symlist_t constants;
symlist_t download_constants;
symlist_t aliases;
symlist_t exported_labels;
symbol_node_t *curnode;
symbol_node_t *regnode;
DBT key;
DBT data;
int flag;
int reg_count = 0, reg_used = 0;
u_int i;
if (symtable == NULL)
return;
SLIST_INIT(&registers);
SLIST_INIT(&masks);
SLIST_INIT(&constants);
SLIST_INIT(&download_constants);
SLIST_INIT(&aliases);
SLIST_INIT(&exported_labels);
flag = R_FIRST;
while (symtable->seq(symtable, &key, &data, flag) == 0) {
symbol_t *cursym;
memcpy(&cursym, data.data, sizeof(cursym));
switch(cursym->type) {
case REGISTER:
case SCBLOC:
case SRAMLOC:
symlist_add(&registers, cursym, SYMLIST_SORT);
break;
case MASK:
case FIELD:
case ENUM:
case ENUM_ENTRY:
symlist_add(&masks, cursym, SYMLIST_SORT);
break;
case CONST:
symlist_add(&constants, cursym,
SYMLIST_INSERT_HEAD);
break;
case DOWNLOAD_CONST:
symlist_add(&download_constants, cursym,
SYMLIST_INSERT_HEAD);
break;
case ALIAS:
symlist_add(&aliases, cursym,
SYMLIST_INSERT_HEAD);
break;
case LABEL:
if (cursym->info.linfo->exported == 0)
break;
symlist_add(&exported_labels, cursym,
SYMLIST_INSERT_HEAD);
break;
default:
break;
}
flag = R_NEXT;
}
/* Register dianostic functions/declarations first. */
aic_print_file_prologue(ofile);
aic_print_reg_dump_types(ofile);
aic_print_file_prologue(dfile);
aic_print_include(dfile, stock_include_file);
SLIST_FOREACH(curnode, &registers, links) {
if (curnode->symbol->dont_generate_debug_code)
continue;
switch(curnode->symbol->type) {
case REGISTER:
case SCBLOC:
case SRAMLOC:
{
symlist_t *fields;
symbol_node_t *fieldnode;
int num_entries;
num_entries = 0;
reg_count++;
if (curnode->symbol->count == 1)
break;
fields = &curnode->symbol->info.rinfo->fields;
SLIST_FOREACH(fieldnode, fields, links) {
if (num_entries == 0)
aic_print_reg_dump_start(dfile,
curnode);
else if (dfile != NULL)
fputs(",\n", dfile);
num_entries++;
aic_print_reg_dump_entry(dfile, fieldnode);
}
aic_print_reg_dump_end(ofile, dfile,
curnode, num_entries);
reg_used++;
}
default:
break;
}
}
fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
reg_used, reg_count);
/* Fold in the masks and bits */
while (SLIST_FIRST(&masks) != NULL) {
char *regname;
curnode = SLIST_FIRST(&masks);
SLIST_REMOVE_HEAD(&masks, links);
regnode = SLIST_FIRST(&curnode->symbol->info.finfo->symrefs);
regname = regnode->symbol->name;
regnode = symlist_search(&registers, regname);
SLIST_INSERT_AFTER(regnode, curnode, links);
}
/* Add the aliases */
while (SLIST_FIRST(&aliases) != NULL) {
char *regname;
curnode = SLIST_FIRST(&aliases);
SLIST_REMOVE_HEAD(&aliases, links);
regname = curnode->symbol->info.ainfo->parent->name;
regnode = symlist_search(&registers, regname);
SLIST_INSERT_AFTER(regnode, curnode, links);
}
/* Output generated #defines. */
while (SLIST_FIRST(&registers) != NULL) {
symbol_node_t *curnode;
u_int value;
char *tab_str;
char *tab_str2;
curnode = SLIST_FIRST(&registers);
SLIST_REMOVE_HEAD(&registers, links);
switch(curnode->symbol->type) {
case REGISTER:
case SCBLOC:
case SRAMLOC:
fprintf(ofile, "\n");
value = curnode->symbol->info.rinfo->address;
tab_str = "\t";
tab_str2 = "\t\t";
break;
case ALIAS:
{
symbol_t *parent;
parent = curnode->symbol->info.ainfo->parent;
value = parent->info.rinfo->address;
tab_str = "\t";
tab_str2 = "\t\t";
break;
}
case MASK:
case FIELD:
case ENUM:
case ENUM_ENTRY:
value = curnode->symbol->info.finfo->value;
tab_str = "\t\t";
tab_str2 = "\t";
break;
default:
value = 0; /* Quiet compiler */
tab_str = NULL;
tab_str2 = NULL;
stop("symtable_dump: Invalid symbol type "
"encountered", EX_SOFTWARE);
break;
}
fprintf(ofile, "#define%s%-16s%s0x%02x\n",
tab_str, curnode->symbol->name, tab_str2,
value);
free(curnode);
}
fprintf(ofile, "\n\n");
while (SLIST_FIRST(&constants) != NULL) {
symbol_node_t *curnode;
curnode = SLIST_FIRST(&constants);
SLIST_REMOVE_HEAD(&constants, links);
fprintf(ofile, "#define\t%-8s\t0x%02x\n",
curnode->symbol->name,
curnode->symbol->info.cinfo->value);
free(curnode);
}
fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {
symbol_node_t *curnode;
curnode = SLIST_FIRST(&download_constants);
SLIST_REMOVE_HEAD(&download_constants, links);
fprintf(ofile, "#define\t%-8s\t0x%02x\n",
curnode->symbol->name,
curnode->symbol->info.cinfo->value);
free(curnode);
}
fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i);
fprintf(ofile, "\n\n/* Exported Labels */\n");
while (SLIST_FIRST(&exported_labels) != NULL) {
symbol_node_t *curnode;
curnode = SLIST_FIRST(&exported_labels);
SLIST_REMOVE_HEAD(&exported_labels, links);
fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n",
curnode->symbol->name,
curnode->symbol->info.linfo->address);
free(curnode);
}
}

View File

@@ -0,0 +1,209 @@
/*
* Aic7xxx SCSI host adapter firmware asssembler symbol table definitions
*
* Copyright (c) 1997 Justin T. Gibbs.
* Copyright (c) 2002 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_symbol.h#17 $
*
* $FreeBSD$
*/
#ifdef __linux__
#include "../queue.h"
#else
#include <sys/queue.h>
#endif
typedef enum {
UNINITIALIZED,
REGISTER,
ALIAS,
SCBLOC,
SRAMLOC,
ENUM_ENTRY,
FIELD,
MASK,
ENUM,
CONST,
DOWNLOAD_CONST,
LABEL,
CONDITIONAL,
MACRO
} symtype;
typedef enum {
RO = 0x01,
WO = 0x02,
RW = 0x03
}amode_t;
typedef SLIST_HEAD(symlist, symbol_node) symlist_t;
struct reg_info {
u_int address;
int size;
amode_t mode;
symlist_t fields;
uint8_t valid_bitmask;
uint8_t modes;
int typecheck_masks;
};
struct field_info {
symlist_t symrefs;
uint8_t value;
uint8_t mask;
};
struct const_info {
u_int value;
int define;
};
struct alias_info {
struct symbol *parent;
};
struct label_info {
int address;
int exported;
};
struct cond_info {
int func_num;
};
struct macro_arg {
STAILQ_ENTRY(macro_arg) links;
regex_t arg_regex;
char *replacement_text;
};
STAILQ_HEAD(macro_arg_list, macro_arg) args;
struct macro_info {
struct macro_arg_list args;
int narg;
const char* body;
};
typedef struct expression_info {
symlist_t referenced_syms;
int value;
} expression_t;
typedef struct symbol {
char *name;
symtype type;
int count;
union {
struct reg_info *rinfo;
struct field_info *finfo;
struct const_info *cinfo;
struct alias_info *ainfo;
struct label_info *linfo;
struct cond_info *condinfo;
struct macro_info *macroinfo;
} info;
int dont_generate_debug_code;
} symbol_t;
typedef struct symbol_ref {
symbol_t *symbol;
int offset;
} symbol_ref_t;
typedef struct symbol_node {
SLIST_ENTRY(symbol_node) links;
symbol_t *symbol;
} symbol_node_t;
typedef struct critical_section {
TAILQ_ENTRY(critical_section) links;
int begin_addr;
int end_addr;
} critical_section_t;
typedef enum {
SCOPE_ROOT,
SCOPE_IF,
SCOPE_ELSE_IF,
SCOPE_ELSE
} scope_type;
typedef struct patch_info {
int skip_patch;
int skip_instr;
} patch_info_t;
typedef struct scope {
SLIST_ENTRY(scope) scope_stack_links;
TAILQ_ENTRY(scope) scope_links;
TAILQ_HEAD(, scope) inner_scope;
scope_type type;
int inner_scope_patches;
int begin_addr;
int end_addr;
patch_info_t patches[2];
int func_num;
} scope_t;
TAILQ_HEAD(cs_tailq, critical_section);
SLIST_HEAD(scope_list, scope);
TAILQ_HEAD(scope_tailq, scope);
void symbol_delete(symbol_t *symbol);
void symtable_open(void);
void symtable_close(void);
symbol_t *
symtable_get(char *name);
symbol_node_t *
symlist_search(symlist_t *symlist, char *symname);
void
symlist_add(symlist_t *symlist, symbol_t *symbol, int how);
#define SYMLIST_INSERT_HEAD 0x00
#define SYMLIST_SORT 0x01
void symlist_free(symlist_t *symlist);
void symlist_merge(symlist_t *symlist_dest, symlist_t *symlist_src1,
symlist_t *symlist_src2);
void symtable_dump(FILE *ofile, FILE *dfile);