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