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