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