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 2001