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