diff options
author | gibbs <gibbs@FreeBSD.org> | 1998-09-15 07:24:17 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1998-09-15 07:24:17 +0000 |
commit | b845ffee8074eddeeb44108a8646161fbcf33aff (patch) | |
tree | 29b6ded2164fbd85ddc231ce2953cec74858b5bc /sys/dev/aic7xxx/aicasm | |
parent | fd4d41dcf7b1812c21942f9a24ef7ee737d2f1dd (diff) | |
download | FreeBSD-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.c | 422 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm/aicasm.h | 19 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm/aicasm_gram.y | 186 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm/aicasm_scan.l | 55 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm/aicasm_symbol.c | 7 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm/aicasm_symbol.h | 42 |
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)); |