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