summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aicasm
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-09-15 07:24:17 +0000
committergibbs <gibbs@FreeBSD.org>1998-09-15 07:24:17 +0000
commitb845ffee8074eddeeb44108a8646161fbcf33aff (patch)
tree29b6ded2164fbd85ddc231ce2953cec74858b5bc /sys/dev/aic7xxx/aicasm
parentfd4d41dcf7b1812c21942f9a24ef7ee737d2f1dd (diff)
downloadFreeBSD-src-b845ffee8074eddeeb44108a8646161fbcf33aff.zip
FreeBSD-src-b845ffee8074eddeeb44108a8646161fbcf33aff.tar.gz
Massive overhaul of the aic7xxx driver:
- Convert to CAM - Use a new DMA based queuing and paging scheme - Add preliminary target mode support - Add support for the aic789X chips - Take advantage of external SRAM on more controllers. - Numerous bug fixes and performance improvements.
Diffstat (limited to 'sys/dev/aic7xxx/aicasm')
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm.c422
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm.h19
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm_gram.y186
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm_scan.l55
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm_symbol.c7
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm_symbol.h42
6 files changed, 518 insertions, 213 deletions
diff --git a/sys/dev/aic7xxx/aicasm/aicasm.c b/sys/dev/aic7xxx/aicasm/aicasm.c
index c05950d..66d30ce 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm.c
+++ b/sys/dev/aic7xxx/aicasm/aicasm.c
@@ -1,7 +1,7 @@
/*
* Aic7xxx SCSI host adapter firmware asssembler
*
- * Copyright (c) 1997 Justin T. Gibbs.
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,10 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -28,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm.c,v 1.18 1997/06/27 19:38:45 gibbs Exp $
+ * $Id: aicasm.c,v 1.19 1997/09/03 03:44:38 gibbs Exp $
*/
#include <sys/types.h>
#include <sys/mman.h>
@@ -43,13 +40,24 @@
#include "aicasm_symbol.h"
#include "sequencer.h"
-static void usage __P((void));
-static void back_patch __P((void));
-static void output_code __P((FILE *ofile));
-static void output_listing __P((FILE *listfile, char *ifilename,
- char *options));
-static struct patch *next_patch __P((struct patch *cur_patch, int options,
- int instrptr));
+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(FILE *ofile);
+static void output_listing(FILE *listfile, char *ifilename);
+static int 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;
@@ -62,8 +70,8 @@ char *listfilename;
FILE *listfile;
static STAILQ_HEAD(,instruction) seq_program;
-static STAILQ_HEAD(, patch) patch_list;
-symlist_t patch_options;
+struct scope_list scope_stack;
+symlist_t patch_functions;
#if DEBUG
extern int yy_flex_debug;
@@ -82,19 +90,24 @@ main(argc, argv)
int ch;
int retval;
char *inputfilename;
- char *options;
+ scope_t *sentinal;
+ STAILQ_INIT(&patches);
SLIST_INIT(&search_path);
STAILQ_INIT(&seq_program);
- STAILQ_INIT(&patch_list);
- SLIST_INIT(&patch_options);
+ 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;
- options = NULL;
#if DEBUG
yy_flex_debug = 0;
+ yydebug = 0;
#endif
while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != -1) {
switch(ch) {
@@ -138,10 +151,6 @@ main(argc, argv)
}
ofilename = optarg;
break;
- case 'O':
- /* Patches to include in the listing */
- options = optarg;
- break;
case 'r':
if ((regfile = fopen(optarg, "w")) == NULL) {
perror(optarg);
@@ -207,13 +216,33 @@ main(argc, 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(ofile);
- if (regfile != NULL)
+ if (regfile != NULL) {
symtable_dump(regfile);
+ }
if (listfile != NULL)
- output_listing(listfile, inputfilename, options);
+ output_listing(listfile, inputfilename);
}
stop(NULL, 0);
@@ -228,7 +257,7 @@ usage()
(void)fprintf(stderr,
"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]
[-r register_output_file] [-l program_list_file]
- [-O option_name[|options_name2]] input_file\n",
+ input_file\n",
appname);
exit(EX_USAGE);
}
@@ -255,12 +284,9 @@ back_patch()
/* NOTREACHED */
}
f3_instr = &cur_instr->format.format3;
- address = ((f3_instr->opcode_addr & ADDR_HIGH_BIT) << 8)
- | f3_instr->address;
+ address = f3_instr->address;
address += cur_instr->patch_label->info.linfo->address;
- f3_instr->opcode_addr &= ~ADDR_HIGH_BIT;
- f3_instr->opcode_addr |= (address >> 8) & ADDR_HIGH_BIT;
- f3_instr->address = address & 0xFF;
+ f3_instr->address = address;
}
}
}
@@ -284,6 +310,7 @@ output_code(ofile)
for(cur_instr = seq_program.stqh_first;
cur_instr != NULL;
cur_instr = cur_instr->links.stqe_next) {
+
fprintf(ofile, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
cur_instr->format.bytes[0],
cur_instr->format.bytes[1],
@@ -291,60 +318,128 @@ output_code(ofile)
cur_instr->format.bytes[3]);
instrcount++;
}
- fprintf(ofile, "};\n");
+ fprintf(ofile, "};\n\n");
/*
- * Output the patch list, option definitions first.
+ * Output patch information. Patch functions first.
*/
- for(cur_node = patch_options.slh_first;
+ for(cur_node = SLIST_FIRST(&patch_functions);
cur_node != NULL;
- cur_node = cur_node->links.sle_next) {
- fprintf(ofile, "#define\t%-16s\t0x%x\n", cur_node->symbol->name,
- cur_node->symbol->info.condinfo->value);
+ cur_node = SLIST_NEXT(cur_node,links)) {
+ fprintf(ofile,
+"static int ahc_patch%d_func(struct ahc_softc *ahc);
+
+static int
+ahc_patch%d_func(struct ahc_softc *ahc)
+{
+ return (%s);
+}\n\n",
+ cur_node->symbol->info.condinfo->func_num,
+ cur_node->symbol->info.condinfo->func_num,
+ cur_node->symbol->name);
}
fprintf(ofile,
-"struct patch {
- int options;
- int negative;
- int begin;
- int end;
+"typedef int patch_func_t __P((struct ahc_softc *));
+struct patch {
+ patch_func_t *patch_func;
+ u_int32_t begin :10,
+ skip_instr :10,
+ skip_patch :12;
} patches[] = {\n");
- for(cur_patch = patch_list.stqh_first;
+ for(cur_patch = STAILQ_FIRST(&patches);
cur_patch != NULL;
- cur_patch = cur_patch->links.stqe_next)
+ cur_patch = STAILQ_NEXT(cur_patch,links)) {
+ fprintf(ofile, "\t{ ahc_patch%d_func, %d, %d, %d },\n",
+ cur_patch->patch_func, cur_patch->begin,
+ cur_patch->skip_instr, cur_patch->skip_patch);
+ }
- fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x },\n",
- cur_patch->options, cur_patch->negative, cur_patch->begin,
- cur_patch->end);
+ fprintf(ofile, "\n};\n");
- fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x }\n};\n",
- 0, 0, 0, 0);
-
fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
}
+static int
+dump_scope(scope_t *scope)
+{
+ scope_t *cur_scope;
+ int patches_emitted = 0;
+
+ /*
+ * 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(listfile, ifilename, patches)
- FILE *listfile;
- char *ifilename;
- char *patches;
+output_listing(FILE *listfile, char *ifilename)
{
+ char buf[1024];
FILE *ifile;
- int line;
struct instruction *cur_instr;
+ patch_t *cur_patch;
+ symbol_node_t *cur_func;
+ int *func_values;
int instrcount;
int instrptr;
- char buf[1024];
- patch_t *cur_patch;
- char *option_spec;
- int options;
+ int line;
+ int func_count;
+ int skip_addr;
instrcount = 0;
instrptr = 0;
line = 1;
- options = 1; /* All code outside of patch blocks */
+ skip_addr = 0;
if ((ifile = fopen(ifilename, "r")) == NULL) {
perror(ifilename);
stop(NULL, EX_DATAERR);
@@ -353,31 +448,66 @@ output_listing(listfile, ifilename, patches)
/*
* Determine which options to apply to this listing.
*/
- while ((option_spec = strsep(&patches, "|")) != NULL) {
- symbol_t *symbol;
-
- symbol = symtable_get(option_spec);
- if (symbol->type != CONDITIONAL) {
- stop("Invalid option specified in patch list for "
- "program listing", EX_USAGE);
- /* NOTREACHED */
+ for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
+ cur_func != NULL;
+ cur_func = SLIST_NEXT(cur_func, links))
+ func_count++;
+
+ 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;
+ }
+ }
}
- options |= symbol->info.condinfo->value;
+ fprintf(stdout, "\nThanks!\n");
}
- cur_patch = patch_list.stqh_first;
- for(cur_instr = seq_program.stqh_first;
+ /* Now output the listing */
+ cur_patch = STAILQ_FIRST(&patches);
+ for(cur_instr = STAILQ_FIRST(&seq_program);
cur_instr != NULL;
- cur_instr = cur_instr->links.stqe_next,instrcount++) {
+ cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
- cur_patch = next_patch(cur_patch, options, instrcount);
- if (cur_patch
- && cur_patch->begin <= instrcount
- && cur_patch->end > 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);
@@ -401,29 +531,39 @@ output_listing(listfile, ifilename, patches)
fclose(ifile);
}
-static struct patch *
-next_patch(cur_patch, options, instrptr)
- struct patch *cur_patch;
- int options;
- int instrptr;
+static int
+check_patch(patch_t **start_patch, int start_instr,
+ int *skip_addr, int *func_vals)
{
- while(cur_patch != NULL) {
- if (((cur_patch->options & options) != 0
- && cur_patch->negative == FALSE)
- || ((cur_patch->options & options) == 0
- && cur_patch->negative == TRUE)
- || (instrptr >= cur_patch->end)) {
- /*
- * Either we want to keep this section of code,
- * or we have consumed this patch. Skip to the
- * next patch.
+ 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 = cur_patch->links.stqe_next;
- } else
- /* Found an okay patch */
- break;
+ cur_patch = STAILQ_NEXT(cur_patch, links);
+ }
}
- return (cur_patch);
+
+ *start_patch = cur_patch;
+ if (start_instr < *skip_addr)
+ /* Still skipping */
+ return (0);
+
+ return (1);
}
/*
@@ -471,7 +611,7 @@ stop(string, err_code)
}
}
- symlist_free(&patch_options);
+ symlist_free(&patch_functions);
symtable_close();
exit(err_code);
@@ -491,15 +631,85 @@ seq_alloc()
return new_instr;
}
-patch_t *
-patch_alloc()
+scope_t *
+scope_alloc()
{
- patch_t *new_patch;
+ scope_t *new_scope;
- new_patch = (patch_t *)malloc(sizeof(patch_t));
- if (new_patch == NULL)
- stop("Unable to malloc patch object", EX_SOFTWARE);
- memset(new_patch, 0, sizeof(*new_patch));
- STAILQ_INSERT_TAIL(&patch_list, new_patch, links);
- return new_patch;
+ 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;
+ }
+
+ cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
+ }
}
diff --git a/sys/dev/aic7xxx/aicasm/aicasm.h b/sys/dev/aic7xxx/aicasm/aicasm.h
index a81afc1..5080675 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm.h
+++ b/sys/dev/aic7xxx/aicasm/aicasm.h
@@ -10,10 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -28,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx_asm.h,v 1.2 1997/03/16 07:28:30 gibbs Exp $
+ * $Id: aicasm.h,v 1.3 1997/06/27 19:38:47 gibbs Exp $
*/
#include <sys/queue.h>
@@ -56,13 +53,15 @@ typedef enum {
SLIST_HEAD(path_list, path_entry);
extern struct path_list search_path;
-extern struct symlist patch_options;
+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 int yylineno;
extern char *yyfilename;
-void stop __P((const char *errstring, int err_code));
-void include_file __P((char *file_name, include_type type));
-struct instruction *seq_alloc __P((void));
-struct patch *patch_alloc __P((void));
+void stop(const char *errstring, int err_code);
+void include_file(char *file_name, include_type type);
+struct instruction *seq_alloc(void);
+struct scope *scope_alloc(void);
+void process_scope(struct scope *);
diff --git a/sys/dev/aic7xxx/aicasm/aicasm_gram.y b/sys/dev/aic7xxx/aicasm/aicasm_gram.y
index fa657c0..09a62b9 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm_gram.y
+++ b/sys/dev/aic7xxx/aicasm/aicasm_gram.y
@@ -2,7 +2,7 @@
/*
* Parser for the Aic7xxx SCSI Host adapter sequencer assembler.
*
- * Copyright (c) 1997 Justin T. Gibbs.
+ * Copyright (c) 1997-1998 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -29,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_gram.y,v 1.3 1997/09/03 03:44:40 gibbs Exp $
+ * $Id: aicasm_gram.y,v 1.4 1997/09/27 19:37:28 gibbs Exp $
*/
#include <stdio.h>
@@ -56,7 +53,6 @@ static symbol_ref_t sindex;
static int instruction_ptr;
static int sram_or_scb_offset;
static int download_constant_count;
-static patch_t *cur_patch;
static void process_bitmask __P((int mask_type, symbol_t *sym, int mask));
static void initialize_symbol __P((symbol_t *symbol));
@@ -118,11 +114,13 @@ static int is_download_const __P((expression_t *immed));
%token <str> T_PATH
+%token <sym> T_CEXPR
+
%token T_EOF T_INCLUDE
%token <value> T_SHR T_SHL T_ROR T_ROL
-%token <value> T_MVI T_MOV T_CLR
+%token <value> T_MVI T_MOV T_CLR T_BMOV
%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
@@ -150,7 +148,7 @@ static int is_download_const __P((expression_t *immed));
%token T_NL
-%token T_IF T_ELSE T_ENDIF
+%token T_IF T_ELSE T_ELSE_IF T_ENDIF
%type <sym_ref> reg_symbol address destination source opt_source
@@ -670,64 +668,89 @@ address:
;
conditional:
- T_IF
+ T_IF T_CEXPR '{'
{
- if (cur_patch != NULL) {
- stop("Nested .if directive", EX_DATAERR);
- /* NOTREACHED */
- }
- cur_patch = patch_alloc();
- cur_patch->begin = instruction_ptr;
- }
- option_list
-;
+ scope_t *new_scope;
-conditional:
- T_ELSE
+ add_conditional($2);
+ new_scope = scope_alloc();
+ new_scope->type = SCOPE_IF;
+ new_scope->begin_addr = instruction_ptr;
+ new_scope->func_num = $2->info.condinfo->func_num;
+ }
+| T_ELSE T_IF T_CEXPR '{'
{
- patch_t *next_patch;
+ scope_t *new_scope;
+ scope_t *scope_context;
+ scope_t *last_scope;
+
+ /*
+ * Ensure that the previous scope is either an
+ * if or and else if.
+ */
+ scope_context = SLIST_FIRST(&scope_stack);
+ last_scope = TAILQ_LAST(&scope_context->inner_scope,
+ scope_tailq);
+ if (last_scope == NULL
+ || last_scope->type == T_ELSE) {
- if (cur_patch == NULL) {
- stop(".else outsize of .if", EX_DATAERR);
+ stop("'else if' without leading 'if'", EX_DATAERR);
+ /* NOTREACHED */
+ }
+ add_conditional($3);
+ new_scope = scope_alloc();
+ new_scope->type = SCOPE_ELSE_IF;
+ new_scope->begin_addr = instruction_ptr;
+ new_scope->func_num = $3->info.condinfo->func_num;
+ }
+| T_ELSE '{'
+ {
+ scope_t *new_scope;
+ scope_t *scope_context;
+ scope_t *last_scope;
+
+ /*
+ * Ensure that the previous scope is either an
+ * if or and else if.
+ */
+ scope_context = SLIST_FIRST(&scope_stack);
+ last_scope = TAILQ_LAST(&scope_context->inner_scope,
+ scope_tailq);
+ if (last_scope == NULL
+ || last_scope->type == SCOPE_ELSE) {
+
+ stop("'else' without leading 'if'", EX_DATAERR);
/* NOTREACHED */
}
- cur_patch->end = instruction_ptr;
- next_patch = patch_alloc();
- next_patch->options = cur_patch->options;
- next_patch->negative = cur_patch->negative ? FALSE : TRUE;
- cur_patch = next_patch;
- cur_patch->begin = instruction_ptr;
+ new_scope = scope_alloc();
+ new_scope->type = SCOPE_ELSE;
+ new_scope->begin_addr = instruction_ptr;
}
;
conditional:
- T_ENDIF
+ '}'
{
- if (cur_patch == NULL) {
- stop(".endif outsize of .if", EX_DATAERR);
+ scope_t *scope_context;
+ scope_t *last_scope;
+
+ scope_context = SLIST_FIRST(&scope_stack);
+ if (scope_context->type == SCOPE_ROOT) {
+ stop("Unexpected '}' encountered", EX_DATAERR);
/* NOTREACHED */
}
- cur_patch->end = instruction_ptr;
- cur_patch = NULL;
- }
-;
-option_list:
- '(' option_symbol_list ')'
-| '!' option_list
- {
- cur_patch->negative = cur_patch->negative ? FALSE : TRUE;
- }
-;
+ scope_context->end_addr = instruction_ptr;
-option_symbol_list:
- T_SYMBOL
- {
- add_conditional($1);
- }
-| option_list '|' T_SYMBOL
- {
- add_conditional($3);
+ /* Pop the scope */
+ SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
+
+ process_scope(scope_context);
+
+ if (SLIST_FIRST(&scope_stack) == NULL) {
+ stop("Unexpected '}' encountered", EX_DATAERR);
+ /* NOTREACHED */
+ }
}
;
@@ -804,6 +827,13 @@ code:
;
code:
+ T_BMOV destination ',' source ',' immediate ret ';'
+ {
+ format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
+ }
+;
+
+code:
T_MOV destination ',' source ret ';'
{
expression_t immed;
@@ -1118,7 +1148,8 @@ format_1_instr(opcode, dest, immed, src, ret)
/* Allocate sequencer space for the instruction and fill it out */
instr = seq_alloc();
f1_instr = &instr->format.format1;
- f1_instr->opcode_ret = (opcode << 1) | (ret ? RETURN_BIT : 0);
+ f1_instr->ret = ret ? 1 : 0;
+ f1_instr->opcode = opcode;
f1_instr->destination = dest->symbol->info.rinfo->address
+ dest->offset;
f1_instr->source = src->symbol->info.rinfo->address
@@ -1126,7 +1157,7 @@ format_1_instr(opcode, dest, immed, src, ret)
f1_instr->immediate = immed->value;
if (is_download_const(immed))
- f1_instr->opcode_ret |= DOWNLOAD_CONST_IMMEDIATE;
+ f1_instr->parity = 1;
symlist_free(&immed->referenced_syms);
instruction_ptr++;
@@ -1154,7 +1185,8 @@ format_2_instr(opcode, dest, places, src, ret)
/* Allocate sequencer space for the instruction and fill it out */
instr = seq_alloc();
f2_instr = &instr->format.format2;
- f2_instr->opcode_ret = (AIC_OP_ROL << 1) | (ret ? RETURN_BIT : 0);
+ f2_instr->ret = ret ? 1 : 0;
+ f2_instr->opcode = AIC_OP_ROL;
f2_instr->destination = dest->symbol->info.rinfo->address
+ dest->offset;
f2_instr->source = src->symbol->info.rinfo->address
@@ -1225,15 +1257,14 @@ format_3_instr(opcode, src, immed, address)
instr->patch_label = address->symbol;
} else
addr = address->symbol->info.linfo->address + address->offset;
- f3_instr->opcode_addr = (opcode << 1)
- | ((addr >> 8) & 0x01);
- f3_instr->address = addr & 0xff;
+ f3_instr->opcode = opcode;
+ f3_instr->address = addr;
f3_instr->source = src->symbol->info.rinfo->address
+ src->offset;
f3_instr->immediate = immed->value;
if (is_download_const(immed))
- f3_instr->opcode_addr |= DOWNLOAD_CONST_IMMEDIATE;
+ f3_instr->parity = 1;
symlist_free(&immed->referenced_syms);
instruction_ptr++;
@@ -1326,19 +1357,38 @@ static void
add_conditional(symbol)
symbol_t *symbol;
{
- static int numoptions = 1;
+ static int numfuncs;
- if (symbol->type == UNINITIALIZED) {
- symbol->type = CONDITIONAL;
- initialize_symbol(symbol);
- symbol->info.condinfo->value = 0x01 << numoptions++;
- symlist_add(&patch_options, symbol, SYMLIST_INSERT_HEAD);
- } else if (symbol->type != CONDITIONAL) {
- stop("Conditional symbol mirrors other symbol",
+ if (numfuncs == 0) {
+ /* add a special conditional, "0" */
+ symbol_t *false_func;
+
+ false_func = symtable_get("0");
+ if (false_func->type != UNINITIALIZED) {
+ stop("Conditional expression '0' "
+ "conflicts with a symbol", EX_DATAERR);
+ /* NOTREACHED */
+ }
+ false_func->type = CONDITIONAL;
+ initialize_symbol(false_func);
+ false_func->info.condinfo->func_num = numfuncs++;
+ symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
+ }
+
+ /* This condition has occurred before */
+ if (symbol->type == CONDITIONAL)
+ return;
+
+ if (symbol->type != UNINITIALIZED) {
+ stop("Conditional expression conflicts with a symbol",
EX_DATAERR);
/* NOTREACHED */
}
- cur_patch->options |= symbol->info.condinfo->value;
+
+ symbol->type = CONDITIONAL;
+ initialize_symbol(symbol);
+ symbol->info.condinfo->func_num = numfuncs++;
+ symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
}
void
diff --git a/sys/dev/aic7xxx/aicasm/aicasm_scan.l b/sys/dev/aic7xxx/aicasm/aicasm_scan.l
index 8446376..44bc834 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm_scan.l
+++ b/sys/dev/aic7xxx/aicasm/aicasm_scan.l
@@ -2,7 +2,7 @@
/*
* Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
*
- * Copyright (c) 1997 Justin T. Gibbs.
+ * Copyright (c) 1997-1998 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -29,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_scan.l,v 1.4 1997/09/03 03:44:42 gibbs Exp $
+ * $Id: aicasm_scan.l,v 1.5 1997/09/27 19:37:29 gibbs Exp $
*/
#include <sys/types.h>
@@ -43,6 +40,11 @@
#include "aicasm.h"
#include "aicasm_symbol.h"
#include "y.tab.h"
+
+#define MAX_STR_CONST 256
+char string_buf[MAX_STR_CONST];
+char *string_buf_ptr;
+int parren_count;
%}
PATH [-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
@@ -50,6 +52,8 @@ WORD [A-Za-z_][-A-Za-z_0-9]*
SPACE [ \t]+
%x COMMENT
+%x CEXPR
+%x INCLUDE
%%
\n { ++yylineno; }
@@ -60,6 +64,32 @@ SPACE [ \t]+
<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>[^()\n]+ {
+ char *yptr = yytext;
+
+ while (*yptr != '\0')
+ *string_buf_ptr++ = *yptr++;
+ }
{SPACE} ;
@@ -109,6 +139,7 @@ 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; }
@@ -120,12 +151,10 @@ and { return T_AND; }
or { return T_OR; }
ret { return T_RET; }
nop { return T_NOP; }
-.if { return T_IF; }
-.else { return T_ELSE; }
-.endif { return T_ENDIF; }
+else { return T_ELSE; }
/* Allowed Symbols */
-[-+,:()~|&."{};<>[\]!] { return yytext[0]; }
+[-+,:()~|&."{};<>[\]!] { return yytext[0]; }
/* Number processing */
0[0-7]* {
@@ -144,7 +173,11 @@ nop { return T_NOP; }
}
/* Include Files */
-#include { return T_INCLUDE; }
+#include { return T_INCLUDE; BEGIN INCLUDE;}
+<INCLUDE>[<>\"] { return yytext[0]; }
+<INCLUDE>{PATH} { yylval.str = strdup(yytext); return T_PATH; }
+<INCLUDE>; { BEGIN INITIAL; return yytext[0]; }
+<INCLUDE>. { stop("Invalid include line", EX_DATAERR); }
/* For parsing C include files with #define foo */
#define { yylval.value = TRUE; return T_CONST; }
diff --git a/sys/dev/aic7xxx/aicasm/aicasm_symbol.c b/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
index c9f645a..f808e89 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
+++ b/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
@@ -10,10 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -28,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_symbol.c,v 1.3 1997/09/03 03:44:44 gibbs Exp $
+ * $Id: aicasm_symbol.c,v 1.4 1997/09/27 19:37:30 gibbs Exp $
*/
diff --git a/sys/dev/aic7xxx/aicasm/aicasm_symbol.h b/sys/dev/aic7xxx/aicasm/aicasm_symbol.h
index 199e3ba..ba98b43 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm_symbol.h
+++ b/sys/dev/aic7xxx/aicasm/aicasm_symbol.h
@@ -10,10 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
@@ -28,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_symbol.h,v 1.2 1997/06/27 19:38:56 gibbs Exp $
+ * $Id: aicasm_symbol.h,v 1.3 1997/09/27 19:37:30 gibbs Exp $
*/
#include <sys/queue.h>
@@ -82,7 +79,7 @@ struct label_info {
};
struct cond_info {
- int value;
+ int func_num;
};
typedef struct expression_info {
@@ -113,13 +110,32 @@ typedef struct symbol_node {
symbol_t *symbol;
}symbol_node_t;
-typedef struct patch {
- STAILQ_ENTRY(patch) links;
- int negative;
- int begin;
- int end;
- int options;
-} patch_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;
+
+SLIST_HEAD(scope_list, scope);
+TAILQ_HEAD(scope_tailq, scope);
void symbol_delete __P((symbol_t *symbol));
OpenPOWER on IntegriCloud