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