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