root/dev/microcode/aic7xxx/aicasm_gram.y

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. YYSTYPE
  2. yyparse
  3. process_field
  4. initialize_symbol
  5. add_macro_arg
  6. add_macro_body
  7. process_register
  8. format_1_instr
  9. format_2_instr
  10. format_3_instr
  11. test_readable_symbol
  12. test_writable_symbol
  13. type_check
  14. make_expression
  15. add_conditional
  16. add_version
  17. yyerror
  18. is_download_const

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

/* [<][>][^][v][top][bottom][index][help] */