The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/aic7xxx/aicasm/aicasm_gram.y

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 %{
    2 /*-
    3  * Parser for the Aic7xxx SCSI Host adapter sequencer assembler.
    4  *
    5  * SPDX-License-Identifier: BSD-3-Clause
    6  *
    7  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
    8  * Copyright (c) 2001, 2002 Adaptec Inc.
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions, and the following disclaimer,
   16  *    without modification.
   17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   18  *    substantially similar to the "NO WARRANTY" disclaimer below
   19  *    ("Disclaimer") and any redistribution must be conditioned upon
   20  *    including a substantially similar Disclaimer requirement for further
   21  *    binary redistribution.
   22  * 3. Neither the names of the above-listed copyright holders nor the names
   23  *    of any contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * Alternatively, this software may be distributed under the terms of the
   27  * GNU General Public License ("GPL") version 2 as published by the Free
   28  * Software Foundation.
   29  *
   30  * NO WARRANTY
   31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   41  * POSSIBILITY OF SUCH DAMAGES.
   42  *
   43  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
   44  *
   45  * $FreeBSD$
   46  */
   47 
   48 #include <sys/types.h>
   49 
   50 #include <inttypes.h>
   51 #include <regex.h>
   52 #include <stdio.h>
   53 #include <stdlib.h>
   54 #include <string.h>
   55 #include <sysexits.h>
   56 #include <sys/queue.h>
   57 
   58 #include "aicasm.h"
   59 #include "aicasm_symbol.h"
   60 #include "aicasm_insformat.h"
   61 
   62 extern int yylineno;
   63 char *yyfilename;
   64 char stock_prefix[] = "aic_";
   65 char *prefix = stock_prefix;
   66 char *patch_arg_list;
   67 char *versions;
   68 static char errbuf[255];
   69 static char regex_pattern[255];
   70 static symbol_t *cur_symbol;
   71 static symbol_t *field_symbol;
   72 static symbol_t *scb_or_sram_symbol;
   73 static symtype cur_symtype;
   74 static symbol_ref_t accumulator;
   75 static symbol_ref_t mode_ptr;
   76 static symbol_ref_t allones;
   77 static symbol_ref_t allzeros;
   78 static symbol_ref_t none;
   79 static symbol_ref_t sindex;
   80 static int instruction_ptr;
   81 static int num_srams;
   82 static int sram_or_scb_offset;
   83 static int download_constant_count;
   84 static int in_critical_section;
   85 static u_int enum_increment;
   86 static u_int enum_next_value;
   87 
   88 static void process_field(unsigned int field_type, symbol_t *sym, int mask);
   89 static void initialize_symbol(symbol_t *symbol);
   90 static void add_macro_arg(const char *argtext, int position);
   91 static void add_macro_body(const char *bodytext);
   92 static void process_register(symbol_t **p_symbol);
   93 static void format_1_instr(int opcode, symbol_ref_t *dest,
   94                            expression_t *immed, symbol_ref_t *src, int ret);
   95 static void format_2_instr(int opcode, symbol_ref_t *dest,
   96                            expression_t *places, symbol_ref_t *src, int ret);
   97 static void format_3_instr(int opcode, symbol_ref_t *src,
   98                            expression_t *immed, symbol_ref_t *address);
   99 static void test_readable_symbol(symbol_t *symbol);
  100 static void test_writable_symbol(symbol_t *symbol);
  101 static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
  102 static void make_expression(expression_t *immed, int value);
  103 static void add_conditional(symbol_t *symbol);
  104 static void add_version(const char *verstring);
  105 static int  is_download_const(expression_t *immed);
  106 
  107 extern int yylex (void);
  108 
  109 #define SRAM_SYMNAME "SRAM_BASE"
  110 #define SCB_SYMNAME "SCB_BASE"
  111 %}
  112 
  113 %union {
  114         u_int           value;
  115         char            *str;
  116         symbol_t        *sym;
  117         symbol_ref_t    sym_ref;
  118         expression_t    expression;
  119 }
  120 
  121 %token T_REGISTER
  122 
  123 %token <value> T_CONST
  124 
  125 %token T_EXPORT
  126 
  127 %token T_DOWNLOAD
  128 
  129 %token T_SCB
  130 
  131 %token T_SRAM
  132 
  133 %token T_ALIAS
  134 
  135 %token T_SIZE
  136 
  137 %token T_EXPR_LSHIFT
  138 
  139 %token T_EXPR_RSHIFT
  140 
  141 %token <value> T_ADDRESS
  142 
  143 %token T_ACCESS_MODE
  144 
  145 %token T_MODES
  146 
  147 %token T_DEFINE
  148 
  149 %token T_SET_SRC_MODE
  150 
  151 %token T_SET_DST_MODE
  152 
  153 %token <value> T_MODE
  154 
  155 %token T_BEGIN_CS
  156 
  157 %token T_END_CS
  158 
  159 %token T_FIELD
  160 
  161 %token T_ENUM
  162 
  163 %token T_MASK
  164 
  165 %token <value> T_NUMBER
  166 
  167 %token <str> T_PATH T_STRING T_ARG T_MACROBODY
  168 
  169 %token <sym> T_CEXPR
  170 
  171 %token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST
  172 
  173 %token <value> T_SHR T_SHL T_ROR T_ROL
  174 
  175 %token <value> T_MVI T_MOV T_CLR T_BMOV
  176 
  177 %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
  178 
  179 %token <value> T_ADD T_ADC
  180 
  181 %token <value> T_INC T_DEC
  182 
  183 %token <value> T_STC T_CLC
  184 
  185 %token <value> T_CMP T_NOT T_XOR
  186 
  187 %token <value> T_TEST T_AND
  188 
  189 %token <value> T_OR
  190 
  191 %token T_RET
  192 
  193 %token T_NOP
  194 
  195 %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR
  196 
  197 %token T_A
  198 
  199 %token <sym> T_SYMBOL
  200 
  201 %token T_NL
  202 
  203 %token T_IF T_ELSE T_ELSE_IF T_ENDIF
  204 
  205 %type <sym_ref> reg_symbol address destination source opt_source
  206 
  207 %type <expression> expression immediate immediate_or_a
  208 
  209 %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
  210 
  211 %type <value> mode_value mode_list macro_arglist
  212 
  213 %left '|'
  214 %left '&'
  215 %left T_EXPR_LSHIFT T_EXPR_RSHIFT
  216 %left '+' '-'
  217 %left '*' '/'
  218 %right '~'
  219 %nonassoc UMINUS
  220 %%
  221 
  222 program:
  223         include
  224 |       program include
  225 |       prefix
  226 |       program prefix
  227 |       patch_arg_list
  228 |       program patch_arg_list
  229 |       version
  230 |       program version
  231 |       register
  232 |       program register
  233 |       constant
  234 |       program constant
  235 |       macrodefn
  236 |       program macrodefn
  237 |       scratch_ram
  238 |       program scratch_ram
  239 |       scb
  240 |       program scb
  241 |       label
  242 |       program label
  243 |       set_src_mode
  244 |       program set_src_mode
  245 |       set_dst_mode
  246 |       program set_dst_mode
  247 |       critical_section_start
  248 |       program critical_section_start
  249 |       critical_section_end
  250 |       program critical_section_end
  251 |       conditional
  252 |       program conditional
  253 |       code
  254 |       program code
  255 ;
  256 
  257 include:
  258         T_INCLUDE '<' T_PATH '>'
  259         {
  260                 include_file($3, BRACKETED_INCLUDE);
  261         }
  262 |       T_INCLUDE '"' T_PATH '"'
  263         {
  264                 include_file($3, QUOTED_INCLUDE);
  265         }
  266 ;
  267 
  268 prefix:
  269         T_PREFIX '=' T_STRING
  270         {
  271                 if (prefix != stock_prefix)
  272                         stop("Prefix multiply defined",
  273                              EX_DATAERR);
  274                 prefix = strdup($3);
  275                 if (prefix == NULL)
  276                         stop("Unable to record prefix", EX_SOFTWARE);
  277         }
  278 ;
  279 
  280 patch_arg_list:
  281         T_PATCH_ARG_LIST '=' T_STRING
  282         {
  283                 if (patch_arg_list != NULL)
  284                         stop("Patch argument list multiply defined",
  285                              EX_DATAERR);
  286                 patch_arg_list = strdup($3);
  287                 if (patch_arg_list == NULL)
  288                         stop("Unable to record patch arg list", EX_SOFTWARE);
  289         }
  290 ;
  291 
  292 version:
  293         T_VERSION '=' T_STRING
  294         { add_version($3); }
  295 ;
  296 
  297 register:
  298         T_REGISTER { cur_symtype = REGISTER; } reg_definition
  299 ;
  300 
  301 reg_definition:
  302         T_SYMBOL '{'
  303                 {
  304                         if ($1->type != UNINITIALIZED) {
  305                                 stop("Register multiply defined", EX_DATAERR);
  306                                 /* NOTREACHED */
  307                         }
  308                         cur_symbol = $1; 
  309                         cur_symbol->type = cur_symtype;
  310                         initialize_symbol(cur_symbol);
  311                 }
  312                 reg_attribute_list
  313         '}'
  314                 {                    
  315                         /*
  316                          * Default to allowing everything in for registers
  317                          * with no bit or mask definitions.
  318                          */
  319                         if (cur_symbol->info.rinfo->valid_bitmask == 0)
  320                                 cur_symbol->info.rinfo->valid_bitmask = 0xFF;
  321 
  322                         if (cur_symbol->info.rinfo->size == 0)
  323                                 cur_symbol->info.rinfo->size = 1;
  324 
  325                         /*
  326                          * This might be useful for registers too.
  327                          */
  328                         if (cur_symbol->type != REGISTER) {
  329                                 if (cur_symbol->info.rinfo->address == 0)
  330                                         cur_symbol->info.rinfo->address =
  331                                             sram_or_scb_offset;
  332                                 sram_or_scb_offset +=
  333                                     cur_symbol->info.rinfo->size;
  334                         }
  335                         cur_symbol = NULL;
  336                 }
  337 ;
  338 
  339 reg_attribute_list:
  340         reg_attribute
  341 |       reg_attribute_list reg_attribute
  342 ;
  343 
  344 reg_attribute:          
  345         reg_address
  346 |       size
  347 |       access_mode
  348 |       modes
  349 |       field_defn
  350 |       enum_defn
  351 |       mask_defn
  352 |       alias
  353 |       accumulator
  354 |       mode_pointer
  355 |       allones
  356 |       allzeros
  357 |       none
  358 |       sindex
  359 ;
  360 
  361 reg_address:
  362         T_ADDRESS T_NUMBER
  363         {
  364                 cur_symbol->info.rinfo->address = $2;
  365         }
  366 ;
  367 
  368 size:
  369         T_SIZE T_NUMBER
  370         {
  371                 cur_symbol->info.rinfo->size = $2;
  372                 if (scb_or_sram_symbol != NULL) {
  373                         u_int max_addr;
  374                         u_int sym_max_addr;
  375 
  376                         max_addr = scb_or_sram_symbol->info.rinfo->address
  377                                  + scb_or_sram_symbol->info.rinfo->size;
  378                         sym_max_addr = cur_symbol->info.rinfo->address
  379                                      + cur_symbol->info.rinfo->size;
  380 
  381                         if (sym_max_addr > max_addr)
  382                                 stop("SCB or SRAM space exhausted", EX_DATAERR);
  383                 }
  384         }
  385 ;
  386 
  387 access_mode:
  388         T_ACCESS_MODE T_MODE
  389         {
  390                 cur_symbol->info.rinfo->mode = $2;
  391         }
  392 ;
  393 
  394 modes:
  395         T_MODES mode_list
  396         {
  397                 cur_symbol->info.rinfo->modes = $2;
  398         }
  399 ;
  400 
  401 mode_list:
  402         mode_value
  403         {
  404                 $$ = $1;
  405         }
  406 |       mode_list ',' mode_value
  407         {
  408                 $$ = $1 | $3;
  409         }
  410 ;
  411 
  412 mode_value:
  413         T_NUMBER
  414         {
  415                 if ($1 > 4) {
  416                         stop("Valid register modes range between 0 and 4.",
  417                              EX_DATAERR);
  418                         /* NOTREACHED */
  419                 }
  420 
  421                 $$ = (0x1 << $1);
  422         }
  423 |       T_SYMBOL
  424         {
  425                 symbol_t *symbol;
  426 
  427                 symbol = $1;
  428                 if (symbol->type != CONST) {
  429                         stop("Only \"const\" symbols allowed in "
  430                              "mode definitions.", EX_DATAERR);
  431                         /* NOTREACHED */
  432                 }
  433                 if (symbol->info.cinfo->value > 4) {
  434                         stop("Valid register modes range between 0 and 4.",
  435                              EX_DATAERR);
  436                         /* NOTREACHED */
  437                 }
  438                 $$ = (0x1 << symbol->info.cinfo->value);
  439         }
  440 ;
  441 
  442 field_defn:
  443         T_FIELD
  444                 {
  445                         field_symbol = NULL;
  446                         enum_next_value = 0;
  447                         enum_increment = 1;
  448                 }
  449         '{' enum_entry_list '}'
  450 |       T_FIELD T_SYMBOL expression
  451                 {
  452                         process_field(FIELD, $2, $3.value);
  453                         field_symbol = $2;
  454                         enum_next_value = 0;
  455                         enum_increment = 0x01 << (ffs($3.value) - 1);
  456                 }
  457         '{' enum_entry_list '}'
  458 |       T_FIELD T_SYMBOL expression
  459         {
  460                 process_field(FIELD, $2, $3.value);
  461         }
  462 ;
  463 
  464 enum_defn:
  465         T_ENUM
  466                 {
  467                         field_symbol = NULL;
  468                         enum_next_value = 0;
  469                         enum_increment = 1;
  470                 }
  471         '{' enum_entry_list '}'
  472 |       T_ENUM T_SYMBOL expression
  473                 {
  474                         process_field(ENUM, $2, $3.value);
  475                         field_symbol = $2;
  476                         enum_next_value = 0;
  477                         enum_increment = 0x01 << (ffs($3.value) - 1);
  478                 }
  479         '{' enum_entry_list '}'
  480 ;
  481 
  482 enum_entry_list:
  483         enum_entry
  484 |       enum_entry_list ',' enum_entry
  485 ;
  486 
  487 enum_entry:
  488         T_SYMBOL
  489         {
  490                 process_field(ENUM_ENTRY, $1, enum_next_value);
  491                 enum_next_value += enum_increment;
  492         }
  493 |       T_SYMBOL expression
  494         {
  495                 process_field(ENUM_ENTRY, $1, $2.value);
  496                 enum_next_value = $2.value + enum_increment;
  497         }
  498 ;
  499 
  500 mask_defn:
  501         T_MASK T_SYMBOL expression
  502         {
  503                 process_field(MASK, $2, $3.value);
  504         }
  505 ;
  506 
  507 alias:
  508         T_ALIAS T_SYMBOL
  509         {
  510                 if ($2->type != UNINITIALIZED) {
  511                         stop("Re-definition of register alias",
  512                              EX_DATAERR);
  513                         /* NOTREACHED */
  514                 }
  515                 $2->type = ALIAS;
  516                 initialize_symbol($2);
  517                 $2->info.ainfo->parent = cur_symbol;
  518         }
  519 ;
  520 
  521 accumulator:
  522         T_ACCUM
  523         {
  524                 if (accumulator.symbol != NULL) {
  525                         stop("Only one accumulator definition allowed",
  526                              EX_DATAERR);
  527                         /* NOTREACHED */
  528                 }
  529                 accumulator.symbol = cur_symbol;
  530         }
  531 ;
  532 
  533 mode_pointer:
  534         T_MODE_PTR
  535         {
  536                 if (mode_ptr.symbol != NULL) {
  537                         stop("Only one mode pointer definition allowed",
  538                              EX_DATAERR);
  539                         /* NOTREACHED */
  540                 }
  541                 mode_ptr.symbol = cur_symbol;
  542         }
  543 ;
  544 
  545 allones:
  546         T_ALLONES
  547         {
  548                 if (allones.symbol != NULL) {
  549                         stop("Only one definition of allones allowed",
  550                              EX_DATAERR);
  551                         /* NOTREACHED */
  552                 }
  553                 allones.symbol = cur_symbol;
  554         }
  555 ;
  556 
  557 allzeros:
  558         T_ALLZEROS
  559         {
  560                 if (allzeros.symbol != NULL) {
  561                         stop("Only one definition of allzeros allowed",
  562                              EX_DATAERR);
  563                         /* NOTREACHED */
  564                 }
  565                 allzeros.symbol = cur_symbol;
  566         }
  567 ;
  568 
  569 none:
  570         T_NONE
  571         {
  572                 if (none.symbol != NULL) {
  573                         stop("Only one definition of none allowed",
  574                              EX_DATAERR);
  575                         /* NOTREACHED */
  576                 }
  577                 none.symbol = cur_symbol;
  578         }
  579 ;
  580 
  581 sindex:
  582         T_SINDEX
  583         {
  584                 if (sindex.symbol != NULL) {
  585                         stop("Only one definition of sindex allowed",
  586                              EX_DATAERR);
  587                         /* NOTREACHED */
  588                 }
  589                 sindex.symbol = cur_symbol;
  590         }
  591 ;
  592 
  593 expression:
  594         expression '|' expression
  595         {
  596                  $$.value = $1.value | $3.value;
  597                  symlist_merge(&$$.referenced_syms,
  598                                &$1.referenced_syms,
  599                                &$3.referenced_syms);
  600         }
  601 |       expression '&' expression
  602         {
  603                 $$.value = $1.value & $3.value;
  604                 symlist_merge(&$$.referenced_syms,
  605                                &$1.referenced_syms,
  606                                &$3.referenced_syms);
  607         }
  608 |       expression '+' expression
  609         {
  610                 $$.value = $1.value + $3.value;
  611                 symlist_merge(&$$.referenced_syms,
  612                                &$1.referenced_syms,
  613                                &$3.referenced_syms);
  614         }
  615 |       expression '-' expression
  616         {
  617                 $$.value = $1.value - $3.value;
  618                 symlist_merge(&($$.referenced_syms),
  619                                &($1.referenced_syms),
  620                                &($3.referenced_syms));
  621         }
  622 |       expression '*' expression
  623         {
  624                 $$.value = $1.value * $3.value;
  625                 symlist_merge(&($$.referenced_syms),
  626                                &($1.referenced_syms),
  627                                &($3.referenced_syms));
  628         }
  629 |       expression '/' expression
  630         {
  631                 $$.value = $1.value / $3.value;
  632                 symlist_merge(&($$.referenced_syms),
  633                                &($1.referenced_syms),
  634                                &($3.referenced_syms));
  635         }
  636 |       expression T_EXPR_LSHIFT expression
  637         {
  638                 $$.value = $1.value << $3.value;
  639                 symlist_merge(&$$.referenced_syms,
  640                                &$1.referenced_syms,
  641                                &$3.referenced_syms);
  642         }
  643 |       expression T_EXPR_RSHIFT expression
  644         {
  645                 $$.value = $1.value >> $3.value;
  646                 symlist_merge(&$$.referenced_syms,
  647                                &$1.referenced_syms,
  648                                &$3.referenced_syms);
  649         }
  650 |       '(' expression ')'
  651         {
  652                 $$ = $2;
  653         }
  654 |       '~' expression
  655         {
  656                 $$ = $2;
  657                 $$.value = (~$$.value) & 0xFF;
  658         }
  659 |       '-' expression %prec UMINUS
  660         {
  661                 $$ = $2;
  662                 $$.value = -$$.value;
  663         }
  664 |       T_NUMBER
  665         {
  666                 $$.value = $1;
  667                 SLIST_INIT(&$$.referenced_syms);
  668         }
  669 |       T_SYMBOL
  670         {
  671                 symbol_t *symbol;
  672 
  673                 symbol = $1;
  674                 switch (symbol->type) {
  675                 case ALIAS:
  676                         symbol = $1->info.ainfo->parent;
  677                 case REGISTER:
  678                 case SCBLOC:
  679                 case SRAMLOC:
  680                         $$.value = symbol->info.rinfo->address;
  681                         break;
  682                 case MASK:
  683                 case FIELD:
  684                 case ENUM:
  685                 case ENUM_ENTRY:
  686                         $$.value = symbol->info.finfo->value;
  687                         break;
  688                 case DOWNLOAD_CONST:
  689                 case CONST:
  690                         $$.value = symbol->info.cinfo->value;
  691                         break;
  692                 case UNINITIALIZED:
  693                 default:
  694                 {
  695                         snprintf(errbuf, sizeof(errbuf),
  696                                  "Undefined symbol %s referenced",
  697                                  symbol->name);
  698                         stop(errbuf, EX_DATAERR);
  699                         /* NOTREACHED */
  700                         break;
  701                 }
  702                 }
  703                 SLIST_INIT(&$$.referenced_syms);
  704                 symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD);
  705         }
  706 ;
  707 
  708 constant:
  709         T_CONST T_SYMBOL expression 
  710         {
  711                 if ($2->type != UNINITIALIZED) {
  712                         stop("Re-definition of symbol as a constant",
  713                              EX_DATAERR);
  714                         /* NOTREACHED */
  715                 }
  716                 $2->type = CONST;
  717                 initialize_symbol($2);
  718                 $2->info.cinfo->value = $3.value;
  719         }
  720 |       T_CONST T_SYMBOL T_DOWNLOAD
  721         {
  722                 if ($1) {
  723                         stop("Invalid downloaded constant declaration",
  724                              EX_DATAERR);
  725                         /* NOTREACHED */
  726                 }
  727                 if ($2->type != UNINITIALIZED) {
  728                         stop("Re-definition of symbol as a downloaded constant",
  729                              EX_DATAERR);
  730                         /* NOTREACHED */
  731                 }
  732                 $2->type = DOWNLOAD_CONST;
  733                 initialize_symbol($2);
  734                 $2->info.cinfo->value = download_constant_count++;
  735         }
  736 ;
  737 
  738 macrodefn_prologue:
  739         T_DEFINE T_SYMBOL
  740         {
  741                 if ($2->type != UNINITIALIZED) {
  742                         stop("Re-definition of symbol as a macro",
  743                              EX_DATAERR);
  744                         /* NOTREACHED */
  745                 }
  746                 cur_symbol = $2;
  747                 cur_symbol->type = MACRO;
  748                 initialize_symbol(cur_symbol);
  749         }
  750 ;
  751 
  752 macrodefn:
  753         macrodefn_prologue T_MACROBODY
  754         {
  755                 add_macro_body($2);
  756         }
  757 |       macrodefn_prologue '(' macro_arglist ')' T_MACROBODY
  758         {
  759                 add_macro_body($5);
  760                 cur_symbol->info.macroinfo->narg = $3;
  761         }
  762 ;
  763 
  764 macro_arglist:
  765         {
  766                 /* Macros can take no arguments */
  767                 $$ = 0;
  768         }
  769 |       T_ARG
  770         {
  771                 $$ = 1;
  772                 add_macro_arg($1, 0);
  773         }
  774 |       macro_arglist ',' T_ARG
  775         {
  776                 if ($1 == 0) {
  777                         stop("Comma without preceding argument in arg list",
  778                              EX_DATAERR);
  779                         /* NOTREACHED */
  780                 }
  781                 $$ = $1 + 1;
  782                 add_macro_arg($3, $1);
  783         }
  784 ;
  785 
  786 scratch_ram:
  787         T_SRAM '{'
  788                 {
  789                         snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME,
  790                                  num_srams);
  791                         cur_symbol = symtable_get(SRAM_SYMNAME);
  792                         cur_symtype = SRAMLOC;
  793                         cur_symbol->type = SRAMLOC;
  794                         initialize_symbol(cur_symbol);
  795                 }
  796                 reg_address
  797                 {
  798                         sram_or_scb_offset = cur_symbol->info.rinfo->address;
  799                 }
  800                 size
  801                 {
  802                         scb_or_sram_symbol = cur_symbol;
  803                 }
  804                 scb_or_sram_attributes
  805         '}'
  806                 {
  807                         cur_symbol = NULL;
  808                         scb_or_sram_symbol = NULL;
  809                 }
  810 ;
  811 
  812 scb:
  813         T_SCB '{'
  814                 {
  815                         cur_symbol = symtable_get(SCB_SYMNAME);
  816                         cur_symtype = SCBLOC;
  817                         if (cur_symbol->type != UNINITIALIZED) {
  818                                 stop("Only one SRAM definition allowed",
  819                                      EX_SOFTWARE);
  820                                 /* NOTREACHED */
  821                         }
  822                         cur_symbol->type = SCBLOC;
  823                         initialize_symbol(cur_symbol);
  824                         /* 64 bytes of SCB space */
  825                         cur_symbol->info.rinfo->size = 64;
  826                 }
  827                 reg_address
  828                 {
  829                         sram_or_scb_offset = cur_symbol->info.rinfo->address;
  830                 }
  831                 size
  832                 {
  833                         scb_or_sram_symbol = cur_symbol;
  834                 }
  835                 scb_or_sram_attributes
  836         '}'
  837                 {
  838                         cur_symbol = NULL;
  839                         scb_or_sram_symbol = NULL;
  840                 }
  841 ;
  842 
  843 scb_or_sram_attributes:
  844         /* NULL definition is okay */
  845 |       modes
  846 |       scb_or_sram_reg_list
  847 |       modes scb_or_sram_reg_list
  848 ;
  849 
  850 scb_or_sram_reg_list:
  851         reg_definition
  852 |       scb_or_sram_reg_list reg_definition
  853 ;
  854 
  855 reg_symbol:
  856         T_SYMBOL
  857         {
  858                 process_register(&$1);
  859                 $$.symbol = $1;
  860                 $$.offset = 0;
  861         }
  862 |       T_SYMBOL '[' T_SYMBOL ']'
  863         {
  864                 process_register(&$1);
  865                 if ($3->type != CONST) {
  866                         stop("register offset must be a constant", EX_DATAERR);
  867                         /* NOTREACHED */
  868                 }
  869                 if (($3->info.cinfo->value + 1) > (unsigned)$1->info.rinfo->size) {
  870                         stop("Accessing offset beyond range of register",
  871                              EX_DATAERR);
  872                         /* NOTREACHED */
  873                 }
  874                 $$.symbol = $1;
  875                 $$.offset = $3->info.cinfo->value;
  876         }
  877 |       T_SYMBOL '[' T_NUMBER ']'
  878         {
  879                 process_register(&$1);
  880                 if (($3 + 1) > (unsigned)$1->info.rinfo->size) {
  881                         stop("Accessing offset beyond range of register",
  882                              EX_DATAERR);
  883                         /* NOTREACHED */
  884                 }
  885                 $$.symbol = $1;
  886                 $$.offset = $3;
  887         }
  888 |       T_A
  889         {
  890                 if (accumulator.symbol == NULL) {
  891                         stop("No accumulator has been defined", EX_DATAERR);
  892                         /* NOTREACHED */
  893                 }
  894                 $$.symbol = accumulator.symbol;
  895                 $$.offset = 0;
  896         }
  897 ;
  898 
  899 destination:
  900         reg_symbol
  901         {
  902                 test_writable_symbol($1.symbol);
  903                 $$ = $1;
  904         }
  905 ;
  906 
  907 immediate:
  908         expression
  909         { $$ = $1; }
  910 ;
  911 
  912 immediate_or_a:
  913         expression
  914         {
  915                 if ($1.value == 0 && is_download_const(&$1) == 0) {
  916                         snprintf(errbuf, sizeof(errbuf),
  917                                  "\nExpression evaluates to 0 and thus "
  918                                  "references the accumulator.\n "
  919                                  "If this is the desired effect, use 'A' "
  920                                  "instead.\n");
  921                         stop(errbuf, EX_DATAERR);
  922                 }
  923                 $$ = $1;
  924         }
  925 |       T_A
  926         {
  927                 SLIST_INIT(&$$.referenced_syms);
  928                 symlist_add(&$$.referenced_syms, accumulator.symbol,
  929                             SYMLIST_INSERT_HEAD);
  930                 $$.value = 0;
  931         }
  932 ;
  933 
  934 source:
  935         reg_symbol
  936         {
  937                 test_readable_symbol($1.symbol);
  938                 $$ = $1;
  939         }
  940 ;
  941 
  942 opt_source:
  943         {
  944                 $$.symbol = NULL;
  945                 $$.offset = 0;
  946         }
  947 |       ',' source
  948         { $$ = $2; }
  949 ;
  950 
  951 ret:
  952         { $$ = 0; }
  953 |       T_RET
  954         { $$ = 1; }
  955 ;
  956 
  957 set_src_mode:
  958         T_SET_SRC_MODE T_NUMBER ';'
  959         {
  960                 src_mode = $2;
  961         }
  962 ;
  963 
  964 set_dst_mode:
  965         T_SET_DST_MODE T_NUMBER ';'
  966         {
  967                 dst_mode = $2;
  968         }
  969 ;
  970 
  971 critical_section_start:
  972         T_BEGIN_CS ';'
  973         {
  974                 critical_section_t *cs;
  975 
  976                 if (in_critical_section != FALSE) {
  977                         stop("Critical Section within Critical Section",
  978                              EX_DATAERR);
  979                         /* NOTREACHED */
  980                 }
  981                 cs = cs_alloc();
  982                 cs->begin_addr = instruction_ptr;
  983                 in_critical_section = TRUE;
  984         }
  985 ;
  986 
  987 critical_section_end:
  988         T_END_CS ';'
  989         {
  990                 critical_section_t *cs;
  991 
  992                 if (in_critical_section == FALSE) {
  993                         stop("Unballanced 'end_cs'", EX_DATAERR);
  994                         /* NOTREACHED */
  995                 }
  996                 cs = TAILQ_LAST(&cs_tailq, cs_tailq);
  997                 cs->end_addr = instruction_ptr;
  998                 in_critical_section = FALSE;
  999         }
 1000 ;
 1001 
 1002 export:
 1003         { $$ = 0; }
 1004 |       T_EXPORT
 1005         { $$ = 1; }
 1006 ;
 1007 
 1008 label:
 1009         export T_SYMBOL ':'
 1010         {
 1011                 if ($2->type != UNINITIALIZED) {
 1012                         stop("Program label multiply defined", EX_DATAERR);
 1013                         /* NOTREACHED */
 1014                 }
 1015                 $2->type = LABEL;
 1016                 initialize_symbol($2);
 1017                 $2->info.linfo->address = instruction_ptr;
 1018                 $2->info.linfo->exported = $1;
 1019         }
 1020 ;
 1021 
 1022 address:
 1023         T_SYMBOL
 1024         {
 1025                 $$.symbol = $1;
 1026                 $$.offset = 0;
 1027         }
 1028 |       T_SYMBOL '+' T_NUMBER
 1029         {
 1030                 $$.symbol = $1;
 1031                 $$.offset = $3;
 1032         }
 1033 |       T_SYMBOL '-' T_NUMBER
 1034         {
 1035                 $$.symbol = $1;
 1036                 $$.offset = -$3;
 1037         }
 1038 |       '.'
 1039         {
 1040                 $$.symbol = NULL;
 1041                 $$.offset = 0;
 1042         }
 1043 |       '.' '+' T_NUMBER
 1044         {
 1045                 $$.symbol = NULL;
 1046                 $$.offset = $3;
 1047         }
 1048 |       '.' '-' T_NUMBER
 1049         {
 1050                 $$.symbol = NULL;
 1051                 $$.offset = -$3;
 1052         }
 1053 ;
 1054 
 1055 conditional:
 1056         T_IF T_CEXPR '{'
 1057         {
 1058                 scope_t *new_scope;
 1059 
 1060                 add_conditional($2);
 1061                 new_scope = scope_alloc();
 1062                 new_scope->type = SCOPE_IF;
 1063                 new_scope->begin_addr = instruction_ptr;
 1064                 new_scope->func_num = $2->info.condinfo->func_num;
 1065         }
 1066 |       T_ELSE T_IF T_CEXPR '{'
 1067         {
 1068                 scope_t *new_scope;
 1069                 scope_t *scope_context;
 1070                 scope_t *last_scope;
 1071 
 1072                 /*
 1073                  * Ensure that the previous scope is either an
 1074                  * if or and else if.
 1075                  */
 1076                 scope_context = SLIST_FIRST(&scope_stack);
 1077                 last_scope = TAILQ_LAST(&scope_context->inner_scope,
 1078                                         scope_tailq);
 1079                 if (last_scope == NULL
 1080                  || last_scope->type == SCOPE_ELSE) {
 1081 
 1082                         stop("'else if' without leading 'if'", EX_DATAERR);
 1083                         /* NOTREACHED */
 1084                 }
 1085                 add_conditional($3);
 1086                 new_scope = scope_alloc();
 1087                 new_scope->type = SCOPE_ELSE_IF;
 1088                 new_scope->begin_addr = instruction_ptr;
 1089                 new_scope->func_num = $3->info.condinfo->func_num;
 1090         }
 1091 |       T_ELSE '{'
 1092         {
 1093                 scope_t *new_scope;
 1094                 scope_t *scope_context;
 1095                 scope_t *last_scope;
 1096 
 1097                 /*
 1098                  * Ensure that the previous scope is either an
 1099                  * if or and else if.
 1100                  */
 1101                 scope_context = SLIST_FIRST(&scope_stack);
 1102                 last_scope = TAILQ_LAST(&scope_context->inner_scope,
 1103                                         scope_tailq);
 1104                 if (last_scope == NULL
 1105                  || last_scope->type == SCOPE_ELSE) {
 1106 
 1107                         stop("'else' without leading 'if'", EX_DATAERR);
 1108                         /* NOTREACHED */
 1109                 }
 1110                 new_scope = scope_alloc();
 1111                 new_scope->type = SCOPE_ELSE;
 1112                 new_scope->begin_addr = instruction_ptr;
 1113         }
 1114 ;
 1115 
 1116 conditional:
 1117         '}'
 1118         {
 1119                 scope_t *scope_context;
 1120 
 1121                 scope_context = SLIST_FIRST(&scope_stack);
 1122                 if (scope_context->type == SCOPE_ROOT) {
 1123                         stop("Unexpected '}' encountered", EX_DATAERR);
 1124                         /* NOTREACHED */
 1125                 }
 1126 
 1127                 scope_context->end_addr = instruction_ptr;
 1128 
 1129                 /* Pop the scope */
 1130                 SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
 1131 
 1132                 process_scope(scope_context);
 1133 
 1134                 if (SLIST_FIRST(&scope_stack) == NULL) {
 1135                         stop("Unexpected '}' encountered", EX_DATAERR);
 1136                         /* NOTREACHED */
 1137                 }
 1138         }
 1139 ;
 1140 
 1141 f1_opcode:
 1142         T_AND { $$ = AIC_OP_AND; }
 1143 |       T_XOR { $$ = AIC_OP_XOR; }
 1144 |       T_ADD { $$ = AIC_OP_ADD; }
 1145 |       T_ADC { $$ = AIC_OP_ADC; }
 1146 ;
 1147 
 1148 code:
 1149         f1_opcode destination ',' immediate_or_a opt_source ret ';'
 1150         {
 1151                 format_1_instr($1, &$2, &$4, &$5, $6);
 1152         }
 1153 ;
 1154 
 1155 code:
 1156         T_OR reg_symbol ',' immediate_or_a opt_source ret ';'
 1157         {
 1158                 format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6);
 1159         }
 1160 ;
 1161 
 1162 code:
 1163         T_INC destination opt_source ret ';'
 1164         {
 1165                 expression_t immed;
 1166 
 1167                 make_expression(&immed, 1);
 1168                 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
 1169         }
 1170 ;
 1171 
 1172 code:
 1173         T_DEC destination opt_source ret ';'
 1174         {
 1175                 expression_t immed;
 1176 
 1177                 make_expression(&immed, -1);
 1178                 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
 1179         }
 1180 ;
 1181 
 1182 code:
 1183         T_CLC ret ';'
 1184         {
 1185                 expression_t immed;
 1186 
 1187                 make_expression(&immed, -1);
 1188                 format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2);
 1189         }
 1190 |       T_CLC T_MVI destination ',' immediate_or_a ret ';'
 1191         {
 1192                 format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6);
 1193         }
 1194 ;
 1195 
 1196 code:
 1197         T_STC ret ';'
 1198         {
 1199                 expression_t immed;
 1200 
 1201                 make_expression(&immed, 1);
 1202                 format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2);
 1203         }
 1204 |       T_STC destination ret ';'
 1205         {
 1206                 expression_t immed;
 1207 
 1208                 make_expression(&immed, 1);
 1209                 format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3);
 1210         }
 1211 ;
 1212 
 1213 code:
 1214         T_BMOV destination ',' source ',' immediate ret ';'
 1215         {
 1216                 format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
 1217         }
 1218 ;
 1219 
 1220 code:
 1221         T_MOV destination ',' source ret ';'
 1222         {
 1223                 expression_t immed;
 1224 
 1225                 make_expression(&immed, 1);
 1226                 format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5);
 1227         }
 1228 ;
 1229 
 1230 code:
 1231         T_MVI destination ',' immediate ret ';'
 1232         {
 1233                 if ($4.value == 0
 1234                  && is_download_const(&$4) == 0) {
 1235                         expression_t immed;
 1236 
 1237                         /*
 1238                          * Allow move immediates of 0 so that macros,
 1239                          * that can't know the immediate's value and
 1240                          * otherwise compensate, still work.
 1241                          */
 1242                         make_expression(&immed, 1);
 1243                         format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5);
 1244                 } else {
 1245                         format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
 1246                 }
 1247         }
 1248 ;
 1249 
 1250 code:
 1251         T_NOT destination opt_source ret ';'
 1252         {
 1253                 expression_t immed;
 1254 
 1255                 make_expression(&immed, 0xff);
 1256                 format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4);
 1257         }
 1258 ;
 1259 
 1260 code:
 1261         T_CLR destination ret ';'
 1262         {
 1263                 expression_t immed;
 1264 
 1265                 make_expression(&immed, 0xff);
 1266                 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3);
 1267         }
 1268 ;
 1269 
 1270 code:
 1271         T_NOP ret ';'
 1272         {
 1273                 expression_t immed;
 1274 
 1275                 make_expression(&immed, 0xff);
 1276                 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2);
 1277         }
 1278 ;
 1279 
 1280 code:
 1281         T_RET ';'
 1282         {
 1283                 expression_t immed;
 1284 
 1285                 make_expression(&immed, 0xff);
 1286                 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE);
 1287         }
 1288 ;
 1289 
 1290         /*
 1291          * This grammar differs from the one in the aic7xxx
 1292          * reference manual since the grammar listed there is
 1293          * ambiguous and causes a shift/reduce conflict.
 1294          * It also seems more logical as the "immediate"
 1295          * argument is listed as the second arg like the
 1296          * other formats.
 1297          */
 1298 
 1299 f2_opcode:
 1300         T_SHL { $$ = AIC_OP_SHL; }
 1301 |       T_SHR { $$ = AIC_OP_SHR; }
 1302 |       T_ROL { $$ = AIC_OP_ROL; }
 1303 |       T_ROR { $$ = AIC_OP_ROR; }
 1304 ;
 1305 
 1306 code:
 1307         f2_opcode destination ',' expression opt_source ret ';'
 1308         {
 1309                 format_2_instr($1, &$2, &$4, &$5, $6);
 1310         }
 1311 ;
 1312 
 1313 jmp_jc_jnc_call:
 1314         T_JMP   { $$ = AIC_OP_JMP; }
 1315 |       T_JC    { $$ = AIC_OP_JC; }
 1316 |       T_JNC   { $$ = AIC_OP_JNC; }
 1317 |       T_CALL  { $$ = AIC_OP_CALL; }
 1318 ;
 1319 
 1320 jz_jnz:
 1321         T_JZ    { $$ = AIC_OP_JZ; }
 1322 |       T_JNZ   { $$ = AIC_OP_JNZ; }
 1323 ;
 1324 
 1325 je_jne:
 1326         T_JE    { $$ = AIC_OP_JE; }
 1327 |       T_JNE   { $$ = AIC_OP_JNE; }
 1328 ;
 1329 
 1330 code:
 1331         jmp_jc_jnc_call address ';'
 1332         {
 1333                 expression_t immed;
 1334 
 1335                 make_expression(&immed, 0);
 1336                 format_3_instr($1, &sindex, &immed, &$2);
 1337         }
 1338 ;
 1339 
 1340 code:
 1341         T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
 1342         {
 1343                 format_3_instr($5, &$2, &$4, &$6);
 1344         }
 1345 ;
 1346 
 1347 code:
 1348         T_TEST source ',' immediate_or_a jz_jnz address ';'
 1349         {
 1350                 format_3_instr($5, &$2, &$4, &$6);
 1351         }
 1352 ;
 1353 
 1354 code:
 1355         T_CMP source ',' immediate_or_a je_jne address ';'
 1356         {
 1357                 format_3_instr($5, &$2, &$4, &$6);
 1358         }
 1359 ;
 1360 
 1361 code:
 1362         T_MOV source jmp_jc_jnc_call address ';'
 1363         {
 1364                 expression_t immed;
 1365 
 1366                 make_expression(&immed, 0);
 1367                 format_3_instr($3, &$2, &immed, &$4);
 1368         }
 1369 ;
 1370 
 1371 code:
 1372         T_MVI immediate jmp_jc_jnc_call address ';'
 1373         {
 1374                 format_3_instr($3, &allzeros, &$2, &$4);
 1375         }
 1376 ;
 1377 
 1378 %%
 1379 
 1380 static void
 1381 process_field(unsigned int field_type, symbol_t *sym, int value)
 1382 {
 1383         /*
 1384          * Add the current register to its
 1385          * symbol list, if it already exists,
 1386          * warn if we are setting it to a
 1387          * different value, or in the bit to
 1388          * the "allowed bits" of this register.
 1389          */
 1390         if (sym->type == UNINITIALIZED) {
 1391                 sym->type = field_type;
 1392                 initialize_symbol(sym);
 1393                 sym->info.finfo->value = value;
 1394                 if (field_type != ENUM_ENTRY) {
 1395                         if (field_type != MASK && value == 0) {
 1396                                 stop("Empty Field, or Enum", EX_DATAERR);
 1397                                 /* NOTREACHED */
 1398                         }
 1399                         sym->info.finfo->value = value;
 1400                         sym->info.finfo->mask = value;
 1401                 } else if (field_symbol != NULL) {
 1402                         sym->info.finfo->mask = field_symbol->info.finfo->value;
 1403                 } else {
 1404                         sym->info.finfo->mask = 0xFF;
 1405                 }
 1406         } else if (sym->type != field_type) {
 1407                 stop("Field definition mirrors a definition of the same "
 1408                      " name, but a different type", EX_DATAERR);
 1409                 /* NOTREACHED */
 1410         } else if (value != sym->info.finfo->value) {
 1411                 stop("Field redefined with a conflicting value", EX_DATAERR);
 1412                 /* NOTREACHED */
 1413         }
 1414         /* Fail if this symbol is already listed */
 1415         if (symlist_search(&(sym->info.finfo->symrefs),
 1416                            cur_symbol->name) != NULL) {
 1417                 stop("Field defined multiple times for register", EX_DATAERR);
 1418                 /* NOTREACHED */
 1419         }
 1420         symlist_add(&(sym->info.finfo->symrefs), cur_symbol,
 1421                     SYMLIST_INSERT_HEAD);
 1422         cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask;
 1423         cur_symbol->info.rinfo->typecheck_masks = TRUE;
 1424         symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT);
 1425 }
 1426 
 1427 static void
 1428 initialize_symbol(symbol_t *symbol)
 1429 {
 1430         switch (symbol->type) {
 1431         case UNINITIALIZED:
 1432                 stop("Call to initialize_symbol with type field unset",
 1433                      EX_SOFTWARE);
 1434                 /* NOTREACHED */
 1435                 break;
 1436         case REGISTER:
 1437         case SRAMLOC:
 1438         case SCBLOC:
 1439                 symbol->info.rinfo =
 1440                     (struct reg_info *)malloc(sizeof(struct reg_info));
 1441                 if (symbol->info.rinfo == NULL) {
 1442                         stop("Can't create register info", EX_SOFTWARE);
 1443                         /* NOTREACHED */
 1444                 }
 1445                 memset(symbol->info.rinfo, 0,
 1446                        sizeof(struct reg_info));
 1447                 SLIST_INIT(&(symbol->info.rinfo->fields));
 1448                 /*
 1449                  * Default to allowing access in all register modes
 1450                  * or to the mode specified by the SCB or SRAM space
 1451                  * we are in.
 1452                  */
 1453                 if (scb_or_sram_symbol != NULL)
 1454                         symbol->info.rinfo->modes =
 1455                             scb_or_sram_symbol->info.rinfo->modes;
 1456                 else
 1457                         symbol->info.rinfo->modes = ~0;
 1458                 break;
 1459         case ALIAS:
 1460                 symbol->info.ainfo =
 1461                     (struct alias_info *)malloc(sizeof(struct alias_info));
 1462                 if (symbol->info.ainfo == NULL) {
 1463                         stop("Can't create alias info", EX_SOFTWARE);
 1464                         /* NOTREACHED */
 1465                 }
 1466                 memset(symbol->info.ainfo, 0,
 1467                        sizeof(struct alias_info));
 1468                 break;
 1469         case MASK:
 1470         case FIELD:
 1471         case ENUM:
 1472         case ENUM_ENTRY:
 1473                 symbol->info.finfo =
 1474                     (struct field_info *)malloc(sizeof(struct field_info));
 1475                 if (symbol->info.finfo == NULL) {
 1476                         stop("Can't create field info", EX_SOFTWARE);
 1477                         /* NOTREACHED */
 1478                 }
 1479                 memset(symbol->info.finfo, 0, sizeof(struct field_info));
 1480                 SLIST_INIT(&(symbol->info.finfo->symrefs));
 1481                 break;
 1482         case CONST:
 1483         case DOWNLOAD_CONST:
 1484                 symbol->info.cinfo =
 1485                     (struct const_info *)malloc(sizeof(struct const_info));
 1486                 if (symbol->info.cinfo == NULL) {
 1487                         stop("Can't create alias info", EX_SOFTWARE);
 1488                         /* NOTREACHED */
 1489                 }
 1490                 memset(symbol->info.cinfo, 0,
 1491                        sizeof(struct const_info));
 1492                 break;
 1493         case LABEL:
 1494                 symbol->info.linfo =
 1495                     (struct label_info *)malloc(sizeof(struct label_info));
 1496                 if (symbol->info.linfo == NULL) {
 1497                         stop("Can't create label info", EX_SOFTWARE);
 1498                         /* NOTREACHED */
 1499                 }
 1500                 memset(symbol->info.linfo, 0,
 1501                        sizeof(struct label_info));
 1502                 break;
 1503         case CONDITIONAL:
 1504                 symbol->info.condinfo =
 1505                     (struct cond_info *)malloc(sizeof(struct cond_info));
 1506                 if (symbol->info.condinfo == NULL) {
 1507                         stop("Can't create conditional info", EX_SOFTWARE);
 1508                         /* NOTREACHED */
 1509                 }
 1510                 memset(symbol->info.condinfo, 0,
 1511                        sizeof(struct cond_info));
 1512                 break;
 1513         case MACRO:
 1514                 symbol->info.macroinfo = 
 1515                     (struct macro_info *)malloc(sizeof(struct macro_info));
 1516                 if (symbol->info.macroinfo == NULL) {
 1517                         stop("Can't create macro info", EX_SOFTWARE);
 1518                         /* NOTREACHED */
 1519                 }
 1520                 memset(symbol->info.macroinfo, 0,
 1521                        sizeof(struct macro_info));
 1522                 STAILQ_INIT(&symbol->info.macroinfo->args);
 1523                 break;
 1524         default:
 1525                 stop("Call to initialize_symbol with invalid symbol type",
 1526                      EX_SOFTWARE);
 1527                 /* NOTREACHED */
 1528                 break;
 1529         }
 1530 }
 1531 
 1532 static void
 1533 add_macro_arg(const char *argtext, int argnum __unused)
 1534 {
 1535         struct macro_arg *marg;
 1536         int retval;
 1537                 
 1538 
 1539         if (cur_symbol == NULL || cur_symbol->type != MACRO) {
 1540                 stop("Invalid current symbol for adding macro arg",
 1541                      EX_SOFTWARE);
 1542                 /* NOTREACHED */
 1543         }
 1544 
 1545         marg = (struct macro_arg *)malloc(sizeof(*marg));
 1546         if (marg == NULL) {
 1547                 stop("Can't create macro_arg structure", EX_SOFTWARE);
 1548                 /* NOTREACHED */
 1549         }
 1550         marg->replacement_text = NULL;
 1551         retval = snprintf(regex_pattern, sizeof(regex_pattern),
 1552                           "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)",
 1553                           argtext);
 1554         if (retval >= (int)sizeof(regex_pattern)) {
 1555                 stop("Regex text buffer too small for arg",
 1556                      EX_SOFTWARE);
 1557                 /* NOTREACHED */
 1558         }
 1559         retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED);
 1560         if (retval != 0) {
 1561                 stop("Regex compilation failed", EX_SOFTWARE);
 1562                 /* NOTREACHED */
 1563         }
 1564         STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links);
 1565 }
 1566 
 1567 static void
 1568 add_macro_body(const char *bodytext)
 1569 {
 1570         if (cur_symbol == NULL || cur_symbol->type != MACRO) {
 1571                 stop("Invalid current symbol for adding macro arg",
 1572                      EX_SOFTWARE);
 1573                 /* NOTREACHED */
 1574         }
 1575         cur_symbol->info.macroinfo->body = strdup(bodytext);
 1576         if (cur_symbol->info.macroinfo->body == NULL) {
 1577                 stop("Can't duplicate macro body text", EX_SOFTWARE);
 1578                 /* NOTREACHED */
 1579         }
 1580 }
 1581 
 1582 static void
 1583 process_register(symbol_t **p_symbol)
 1584 {
 1585         symbol_t *symbol = *p_symbol;
 1586 
 1587         if (symbol->type == UNINITIALIZED) {
 1588                 snprintf(errbuf, sizeof(errbuf), "Undefined register %s",
 1589                          symbol->name);
 1590                 stop(errbuf, EX_DATAERR);
 1591                 /* NOTREACHED */
 1592         } else if (symbol->type == ALIAS) {
 1593                 *p_symbol = symbol->info.ainfo->parent;
 1594         } else if ((symbol->type != REGISTER)
 1595                 && (symbol->type != SCBLOC)
 1596                 && (symbol->type != SRAMLOC)) {
 1597                 snprintf(errbuf, sizeof(errbuf),
 1598                          "Specified symbol %s is not a register",
 1599                          symbol->name);
 1600                 stop(errbuf, EX_DATAERR);
 1601         }
 1602 }
 1603 
 1604 static void
 1605 format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
 1606                symbol_ref_t *src, int ret)
 1607 {
 1608         struct instruction *instr;
 1609         struct ins_format1 *f1_instr;
 1610 
 1611         if (src->symbol == NULL)
 1612                 src = dest;
 1613 
 1614         /* Test register permissions */
 1615         test_writable_symbol(dest->symbol);
 1616         test_readable_symbol(src->symbol);
 1617 
 1618         /* Ensure that immediate makes sense for this destination */
 1619         type_check(dest->symbol, immed, opcode);
 1620 
 1621         /* Allocate sequencer space for the instruction and fill it out */
 1622         instr = seq_alloc();
 1623         f1_instr = &instr->format.format1;
 1624         f1_instr->ret = ret ? 1 : 0;
 1625         f1_instr->opcode = opcode;
 1626         f1_instr->destination = dest->symbol->info.rinfo->address
 1627                               + dest->offset;
 1628         f1_instr->source = src->symbol->info.rinfo->address
 1629                          + src->offset;
 1630         f1_instr->immediate = immed->value;
 1631 
 1632         if (is_download_const(immed))
 1633                 f1_instr->parity = 1;
 1634         else if (dest->symbol == mode_ptr.symbol) {
 1635                 u_int src_value;
 1636                 u_int dst_value;
 1637 
 1638                 /*
 1639                  * Attempt to update mode information if
 1640                  * we are operating on the mode register.
 1641                  */
 1642                 if (src->symbol == allones.symbol)
 1643                         src_value = 0xFF;
 1644                 else if (src->symbol == allzeros.symbol)
 1645                         src_value = 0;
 1646                 else if (src->symbol == mode_ptr.symbol)
 1647                         src_value = (dst_mode << 4) | src_mode;
 1648                 else
 1649                         goto cant_update;
 1650 
 1651                 switch (opcode) {
 1652                 case AIC_OP_AND:
 1653                         dst_value = src_value & immed->value;
 1654                         break;
 1655                 case AIC_OP_XOR:
 1656                         dst_value = src_value ^ immed->value;
 1657                         break;
 1658                 case AIC_OP_ADD:
 1659                         dst_value = (src_value + immed->value) & 0xFF;
 1660                         break;
 1661                 case AIC_OP_OR:
 1662                         dst_value = src_value | immed->value;
 1663                         break;
 1664                 case AIC_OP_BMOV:
 1665                         dst_value = src_value;
 1666                         break;
 1667                 default:
 1668                         goto cant_update;
 1669                 }
 1670                 src_mode = dst_value & 0xF;
 1671                 dst_mode = (dst_value >> 4) & 0xF;
 1672         }
 1673 
 1674 cant_update:
 1675         symlist_free(&immed->referenced_syms);
 1676         instruction_ptr++;
 1677 }
 1678 
 1679 static void
 1680 format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places,
 1681                symbol_ref_t *src, int ret)
 1682 {
 1683         struct instruction *instr;
 1684         struct ins_format2 *f2_instr;
 1685         uint8_t shift_control;
 1686 
 1687         if (src->symbol == NULL)
 1688                 src = dest;
 1689 
 1690         /* Test register permissions */
 1691         test_writable_symbol(dest->symbol);
 1692         test_readable_symbol(src->symbol);
 1693 
 1694         /* Allocate sequencer space for the instruction and fill it out */
 1695         instr = seq_alloc();
 1696         f2_instr = &instr->format.format2;
 1697         f2_instr->ret = ret ? 1 : 0;
 1698         f2_instr->opcode = AIC_OP_ROL;
 1699         f2_instr->destination = dest->symbol->info.rinfo->address
 1700                               + dest->offset;
 1701         f2_instr->source = src->symbol->info.rinfo->address
 1702                          + src->offset;
 1703         if (places->value > 8 || places->value <= 0) {
 1704                 stop("illegal shift value", EX_DATAERR);
 1705                 /* NOTREACHED */
 1706         }
 1707         switch (opcode) {
 1708         case AIC_OP_SHL:
 1709                 if (places->value == 8)
 1710                         shift_control = 0xf0;
 1711                 else
 1712                         shift_control = (places->value << 4) | places->value;
 1713                 break;
 1714         case AIC_OP_SHR:
 1715                 if (places->value == 8) {
 1716                         shift_control = 0xf8;
 1717                 } else {
 1718                         shift_control = (places->value << 4)
 1719                                       | (8 - places->value)
 1720                                       | 0x08;
 1721                 }
 1722                 break;
 1723         case AIC_OP_ROL:
 1724                 shift_control = places->value & 0x7;
 1725                 break;
 1726         case AIC_OP_ROR:
 1727                 shift_control = (8 - places->value) | 0x08;
 1728                 break;
 1729         default:
 1730                 shift_control = 0; /* Quiet Compiler */
 1731                 stop("Invalid shift operation specified", EX_SOFTWARE);
 1732                 /* NOTREACHED */
 1733                 break;
 1734         };
 1735         f2_instr->shift_control = shift_control;
 1736         symlist_free(&places->referenced_syms);
 1737         instruction_ptr++;
 1738 }
 1739 
 1740 static void
 1741 format_3_instr(int opcode, symbol_ref_t *src,
 1742                expression_t *immed, symbol_ref_t *address)
 1743 {
 1744         struct instruction *instr;
 1745         struct ins_format3 *f3_instr;
 1746         int addr;
 1747 
 1748         /* Test register permissions */
 1749         test_readable_symbol(src->symbol);
 1750 
 1751         /* Ensure that immediate makes sense for this source */
 1752         type_check(src->symbol, immed, opcode);
 1753 
 1754         /* Allocate sequencer space for the instruction and fill it out */
 1755         instr = seq_alloc();
 1756         f3_instr = &instr->format.format3;
 1757         if (address->symbol == NULL) {
 1758                 /* 'dot' reference.  Use the current instruction pointer */
 1759                 addr = instruction_ptr + address->offset;
 1760         } else if (address->symbol->type == UNINITIALIZED) {
 1761                 /* forward reference */
 1762                 addr = address->offset;
 1763                 instr->patch_label = address->symbol;
 1764         } else
 1765                 addr = address->symbol->info.linfo->address + address->offset;
 1766         f3_instr->opcode = opcode;
 1767         f3_instr->address = addr;
 1768         f3_instr->source = src->symbol->info.rinfo->address
 1769                          + src->offset;
 1770         f3_instr->immediate = immed->value;
 1771 
 1772         if (is_download_const(immed))
 1773                 f3_instr->parity = 1;
 1774 
 1775         symlist_free(&immed->referenced_syms);
 1776         instruction_ptr++;
 1777 }
 1778 
 1779 static void
 1780 test_readable_symbol(symbol_t *symbol)
 1781 {
 1782         
 1783         if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
 1784                 snprintf(errbuf, sizeof(errbuf),
 1785                         "Register %s unavailable in source reg mode %d",
 1786                         symbol->name, src_mode);
 1787                 stop(errbuf, EX_DATAERR);
 1788         }
 1789 
 1790         if (symbol->info.rinfo->mode == WO) {
 1791                 stop("Write Only register specified as source",
 1792                      EX_DATAERR);
 1793                 /* NOTREACHED */
 1794         }
 1795 }
 1796 
 1797 static void
 1798 test_writable_symbol(symbol_t *symbol)
 1799 {
 1800         
 1801         if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
 1802                 snprintf(errbuf, sizeof(errbuf),
 1803                         "Register %s unavailable in destination reg mode %d",
 1804                         symbol->name, dst_mode);
 1805                 stop(errbuf, EX_DATAERR);
 1806         }
 1807 
 1808         if (symbol->info.rinfo->mode == RO) {
 1809                 stop("Read Only register specified as destination",
 1810                      EX_DATAERR);
 1811                 /* NOTREACHED */
 1812         }
 1813 }
 1814 
 1815 static void
 1816 type_check(symbol_t *symbol, expression_t *expression, int opcode)
 1817 {
 1818         symbol_node_t *node;
 1819         int and_op;
 1820         uint8_t invalid_bits;
 1821 
 1822         and_op = FALSE;
 1823         if (opcode == AIC_OP_AND
 1824          || opcode == AIC_OP_BMOV
 1825          || opcode == AIC_OP_JE
 1826          || opcode == AIC_OP_JNE
 1827          || opcode == AIC_OP_JNZ
 1828          || opcode == AIC_OP_JZ)
 1829                 and_op = TRUE;
 1830 
 1831         /*
 1832          * Make sure that we aren't attempting to write something
 1833          * that hasn't been defined.  If this is an and operation,
 1834          * this is a mask, so "undefined" bits are okay.
 1835          */
 1836         invalid_bits = expression->value & ~symbol->info.rinfo->valid_bitmask;
 1837         if (and_op == FALSE && invalid_bits != 0) {
 1838                 snprintf(errbuf, sizeof(errbuf),
 1839                          "Invalid bit(s) 0x%x in immediate written to %s",
 1840                          invalid_bits, symbol->name);
 1841                 stop(errbuf, EX_DATAERR);
 1842                 /* NOTREACHED */
 1843         }
 1844 
 1845         /*
 1846          * Now make sure that all of the symbols referenced by the
 1847          * expression are defined for this register.
 1848          */
 1849         if (symbol->info.rinfo->typecheck_masks != FALSE) {
 1850                 for(node = expression->referenced_syms.slh_first;
 1851                     node != NULL;
 1852                     node = node->links.sle_next) {
 1853                         if ((node->symbol->type == MASK
 1854                           || node->symbol->type == FIELD
 1855                           || node->symbol->type == ENUM
 1856                           || node->symbol->type == ENUM_ENTRY)
 1857                          && symlist_search(&node->symbol->info.finfo->symrefs,
 1858                                            symbol->name) == NULL) {
 1859                                 snprintf(errbuf, sizeof(errbuf),
 1860                                          "Invalid field or mask %s "
 1861                                          "for register %s",
 1862                                          node->symbol->name, symbol->name);
 1863                                 stop(errbuf, EX_DATAERR);
 1864                                 /* NOTREACHED */
 1865                         }
 1866                 }
 1867         }
 1868 }
 1869 
 1870 static void
 1871 make_expression(expression_t *immed, int value)
 1872 {
 1873         SLIST_INIT(&immed->referenced_syms);
 1874         immed->value = value & 0xff;
 1875 }
 1876 
 1877 static void
 1878 add_conditional(symbol_t *symbol)
 1879 {
 1880         static int numfuncs;
 1881 
 1882         if (numfuncs == 0) {
 1883                 /* add a special conditional, "0" */
 1884                 symbol_t *false_func;
 1885 
 1886                 false_func = symtable_get("0");
 1887                 if (false_func->type != UNINITIALIZED) {
 1888                         stop("Conditional expression '0' "
 1889                              "conflicts with a symbol", EX_DATAERR);
 1890                         /* NOTREACHED */
 1891                 }
 1892                 false_func->type = CONDITIONAL;
 1893                 initialize_symbol(false_func);
 1894                 false_func->info.condinfo->func_num = numfuncs++;
 1895                 symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
 1896         }
 1897 
 1898         /* This condition has occurred before */
 1899         if (symbol->type == CONDITIONAL)
 1900                 return;
 1901 
 1902         if (symbol->type != UNINITIALIZED) {
 1903                 stop("Conditional expression conflicts with a symbol",
 1904                      EX_DATAERR);
 1905                 /* NOTREACHED */
 1906         }
 1907 
 1908         symbol->type = CONDITIONAL;
 1909         initialize_symbol(symbol);
 1910         symbol->info.condinfo->func_num = numfuncs++;
 1911         symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
 1912 }
 1913 
 1914 static void
 1915 add_version(const char *verstring)
 1916 {
 1917         const char verprefix[] = " * ";
 1918         int newlen;
 1919         int oldlen;
 1920 
 1921         newlen = strlen(verstring) + strlen(verprefix);
 1922         oldlen = 0;
 1923         if (versions != NULL)
 1924                 oldlen = strlen(versions);
 1925         versions = realloc(versions, newlen + oldlen + 2);
 1926         if (versions == NULL)
 1927                 stop("Can't allocate version string", EX_SOFTWARE);
 1928         strcpy(&versions[oldlen], verprefix);
 1929         strcpy(&versions[oldlen + strlen(verprefix)], verstring);
 1930         versions[newlen + oldlen] = '\n';
 1931         versions[newlen + oldlen + 1] = '\0';
 1932 }
 1933 
 1934 static void
 1935 yyerror(const char *string)
 1936 {
 1937         stop(string, EX_DATAERR);
 1938 }
 1939 
 1940 static int
 1941 is_download_const(expression_t *immed)
 1942 {
 1943         if ((immed->referenced_syms.slh_first != NULL)
 1944          && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST))
 1945                 return (TRUE);
 1946 
 1947         return (FALSE);
 1948 }

Cache object: f126ecc7eda8be68ca9ef97f74db2ebc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.