root/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y

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

DEFINITIONS

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

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

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