diff options
Diffstat (limited to 'sys/dev/microcode/aic7xxx/aicasm_gram.y')
-rw-r--r-- | sys/dev/microcode/aic7xxx/aicasm_gram.y | 386 |
1 files changed, 242 insertions, 144 deletions
diff --git a/sys/dev/microcode/aic7xxx/aicasm_gram.y b/sys/dev/microcode/aic7xxx/aicasm_gram.y index 6b88e2c0372..2c84b9215b7 100644 --- a/sys/dev/microcode/aic7xxx/aicasm_gram.y +++ b/sys/dev/microcode/aic7xxx/aicasm_gram.y @@ -1,9 +1,12 @@ %{ +/* $OpenBSD: aicasm_gram.y,v 1.11 2003/12/24 23:27:55 krw Exp $ */ +/* $NetBSD: aicasm_gram.y,v 1.3 2003/04/19 19:26:11 fvdl Exp $ */ + /* * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. * * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. - * Copyright (c) 2001 Adaptec Inc. + * Copyright (c) 2001, 2002 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +41,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.17 2002/06/05 22:51:54 gibbs Exp $ + * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.23 2003/01/20 18:02:11 gibbs Exp $ */ #include <sys/types.h> @@ -50,19 +53,26 @@ #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 "sequencer.h" +#include "aicasm_insformat.h" int yylineno; char *yyfilename; +char stock_prefix[] = "aic_"; +char *prefix = stock_prefix; char *patch_arg_list; char *versions; static char errbuf[255]; static char regex_pattern[255]; static symbol_t *cur_symbol; +static symbol_t *field_symbol; static symbol_t *scb_or_sram_symbol; static symtype cur_symtype; static symbol_ref_t accumulator; @@ -76,8 +86,10 @@ static int num_srams; static int sram_or_scb_offset; static int download_constant_count; static int in_critical_section; +static u_int enum_increment; +static u_int enum_next_value; -static void process_bitmask(int mask_type, symbol_t *sym, int mask); +static void process_field(int field_type, symbol_t *sym, int mask); static void initialize_symbol(symbol_t *symbol); static void add_macro_arg(const char *argtext, int position); static void add_macro_body(const char *bodytext); @@ -146,7 +158,9 @@ static int is_download_const(expression_t *immed); %token T_END_CS -%token T_BIT +%token T_FIELD + +%token T_ENUM %token T_MASK @@ -156,7 +170,7 @@ static int is_download_const(expression_t *immed); %token <sym> T_CEXPR -%token T_EOF T_INCLUDE T_VERSION T_PATCH_ARG_LIST +%token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST %token <value> T_SHR T_SHL T_ROR T_ROL @@ -196,7 +210,7 @@ static int is_download_const(expression_t *immed); %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne -%type <value> numerical_value mode_value mode_list macro_arglist +%type <value> mode_value mode_list macro_arglist %left '|' %left '&' @@ -210,10 +224,12 @@ static int is_download_const(expression_t *immed); program: include | program include +| prefix +| program prefix | patch_arg_list | program patch_arg_list -| version -| program version +| version +| program version | register | program register | constant @@ -230,10 +246,10 @@ program: | program set_src_mode | set_dst_mode | program set_dst_mode -| critical_section_start -| program critical_section_start -| critical_section_end -| program critical_section_end +| critical_section_start +| program critical_section_start +| critical_section_end +| program critical_section_end | conditional | program conditional | code @@ -242,13 +258,25 @@ program: include: T_INCLUDE '<' T_PATH '>' - { - include_file($3, BRACKETED_INCLUDE); - } + { + include_file($3, BRACKETED_INCLUDE); + } | T_INCLUDE '"' T_PATH '"' - { - include_file($3, QUOTED_INCLUDE); - } + { + include_file($3, QUOTED_INCLUDE); + } +; + +prefix: + T_PREFIX '=' T_STRING + { + if (prefix != stock_prefix) + stop("Prefix multiply defined", + EX_DATAERR); + prefix = strdup($3); + if (prefix == NULL) + stop("Unable to record prefix", EX_SOFTWARE); + } ; patch_arg_list: @@ -264,8 +292,8 @@ patch_arg_list: ; version: - T_VERSION '=' T_STRING - { add_version($3); } + T_VERSION '=' T_STRING + { add_version($3); } ; register: @@ -320,7 +348,8 @@ reg_attribute: | size | access_mode | modes -| bit_defn +| field_defn +| enum_defn | mask_defn | alias | accumulator @@ -412,17 +441,68 @@ mode_value: } ; -bit_defn: - T_BIT T_SYMBOL T_NUMBER +field_defn: + T_FIELD + { + field_symbol = NULL; + enum_next_value = 0; + enum_increment = 1; + } + '{' enum_entry_list '}' +| T_FIELD T_SYMBOL expression + { + process_field(FIELD, $2, $3.value); + field_symbol = $2; + enum_next_value = 0; + enum_increment = 0x01 << (ffs($3.value) - 1); + } + '{' enum_entry_list '}' +| T_FIELD T_SYMBOL expression { - process_bitmask(BIT, $2, $3); + process_field(FIELD, $2, $3.value); + } +; + +enum_defn: + T_ENUM + { + field_symbol = NULL; + enum_next_value = 0; + enum_increment = 1; + } + '{' enum_entry_list '}' +| T_ENUM T_SYMBOL expression + { + process_field(ENUM, $2, $3.value); + field_symbol = $2; + enum_next_value = 0; + enum_increment = 0x01 << (ffs($3.value) - 1); + } + '{' enum_entry_list '}' +; + +enum_entry_list: + enum_entry +| enum_entry_list ',' enum_entry +; + +enum_entry: + T_SYMBOL + { + process_field(ENUM_ENTRY, $1, enum_next_value); + enum_next_value += enum_increment; + } +| T_SYMBOL expression + { + process_field(ENUM_ENTRY, $1, $2.value); + enum_next_value = $2.value + enum_increment; } ; mask_defn: T_MASK T_SYMBOL expression { - process_bitmask(MASK, $2, $3.value); + process_field(MASK, $2, $3.value); } ; @@ -602,8 +682,10 @@ expression: $$.value = symbol->info.rinfo->address; break; case MASK: - case BIT: - $$.value = symbol->info.minfo->mask; + case FIELD: + case ENUM: + case ENUM_ENTRY: + $$.value = symbol->info.finfo->value; break; case DOWNLOAD_CONST: case CONST: @@ -626,7 +708,7 @@ expression: ; constant: - T_CONST T_SYMBOL numerical_value + T_CONST T_SYMBOL expression { if ($2->type != UNINITIALIZED) { stop("Re-definition of symbol as a constant", @@ -635,7 +717,7 @@ constant: } $2->type = CONST; initialize_symbol($2); - $2->info.cinfo->value = $3; + $2->info.cinfo->value = $3.value; } | T_CONST T_SYMBOL T_DOWNLOAD { @@ -703,17 +785,6 @@ macro_arglist: } ; -numerical_value: - T_NUMBER - { - $$ = $1; - } -| '-' T_NUMBER - { - $$ = -$2; - } -; - scratch_ram: T_SRAM '{' { @@ -752,8 +823,8 @@ scb: } cur_symbol->type = SCBLOC; initialize_symbol(cur_symbol); - /* 64 bytes of SCB space */ - cur_symbol->info.rinfo->size = 64; + /* 64 bytes of SCB space */ + cur_symbol->info.rinfo->size = 64; } reg_address { @@ -790,21 +861,21 @@ reg_symbol: $$.symbol = $1; $$.offset = 0; } -| T_SYMBOL '[' T_SYMBOL ']' - { - process_register(&$1); - if ($3->type != CONST) { - stop("register offset must be a constant", EX_DATAERR); - /* NOTREACHED */ - } - if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { - stop("Accessing offset beyond range of register", - EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = $1; - $$.offset = $3->info.cinfo->value; - } +| T_SYMBOL '[' T_SYMBOL ']' + { + process_register(&$1); + if ($3->type != CONST) { + stop("register offset must be a constant", EX_DATAERR); + /* NOTREACHED */ + } + if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { + stop("Accessing offset beyond range of register", + EX_DATAERR); + /* NOTREACHED */ + } + $$.symbol = $1; + $$.offset = $3->info.cinfo->value; + } | T_SYMBOL '[' T_NUMBER ']' { process_register(&$1); @@ -856,6 +927,8 @@ immediate_or_a: | T_A { SLIST_INIT(&$$.referenced_syms); + symlist_add(&$$.referenced_syms, accumulator.symbol, + SYMLIST_INSERT_HEAD); $$.value = 0; } ; @@ -900,31 +973,33 @@ set_dst_mode: critical_section_start: T_BEGIN_CS ';' { - critical_section_t *cs; + critical_section_t *cs; - if (in_critical_section != FALSE) { - stop("Critical Section within Critical Section", - EX_DATAERR); - /* NOTREACHED */ - } - cs = cs_alloc(); - cs->begin_addr = instruction_ptr; - in_critical_section = TRUE; - } + if (in_critical_section != FALSE) { + stop("Critical Section within Critical Section", + EX_DATAERR); + /* NOTREACHED */ + } + cs = cs_alloc(); + cs->begin_addr = instruction_ptr; + in_critical_section = TRUE; + } +; critical_section_end: T_END_CS ';' { - critical_section_t *cs; + critical_section_t *cs; - if (in_critical_section == FALSE) { - stop("Unballanced 'end_cs'", EX_DATAERR); - /* NOTREACHED */ - } - cs = TAILQ_LAST(&cs_tailq, cs_tailq); - cs->end_addr = instruction_ptr; - in_critical_section = FALSE; - } + if (in_critical_section == FALSE) { + stop("Unballanced 'end_cs'", EX_DATAERR); + /* NOTREACHED */ + } + cs = TAILQ_LAST(&cs_tailq, cs_tailq); + cs->end_addr = instruction_ptr; + in_critical_section = FALSE; + } +; export: { $$ = 0; } @@ -1149,25 +1224,38 @@ code: { expression_t immed; - make_expression(&immed, 1); - format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); + make_expression(&immed, 1); + format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); } ; code: - T_MVI destination ',' immediate_or_a ret ';' + T_MVI destination ',' immediate ret ';' { - format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); - } + if ($4.value == 0 + && is_download_const(&$4) == 0) { + expression_t immed; + + /* + * Allow move immediates of 0 so that macros, + * that can't know the immediate's value and + * otherwise compensate, still work. + */ + make_expression(&immed, 1); + format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5); + } else { + format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); + } + } ; code: - T_NOT destination opt_source ret ';' - { - expression_t immed; + T_NOT destination opt_source ret ';' + { + expression_t immed; - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); + make_expression(&immed, 0xff); + format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); } ; @@ -1292,7 +1380,7 @@ code: %% static void -process_bitmask(int mask_type, symbol_t *sym, int mask) +process_field(int field_type, symbol_t *sym, int value) { /* * Add the current register to its @@ -1302,52 +1390,54 @@ process_bitmask(int mask_type, symbol_t *sym, int mask) * the "allowed bits" of this register. */ if (sym->type == UNINITIALIZED) { - sym->type = mask_type; + sym->type = field_type; initialize_symbol(sym); - if (mask_type == BIT) { - if (mask == 0) { - stop("Bitmask with no bits set", EX_DATAERR); - /* NOTREACHED */ - } - if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) { - stop("Bitmask with more than one bit set", - EX_DATAERR); + sym->info.finfo->value = value; + if (field_type != ENUM_ENTRY) { + if (field_type != MASK && value == 0) { + stop("Empty Field, or Enum", EX_DATAERR); /* NOTREACHED */ } + sym->info.finfo->value = value; + sym->info.finfo->mask = value; + } else if (field_symbol != NULL) { + sym->info.finfo->mask = field_symbol->info.finfo->value; + } else { + sym->info.finfo->mask = 0xFF; } - sym->info.minfo->mask = mask; - } else if (sym->type != mask_type) { - stop("Bit definition mirrors a definition of the same " + } else if (sym->type != field_type) { + stop("Field definition mirrors a definition of the same " " name, but a different type", EX_DATAERR); /* NOTREACHED */ - } else if (mask != sym->info.minfo->mask) { - stop("Bitmask redefined with a conflicting value", EX_DATAERR); + } else if (value != sym->info.finfo->value) { + stop("Field redefined with a conflicting value", EX_DATAERR); /* NOTREACHED */ } /* Fail if this symbol is already listed */ - if (symlist_search(&(sym->info.minfo->symrefs), + if (symlist_search(&(sym->info.finfo->symrefs), cur_symbol->name) != NULL) { - stop("Bitmask defined multiple times for register", EX_DATAERR); + stop("Field defined multiple times for register", EX_DATAERR); /* NOTREACHED */ } - symlist_add(&(sym->info.minfo->symrefs), cur_symbol, + symlist_add(&(sym->info.finfo->symrefs), cur_symbol, SYMLIST_INSERT_HEAD); - cur_symbol->info.rinfo->valid_bitmask |= mask; + cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; cur_symbol->info.rinfo->typecheck_masks = TRUE; + symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); } static void initialize_symbol(symbol_t *symbol) { switch (symbol->type) { - case UNINITIALIZED: + case UNINITIALIZED: stop("Call to initialize_symbol with type field unset", EX_SOFTWARE); /* NOTREACHED */ break; - case REGISTER: - case SRAMLOC: - case SCBLOC: + case REGISTER: + case SRAMLOC: + case SCBLOC: symbol->info.rinfo = (struct reg_info *)malloc(sizeof(struct reg_info)); if (symbol->info.rinfo == NULL) { @@ -1356,6 +1446,7 @@ initialize_symbol(symbol_t *symbol) } memset(symbol->info.rinfo, 0, sizeof(struct reg_info)); + SLIST_INIT(&(symbol->info.rinfo->fields)); /* * Default to allowing access in all register modes * or to the mode specified by the SCB or SRAM space @@ -1367,7 +1458,7 @@ initialize_symbol(symbol_t *symbol) else symbol->info.rinfo->modes = ~0; break; - case ALIAS: + case ALIAS: symbol->info.ainfo = (struct alias_info *)malloc(sizeof(struct alias_info)); if (symbol->info.ainfo == NULL) { @@ -1377,19 +1468,21 @@ initialize_symbol(symbol_t *symbol) memset(symbol->info.ainfo, 0, sizeof(struct alias_info)); break; - case MASK: - case BIT: - symbol->info.minfo = - (struct mask_info *)malloc(sizeof(struct mask_info)); - if (symbol->info.minfo == NULL) { - stop("Can't create bitmask info", EX_SOFTWARE); + case MASK: + case FIELD: + case ENUM: + case ENUM_ENTRY: + symbol->info.finfo = + (struct field_info *)malloc(sizeof(struct field_info)); + if (symbol->info.finfo == NULL) { + stop("Can't create field info", EX_SOFTWARE); /* NOTREACHED */ } - memset(symbol->info.minfo, 0, sizeof(struct mask_info)); - SLIST_INIT(&(symbol->info.minfo->symrefs)); + memset(symbol->info.finfo, 0, sizeof(struct field_info)); + SLIST_INIT(&(symbol->info.finfo->symrefs)); break; - case CONST: - case DOWNLOAD_CONST: + case CONST: + case DOWNLOAD_CONST: symbol->info.cinfo = (struct const_info *)malloc(sizeof(struct const_info)); if (symbol->info.cinfo == NULL) { @@ -1571,7 +1664,6 @@ format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, case AIC_OP_OR: dst_value = src_value | immed->value; break; - break; case AIC_OP_BMOV: dst_value = src_value; break; @@ -1580,9 +1672,9 @@ format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, } src_mode = dst_value & 0xF; dst_mode = (dst_value >> 4) & 0xF; -cant_update: } +cant_update: symlist_free(&immed->referenced_syms); instruction_ptr++; } @@ -1752,14 +1844,18 @@ type_check(symbol_t *symbol, expression_t *expression, int opcode) * Now make sure that all of the symbols referenced by the * expression are defined for this register. */ - if(symbol->info.rinfo->typecheck_masks != FALSE) { - SLIST_FOREACH(node, &expression->referenced_syms, links) { + if (symbol->info.rinfo->typecheck_masks != FALSE) { + for(node = expression->referenced_syms.slh_first; + node != NULL; + node = node->links.sle_next) { if ((node->symbol->type == MASK - || node->symbol->type == BIT) - && symlist_search(&node->symbol->info.minfo->symrefs, + || node->symbol->type == FIELD + || node->symbol->type == ENUM + || node->symbol->type == ENUM_ENTRY) + && symlist_search(&node->symbol->info.finfo->symrefs, symbol->name) == NULL) { snprintf(errbuf, sizeof(errbuf), - "Invalid bit or mask %s " + "Invalid field or mask %s " "for register %s", node->symbol->name, symbol->name); stop(errbuf, EX_DATAERR); @@ -1816,18 +1912,21 @@ add_conditional(symbol_t *symbol) static void add_version(const char *verstring) { - const char prefix[] = " * "; - int newlen; - int oldlen; - - newlen = strlen(verstring) + strlen(prefix); - oldlen = 0; - if (versions != NULL) - oldlen = strlen(versions); - versions = realloc(versions, newlen + oldlen + 2); - if (versions == NULL) - stop("Can't allocate version string", EX_SOFTWARE); - snprintf(&versions[oldlen], newlen + 2, "%s%s\n", prefix, verstring); + const char prefix[] = " * "; + int newlen; + int oldlen; + + newlen = strlen(verstring) + strlen(prefix); + oldlen = 0; + if (versions != NULL) + oldlen = strlen(versions); + versions = realloc(versions, newlen + oldlen + 2); + if (versions == NULL) + stop("Can't allocate version string", EX_SOFTWARE); + strcpy(&versions[oldlen], prefix); + strcpy(&versions[oldlen + strlen(prefix)], verstring); + versions[newlen + oldlen] = '\n'; + versions[newlen + oldlen + 1] = '\0'; } void @@ -1839,10 +1938,9 @@ yyerror(const char *string) static int is_download_const(expression_t *immed) { - if (SLIST_EMPTY(&immed->referenced_syms)) - return (FALSE); - if (SLIST_FIRST(&immed->referenced_syms)->symbol->type == - DOWNLOAD_CONST) + if ((immed->referenced_syms.slh_first != NULL) + && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) return (TRUE); + return (FALSE); } |