1 %{ 2 /* 3 * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 4 * 5 * Copyright (c) 1997-1998 Justin T. Gibbs. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <sysexits.h> 36 37 #include <sys/types.h> 38 #include <sys/queue.h> 39 40 #include "aicasm.h" 41 #include "aicasm_symbol.h" 42 #include "sequencer.h" 43 44 int yylineno; 45 char *yyfilename; 46 static symbol_t *cur_symbol; 47 static symtype cur_symtype; 48 static symbol_t *accumulator; 49 static symbol_ref_t allones; 50 static symbol_ref_t allzeros; 51 static symbol_ref_t none; 52 static symbol_ref_t sindex; 53 static int instruction_ptr; 54 static int sram_or_scb_offset; 55 static int download_constant_count; 56 57 static void process_bitmask __P((int mask_type, symbol_t *sym, int mask)); 58 static void initialize_symbol __P((symbol_t *symbol)); 59 static void process_register __P((symbol_t **p_symbol)); 60 static void format_1_instr __P((int opcode, symbol_ref_t *dest, 61 expression_t *immed, symbol_ref_t *src, 62 int ret)); 63 static void format_2_instr __P((int opcode, symbol_ref_t *dest, 64 expression_t *places, symbol_ref_t *src, 65 int ret)); 66 static void format_3_instr __P((int opcode, symbol_ref_t *src, 67 expression_t *immed, symbol_ref_t *address)); 68 static void test_readable_symbol __P((symbol_t *symbol)); 69 static void test_writable_symbol __P((symbol_t *symbol)); 70 static void type_check __P((symbol_t *symbol, expression_t *expression, 71 int and_op)); 72 static void make_expression __P((expression_t *immed, int value)); 73 static void add_conditional __P((symbol_t *symbol)); 74 static int is_download_const __P((expression_t *immed)); 75 76 #define YYDEBUG 1 77 #define SRAM_SYMNAME "SRAM_BASE" 78 #define SCB_SYMNAME "SCB_BASE" 79 %} 80 81 %union { 82 int value; 83 char *str; 84 symbol_t *sym; 85 symbol_ref_t sym_ref; 86 expression_t expression; 87 } 88 89 %token T_REGISTER 90 91 %token <value> T_CONST 92 93 %token T_DOWNLOAD 94 95 %token T_SCB 96 97 %token T_SRAM 98 99 %token T_ALIAS 100 101 %token T_SIZE 102 103 %token <value> T_ADDRESS 104 105 %token T_ACCESS_MODE 106 107 %token <value> T_MODE 108 109 %token T_BIT 110 111 %token T_MASK 112 113 %token <value> T_NUMBER 114 115 %token <str> T_PATH 116 117 %token <sym> T_CEXPR 118 119 %token T_EOF T_INCLUDE 120 121 %token <value> T_SHR T_SHL T_ROR T_ROL 122 123 %token <value> T_MVI T_MOV T_CLR T_BMOV 124 125 %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 126 127 %token <value> T_ADD T_ADC 128 129 %token <value> T_INC T_DEC 130 131 %token <value> T_STC T_CLC 132 133 %token <value> T_CMP T_XOR 134 135 %token <value> T_TEST T_AND 136 137 %token <value> T_OR 138 139 %token T_RET 140 141 %token T_NOP 142 143 %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX 144 145 %token T_A 146 147 %token <sym> T_SYMBOL 148 149 %token T_NL 150 151 %token T_IF T_ELSE T_ELSE_IF T_ENDIF 152 153 %type <sym_ref> reg_symbol address destination source opt_source 154 155 %type <expression> expression immediate immediate_or_a 156 157 %type <value> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 158 159 %type <value> numerical_value 160 161 %left '|' 162 %left '&' 163 %left '+' '-' 164 %right '~' 165 %nonassoc UMINUS 166 %% 167 168 program: 169 include 170 | program include 171 | register 172 | program register 173 | constant 174 | program constant 175 | scratch_ram 176 | program scratch_ram 177 | scb 178 | program scb 179 | label 180 | program label 181 | conditional 182 | program conditional 183 | code 184 | program code 185 ; 186 187 include: 188 T_INCLUDE '<' T_PATH '>' 189 { include_file($3, BRACKETED_INCLUDE); } 190 | T_INCLUDE '"' T_PATH '"' 191 { include_file($3, QUOTED_INCLUDE); } 192 ; 193 194 register: 195 T_REGISTER { cur_symtype = REGISTER; } reg_definition 196 ; 197 198 reg_definition: 199 T_SYMBOL '{' 200 { 201 if ($1->type != UNINITIALIZED) { 202 stop("Register multiply defined", EX_DATAERR); 203 /* NOTREACHED */ 204 } 205 cur_symbol = $1; 206 cur_symbol->type = cur_symtype; 207 initialize_symbol(cur_symbol); 208 } 209 reg_attribute_list 210 '}' 211 { 212 /* 213 * Default to allowing everything in for registers 214 * with no bit or mask definitions. 215 */ 216 if (cur_symbol->info.rinfo->valid_bitmask == 0) 217 cur_symbol->info.rinfo->valid_bitmask = 0xFF; 218 219 if (cur_symbol->info.rinfo->size == 0) 220 cur_symbol->info.rinfo->size = 1; 221 222 /* 223 * This might be useful for registers too. 224 */ 225 if (cur_symbol->type != REGISTER) { 226 if (cur_symbol->info.rinfo->address == 0) 227 cur_symbol->info.rinfo->address = 228 sram_or_scb_offset; 229 sram_or_scb_offset += 230 cur_symbol->info.rinfo->size; 231 } 232 cur_symbol = NULL; 233 } 234 ; 235 236 reg_attribute_list: 237 reg_attribute 238 | reg_attribute_list reg_attribute 239 ; 240 241 reg_attribute: 242 reg_address 243 | size 244 | access_mode 245 | bit_defn 246 | mask_defn 247 | alias 248 | accumulator 249 | allones 250 | allzeros 251 | none 252 | sindex 253 ; 254 255 reg_address: 256 T_ADDRESS T_NUMBER 257 { 258 cur_symbol->info.rinfo->address = $2; 259 } 260 ; 261 262 size: 263 T_SIZE T_NUMBER 264 { 265 cur_symbol->info.rinfo->size = $2; 266 } 267 ; 268 269 access_mode: 270 T_ACCESS_MODE T_MODE 271 { 272 cur_symbol->info.rinfo->mode = $2; 273 } 274 ; 275 276 bit_defn: 277 T_BIT T_SYMBOL T_NUMBER 278 { 279 process_bitmask(BIT, $2, $3); 280 } 281 ; 282 283 mask_defn: 284 T_MASK T_SYMBOL expression 285 { 286 process_bitmask(MASK, $2, $3.value); 287 } 288 ; 289 290 alias: 291 T_ALIAS T_SYMBOL 292 { 293 if ($2->type != UNINITIALIZED) { 294 stop("Re-definition of register alias", 295 EX_DATAERR); 296 /* NOTREACHED */ 297 } 298 $2->type = ALIAS; 299 initialize_symbol($2); 300 $2->info.ainfo->parent = cur_symbol; 301 } 302 ; 303 304 accumulator: 305 T_ACCUM 306 { 307 if (accumulator != NULL) { 308 stop("Only one accumulator definition allowed", 309 EX_DATAERR); 310 /* NOTREACHED */ 311 } 312 accumulator = cur_symbol; 313 } 314 ; 315 316 allones: 317 T_ALLONES 318 { 319 if (allones.symbol != NULL) { 320 stop("Only one definition of allones allowed", 321 EX_DATAERR); 322 /* NOTREACHED */ 323 } 324 allones.symbol = cur_symbol; 325 } 326 ; 327 328 allzeros: 329 T_ALLZEROS 330 { 331 if (allzeros.symbol != NULL) { 332 stop("Only one definition of allzeros allowed", 333 EX_DATAERR); 334 /* NOTREACHED */ 335 } 336 allzeros.symbol = cur_symbol; 337 } 338 ; 339 340 none: 341 T_NONE 342 { 343 if (none.symbol != NULL) { 344 stop("Only one definition of none allowed", 345 EX_DATAERR); 346 /* NOTREACHED */ 347 } 348 none.symbol = cur_symbol; 349 } 350 ; 351 352 sindex: 353 T_SINDEX 354 { 355 if (sindex.symbol != NULL) { 356 stop("Only one definition of sindex allowed", 357 EX_DATAERR); 358 /* NOTREACHED */ 359 } 360 sindex.symbol = cur_symbol; 361 } 362 ; 363 364 expression: 365 expression '|' expression 366 { 367 $$.value = $1.value | $3.value; 368 symlist_merge(&$$.referenced_syms, 369 &$1.referenced_syms, 370 &$3.referenced_syms); 371 } 372 | expression '&' expression 373 { 374 $$.value = $1.value & $3.value; 375 symlist_merge(&$$.referenced_syms, 376 &$1.referenced_syms, 377 &$3.referenced_syms); 378 } 379 | expression '+' expression 380 { 381 $$.value = $1.value + $3.value; 382 symlist_merge(&$$.referenced_syms, 383 &$1.referenced_syms, 384 &$3.referenced_syms); 385 } 386 | expression '-' expression 387 { 388 $$.value = $1.value - $3.value; 389 symlist_merge(&($$.referenced_syms), 390 &($1.referenced_syms), 391 &($3.referenced_syms)); 392 } 393 | '(' expression ')' 394 { 395 $$ = $2; 396 } 397 | '~' expression 398 { 399 $$ = $2; 400 $$.value = (~$$.value) & 0xFF; 401 } 402 | '-' expression %prec UMINUS 403 { 404 $$ = $2; 405 $$.value = -$$.value; 406 } 407 | T_NUMBER 408 { 409 $$.value = $1; 410 SLIST_INIT(&$$.referenced_syms); 411 } 412 | T_SYMBOL 413 { 414 symbol_t *symbol; 415 416 symbol = $1; 417 switch (symbol->type) { 418 case ALIAS: 419 symbol = $1->info.ainfo->parent; 420 case REGISTER: 421 case SCBLOC: 422 case SRAMLOC: 423 $$.value = symbol->info.rinfo->address; 424 break; 425 case MASK: 426 case BIT: 427 $$.value = symbol->info.minfo->mask; 428 break; 429 case DOWNLOAD_CONST: 430 case CONST: 431 $$.value = symbol->info.cinfo->value; 432 break; 433 case UNINITIALIZED: 434 default: 435 { 436 char buf[255]; 437 438 snprintf(buf, sizeof(buf), 439 "Undefined symbol %s referenced", 440 symbol->name); 441 stop(buf, EX_DATAERR); 442 /* NOTREACHED */ 443 break; 444 } 445 } 446 SLIST_INIT(&$$.referenced_syms); 447 symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 448 } 449 ; 450 451 constant: 452 T_CONST T_SYMBOL numerical_value 453 { 454 if ($2->type != UNINITIALIZED) { 455 stop("Re-definition of symbol as a constant", 456 EX_DATAERR); 457 /* NOTREACHED */ 458 } 459 $2->type = CONST; 460 initialize_symbol($2); 461 $2->info.cinfo->value = $3; 462 $2->info.cinfo->define = $1; 463 } 464 | T_CONST T_SYMBOL T_DOWNLOAD 465 { 466 if ($1) { 467 stop("Invalid downloaded constant declaration", 468 EX_DATAERR); 469 /* NOTREACHED */ 470 } 471 if ($2->type != UNINITIALIZED) { 472 stop("Re-definition of symbol as a downloaded constant", 473 EX_DATAERR); 474 /* NOTREACHED */ 475 } 476 $2->type = DOWNLOAD_CONST; 477 initialize_symbol($2); 478 $2->info.cinfo->value = download_constant_count++; 479 $2->info.cinfo->define = FALSE; 480 } 481 ; 482 483 numerical_value: 484 T_NUMBER 485 { 486 $$ = $1; 487 } 488 | '-' T_NUMBER 489 { 490 $$ = -$2; 491 } 492 ; 493 494 scratch_ram: 495 T_SRAM '{' 496 { 497 cur_symbol = symtable_get(SRAM_SYMNAME); 498 cur_symtype = SRAMLOC; 499 if (cur_symbol->type != UNINITIALIZED) { 500 stop("Only one SRAM definition allowed", 501 EX_DATAERR); 502 /* NOTREACHED */ 503 } 504 cur_symbol->type = SRAMLOC; 505 initialize_symbol(cur_symbol); 506 } 507 reg_address 508 { 509 sram_or_scb_offset = cur_symbol->info.rinfo->address; 510 } 511 scb_or_sram_reg_list 512 '}' 513 { 514 cur_symbol = NULL; 515 } 516 ; 517 518 scb: 519 T_SCB '{' 520 { 521 cur_symbol = symtable_get(SCB_SYMNAME); 522 cur_symtype = SCBLOC; 523 if (cur_symbol->type != UNINITIALIZED) { 524 stop("Only one SRAM definition allowed", 525 EX_SOFTWARE); 526 /* NOTREACHED */ 527 } 528 cur_symbol->type = SCBLOC; 529 initialize_symbol(cur_symbol); 530 } 531 reg_address 532 { 533 sram_or_scb_offset = cur_symbol->info.rinfo->address; 534 } 535 scb_or_sram_reg_list 536 '}' 537 { 538 cur_symbol = NULL; 539 } 540 ; 541 542 scb_or_sram_reg_list: 543 reg_definition 544 | scb_or_sram_reg_list reg_definition 545 ; 546 547 reg_symbol: 548 T_SYMBOL 549 { 550 process_register(&$1); 551 $$.symbol = $1; 552 $$.offset = 0; 553 } 554 | T_SYMBOL '[' T_NUMBER ']' 555 { 556 process_register(&$1); 557 if (($3 + 1) > $1->info.rinfo->size) { 558 stop("Accessing offset beyond range of register", 559 EX_DATAERR); 560 /* NOTREACHED */ 561 } 562 $$.symbol = $1; 563 $$.offset = $3; 564 } 565 | T_A 566 { 567 if (accumulator == NULL) { 568 stop("No accumulator has been defined", EX_DATAERR); 569 /* NOTREACHED */ 570 } 571 $$.symbol = accumulator; 572 $$.offset = 0; 573 } 574 ; 575 576 destination: 577 reg_symbol 578 { 579 test_writable_symbol($1.symbol); 580 $$ = $1; 581 } 582 ; 583 584 immediate: 585 expression 586 { $$ = $1; } 587 ; 588 589 immediate_or_a: 590 expression 591 { 592 $$ = $1; 593 } 594 | T_A 595 { 596 SLIST_INIT(&$$.referenced_syms); 597 $$.value = 0; 598 } 599 ; 600 601 source: 602 reg_symbol 603 { 604 test_readable_symbol($1.symbol); 605 $$ = $1; 606 } 607 ; 608 609 opt_source: 610 { 611 $$.symbol = NULL; 612 $$.offset = 0; 613 } 614 | ',' source 615 { $$ = $2; } 616 ; 617 618 ret: 619 { $$ = 0; } 620 | T_RET 621 { $$ = 1; } 622 ; 623 624 label: 625 T_SYMBOL ':' 626 { 627 if ($1->type != UNINITIALIZED) { 628 stop("Program label multiply defined", EX_DATAERR); 629 /* NOTREACHED */ 630 } 631 $1->type = LABEL; 632 initialize_symbol($1); 633 $1->info.linfo->address = instruction_ptr; 634 } 635 ; 636 637 address: 638 T_SYMBOL 639 { 640 $$.symbol = $1; 641 $$.offset = 0; 642 } 643 | T_SYMBOL '+' T_NUMBER 644 { 645 $$.symbol = $1; 646 $$.offset = $3; 647 } 648 | T_SYMBOL '-' T_NUMBER 649 { 650 $$.symbol = $1; 651 $$.offset = -$3; 652 } 653 | '.' 654 { 655 $$.symbol = NULL; 656 $$.offset = 0; 657 } 658 | '.' '+' T_NUMBER 659 { 660 $$.symbol = NULL; 661 $$.offset = $3; 662 } 663 | '.' '-' T_NUMBER 664 { 665 $$.symbol = NULL; 666 $$.offset = -$3; 667 } 668 ; 669 670 conditional: 671 T_IF T_CEXPR '{' 672 { 673 scope_t *new_scope; 674 675 add_conditional($2); 676 new_scope = scope_alloc(); 677 new_scope->type = SCOPE_IF; 678 new_scope->begin_addr = instruction_ptr; 679 new_scope->func_num = $2->info.condinfo->func_num; 680 } 681 | T_ELSE T_IF T_CEXPR '{' 682 { 683 scope_t *new_scope; 684 scope_t *scope_context; 685 scope_t *last_scope; 686 687 /* 688 * Ensure that the previous scope is either an 689 * if or and else if. 690 */ 691 scope_context = SLIST_FIRST(&scope_stack); 692 last_scope = TAILQ_LAST(&scope_context->inner_scope, 693 scope_tailq); 694 if (last_scope == NULL 695 || last_scope->type == T_ELSE) { 696 697 stop("'else if' without leading 'if'", EX_DATAERR); 698 /* NOTREACHED */ 699 } 700 add_conditional($3); 701 new_scope = scope_alloc(); 702 new_scope->type = SCOPE_ELSE_IF; 703 new_scope->begin_addr = instruction_ptr; 704 new_scope->func_num = $3->info.condinfo->func_num; 705 } 706 | T_ELSE '{' 707 { 708 scope_t *new_scope; 709 scope_t *scope_context; 710 scope_t *last_scope; 711 712 /* 713 * Ensure that the previous scope is either an 714 * if or and else if. 715 */ 716 scope_context = SLIST_FIRST(&scope_stack); 717 last_scope = TAILQ_LAST(&scope_context->inner_scope, 718 scope_tailq); 719 if (last_scope == NULL 720 || last_scope->type == SCOPE_ELSE) { 721 722 stop("'else' without leading 'if'", EX_DATAERR); 723 /* NOTREACHED */ 724 } 725 new_scope = scope_alloc(); 726 new_scope->type = SCOPE_ELSE; 727 new_scope->begin_addr = instruction_ptr; 728 } 729 ; 730 731 conditional: 732 '}' 733 { 734 scope_t *scope_context; 735 scope_t *last_scope; 736 737 scope_context = SLIST_FIRST(&scope_stack); 738 if (scope_context->type == SCOPE_ROOT) { 739 stop("Unexpected '}' encountered", EX_DATAERR); 740 /* NOTREACHED */ 741 } 742 743 scope_context->end_addr = instruction_ptr; 744 745 /* Pop the scope */ 746 SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 747 748 process_scope(scope_context); 749 750 if (SLIST_FIRST(&scope_stack) == NULL) { 751 stop("Unexpected '}' encountered", EX_DATAERR); 752 /* NOTREACHED */ 753 } 754 } 755 ; 756 757 f1_opcode: 758 T_AND { $$ = AIC_OP_AND; } 759 | T_XOR { $$ = AIC_OP_XOR; } 760 | T_ADD { $$ = AIC_OP_ADD; } 761 | T_ADC { $$ = AIC_OP_ADC; } 762 ; 763 764 code: 765 f1_opcode destination ',' immediate_or_a opt_source ret ';' 766 { 767 format_1_instr($1, &$2, &$4, &$5, $6); 768 } 769 ; 770 771 code: 772 T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 773 { 774 format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 775 } 776 ; 777 778 code: 779 T_INC destination opt_source ret ';' 780 { 781 expression_t immed; 782 783 make_expression(&immed, 1); 784 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 785 } 786 ; 787 788 code: 789 T_DEC destination opt_source ret ';' 790 { 791 expression_t immed; 792 793 make_expression(&immed, -1); 794 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 795 } 796 ; 797 798 code: 799 T_CLC ret ';' 800 { 801 expression_t immed; 802 803 make_expression(&immed, -1); 804 format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 805 } 806 | T_CLC T_MVI destination ',' immediate_or_a ret ';' 807 { 808 format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 809 } 810 ; 811 812 code: 813 T_STC ret ';' 814 { 815 expression_t immed; 816 817 make_expression(&immed, 1); 818 format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 819 } 820 | T_STC destination ret ';' 821 { 822 expression_t immed; 823 824 make_expression(&immed, 1); 825 format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 826 } 827 ; 828 829 code: 830 T_BMOV destination ',' source ',' immediate ret ';' 831 { 832 format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 833 } 834 ; 835 836 code: 837 T_MOV destination ',' source ret ';' 838 { 839 expression_t immed; 840 841 make_expression(&immed, 0xff); 842 format_1_instr(AIC_OP_AND, &$2, &immed, &$4, $5); 843 } 844 ; 845 846 code: 847 T_MVI destination ',' immediate_or_a ret ';' 848 { 849 format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 850 } 851 ; 852 853 code: 854 T_CLR destination ret ';' 855 { 856 expression_t immed; 857 858 make_expression(&immed, 0xff); 859 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 860 } 861 ; 862 863 code: 864 T_NOP ret ';' 865 { 866 expression_t immed; 867 868 make_expression(&immed, 0xff); 869 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 870 } 871 ; 872 873 code: 874 T_RET ';' 875 { 876 expression_t immed; 877 878 make_expression(&immed, 0xff); 879 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 880 } 881 ; 882 883 /* 884 * This grammer differs from the one in the aic7xxx 885 * reference manual since the grammer listed there is 886 * ambiguous and causes a shift/reduce conflict. 887 * It also seems more logical as the "immediate" 888 * argument is listed as the second arg like the 889 * other formats. 890 */ 891 892 f2_opcode: 893 T_SHL { $$ = AIC_OP_SHL; } 894 | T_SHR { $$ = AIC_OP_SHR; } 895 | T_ROL { $$ = AIC_OP_ROL; } 896 | T_ROR { $$ = AIC_OP_ROR; } 897 ; 898 899 code: 900 f2_opcode destination ',' expression opt_source ret ';' 901 { 902 format_2_instr($1, &$2, &$4, &$5, $6); 903 } 904 ; 905 906 jmp_jc_jnc_call: 907 T_JMP { $$ = AIC_OP_JMP; } 908 | T_JC { $$ = AIC_OP_JC; } 909 | T_JNC { $$ = AIC_OP_JNC; } 910 | T_CALL { $$ = AIC_OP_CALL; } 911 ; 912 913 jz_jnz: 914 T_JZ { $$ = AIC_OP_JZ; } 915 | T_JNZ { $$ = AIC_OP_JNZ; } 916 ; 917 918 je_jne: 919 T_JE { $$ = AIC_OP_JE; } 920 | T_JNE { $$ = AIC_OP_JNE; } 921 ; 922 923 code: 924 jmp_jc_jnc_call address ';' 925 { 926 expression_t immed; 927 928 make_expression(&immed, 0); 929 format_3_instr($1, &sindex, &immed, &$2); 930 } 931 ; 932 933 code: 934 T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 935 { 936 format_3_instr($5, &$2, &$4, &$6); 937 } 938 ; 939 940 code: 941 T_TEST source ',' immediate_or_a jz_jnz address ';' 942 { 943 format_3_instr($5, &$2, &$4, &$6); 944 } 945 ; 946 947 code: 948 T_CMP source ',' immediate_or_a je_jne address ';' 949 { 950 format_3_instr($5, &$2, &$4, &$6); 951 } 952 ; 953 954 code: 955 T_MOV source jmp_jc_jnc_call address ';' 956 { 957 expression_t immed; 958 959 make_expression(&immed, 0); 960 format_3_instr($3, &$2, &immed, &$4); 961 } 962 ; 963 964 code: 965 T_MVI immediate jmp_jc_jnc_call address ';' 966 { 967 format_3_instr($3, &allzeros, &$2, &$4); 968 } 969 ; 970 971 %% 972 973 static void 974 process_bitmask(mask_type, sym, mask) 975 int mask_type; 976 symbol_t *sym; 977 int mask; 978 { 979 /* 980 * Add the current register to its 981 * symbol list, if it already exists, 982 * warn if we are setting it to a 983 * different value, or in the bit to 984 * the "allowed bits" of this register. 985 */ 986 if (sym->type == UNINITIALIZED) { 987 sym->type = mask_type; 988 initialize_symbol(sym); 989 if (mask_type == BIT) { 990 if (mask == 0) { 991 stop("Bitmask with no bits set", EX_DATAERR); 992 /* NOTREACHED */ 993 } 994 if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) { 995 stop("Bitmask with more than one bit set", 996 EX_DATAERR); 997 /* NOTREACHED */ 998 } 999 } 1000 sym->info.minfo->mask = mask; 1001 } else if (sym->type != mask_type) { 1002 stop("Bit definition mirrors a definition of the same " 1003 " name, but a different type", EX_DATAERR); 1004 /* NOTREACHED */ 1005 } else if (mask != sym->info.minfo->mask) { 1006 stop("Bitmask redefined with a conflicting value", EX_DATAERR); 1007 /* NOTREACHED */ 1008 } 1009 /* Fail if this symbol is already listed */ 1010 if (symlist_search(&(sym->info.minfo->symrefs), 1011 cur_symbol->name) != NULL) { 1012 stop("Bitmask defined multiple times for register", EX_DATAERR); 1013 /* NOTREACHED */ 1014 } 1015 symlist_add(&(sym->info.minfo->symrefs), cur_symbol, 1016 SYMLIST_INSERT_HEAD); 1017 cur_symbol->info.rinfo->valid_bitmask |= mask; 1018 cur_symbol->info.rinfo->typecheck_masks = TRUE; 1019 } 1020 1021 static void 1022 initialize_symbol(symbol) 1023 symbol_t *symbol; 1024 { 1025 switch (symbol->type) { 1026 case UNINITIALIZED: 1027 stop("Call to initialize_symbol with type field unset", 1028 EX_SOFTWARE); 1029 /* NOTREACHED */ 1030 break; 1031 case REGISTER: 1032 case SRAMLOC: 1033 case SCBLOC: 1034 symbol->info.rinfo = 1035 (struct reg_info *)malloc(sizeof(struct reg_info)); 1036 if (symbol->info.rinfo == NULL) { 1037 stop("Can't create register info", EX_SOFTWARE); 1038 /* NOTREACHED */ 1039 } 1040 memset(symbol->info.rinfo, 0, 1041 sizeof(struct reg_info)); 1042 break; 1043 case ALIAS: 1044 symbol->info.ainfo = 1045 (struct alias_info *)malloc(sizeof(struct alias_info)); 1046 if (symbol->info.ainfo == NULL) { 1047 stop("Can't create alias info", EX_SOFTWARE); 1048 /* NOTREACHED */ 1049 } 1050 memset(symbol->info.ainfo, 0, 1051 sizeof(struct alias_info)); 1052 break; 1053 case MASK: 1054 case BIT: 1055 symbol->info.minfo = 1056 (struct mask_info *)malloc(sizeof(struct mask_info)); 1057 if (symbol->info.minfo == NULL) { 1058 stop("Can't create bitmask info", EX_SOFTWARE); 1059 /* NOTREACHED */ 1060 } 1061 memset(symbol->info.minfo, 0, sizeof(struct mask_info)); 1062 SLIST_INIT(&(symbol->info.minfo->symrefs)); 1063 break; 1064 case CONST: 1065 case DOWNLOAD_CONST: 1066 symbol->info.cinfo = 1067 (struct const_info *)malloc(sizeof(struct const_info)); 1068 if (symbol->info.cinfo == NULL) { 1069 stop("Can't create alias info", EX_SOFTWARE); 1070 /* NOTREACHED */ 1071 } 1072 memset(symbol->info.cinfo, 0, 1073 sizeof(struct const_info)); 1074 break; 1075 case LABEL: 1076 symbol->info.linfo = 1077 (struct label_info *)malloc(sizeof(struct label_info)); 1078 if (symbol->info.linfo == NULL) { 1079 stop("Can't create label info", EX_SOFTWARE); 1080 /* NOTREACHED */ 1081 } 1082 memset(symbol->info.linfo, 0, 1083 sizeof(struct label_info)); 1084 break; 1085 case CONDITIONAL: 1086 symbol->info.condinfo = 1087 (struct cond_info *)malloc(sizeof(struct cond_info)); 1088 if (symbol->info.condinfo == NULL) { 1089 stop("Can't create conditional info", EX_SOFTWARE); 1090 /* NOTREACHED */ 1091 } 1092 memset(symbol->info.condinfo, 0, 1093 sizeof(struct cond_info)); 1094 break; 1095 default: 1096 stop("Call to initialize_symbol with invalid symbol type", 1097 EX_SOFTWARE); 1098 /* NOTREACHED */ 1099 break; 1100 } 1101 } 1102 1103 static void 1104 process_register(p_symbol) 1105 symbol_t **p_symbol; 1106 { 1107 char buf[255]; 1108 symbol_t *symbol = *p_symbol; 1109 1110 if (symbol->type == UNINITIALIZED) { 1111 snprintf(buf, sizeof(buf), "Undefined register %s", 1112 symbol->name); 1113 stop(buf, EX_DATAERR); 1114 /* NOTREACHED */ 1115 } else if (symbol->type == ALIAS) { 1116 *p_symbol = symbol->info.ainfo->parent; 1117 } else if ((symbol->type != REGISTER) 1118 && (symbol->type != SCBLOC) 1119 && (symbol->type != SRAMLOC)) { 1120 snprintf(buf, sizeof(buf), 1121 "Specified symbol %s is not a register", 1122 symbol->name); 1123 stop(buf, EX_DATAERR); 1124 } 1125 } 1126 1127 static void 1128 format_1_instr(opcode, dest, immed, src, ret) 1129 int opcode; 1130 symbol_ref_t *dest; 1131 expression_t *immed; 1132 symbol_ref_t *src; 1133 int ret; 1134 { 1135 struct instruction *instr; 1136 struct ins_format1 *f1_instr; 1137 1138 if (src->symbol == NULL) 1139 src = dest; 1140 1141 /* Test register permissions */ 1142 test_writable_symbol(dest->symbol); 1143 test_readable_symbol(src->symbol); 1144 1145 /* Ensure that immediate makes sense for this destination */ 1146 type_check(dest->symbol, immed, opcode); 1147 1148 /* Allocate sequencer space for the instruction and fill it out */ 1149 instr = seq_alloc(); 1150 f1_instr = &instr->format.format1; 1151 f1_instr->ret = ret ? 1 : 0; 1152 f1_instr->opcode = opcode; 1153 f1_instr->destination = dest->symbol->info.rinfo->address 1154 + dest->offset; 1155 f1_instr->source = src->symbol->info.rinfo->address 1156 + src->offset; 1157 f1_instr->immediate = immed->value; 1158 1159 if (is_download_const(immed)) 1160 f1_instr->parity = 1; 1161 1162 symlist_free(&immed->referenced_syms); 1163 instruction_ptr++; 1164 } 1165 1166 static void 1167 format_2_instr(opcode, dest, places, src, ret) 1168 int opcode; 1169 symbol_ref_t *dest; 1170 expression_t *places; 1171 symbol_ref_t *src; 1172 int ret; 1173 { 1174 struct instruction *instr; 1175 struct ins_format2 *f2_instr; 1176 u_int8_t shift_control; 1177 1178 if (src->symbol == NULL) 1179 src = dest; 1180 1181 /* Test register permissions */ 1182 test_writable_symbol(dest->symbol); 1183 test_readable_symbol(src->symbol); 1184 1185 /* Allocate sequencer space for the instruction and fill it out */ 1186 instr = seq_alloc(); 1187 f2_instr = &instr->format.format2; 1188 f2_instr->ret = ret ? 1 : 0; 1189 f2_instr->opcode = AIC_OP_ROL; 1190 f2_instr->destination = dest->symbol->info.rinfo->address 1191 + dest->offset; 1192 f2_instr->source = src->symbol->info.rinfo->address 1193 + src->offset; 1194 if (places->value > 8 || places->value <= 0) { 1195 stop("illegal shift value", EX_DATAERR); 1196 /* NOTREACHED */ 1197 } 1198 switch (opcode) { 1199 case AIC_OP_SHL: 1200 if (places->value == 8) 1201 shift_control = 0xf0; 1202 else 1203 shift_control = (places->value << 4) | places->value; 1204 break; 1205 case AIC_OP_SHR: 1206 if (places->value == 8) { 1207 shift_control = 0xf8; 1208 } else { 1209 shift_control = (places->value << 4) 1210 | (8 - places->value) 1211 | 0x08; 1212 } 1213 break; 1214 case AIC_OP_ROL: 1215 shift_control = places->value & 0x7; 1216 break; 1217 case AIC_OP_ROR: 1218 shift_control = (8 - places->value) | 0x08; 1219 break; 1220 default: 1221 shift_control = 0; /* Quiet Compiler */ 1222 stop("Invalid shift operation specified", EX_SOFTWARE); 1223 /* NOTREACHED */ 1224 break; 1225 }; 1226 f2_instr->shift_control = shift_control; 1227 symlist_free(&places->referenced_syms); 1228 instruction_ptr++; 1229 } 1230 1231 static void 1232 format_3_instr(opcode, src, immed, address) 1233 int opcode; 1234 symbol_ref_t *src; 1235 expression_t *immed; 1236 symbol_ref_t *address; 1237 { 1238 struct instruction *instr; 1239 struct ins_format3 *f3_instr; 1240 int addr; 1241 1242 /* Test register permissions */ 1243 test_readable_symbol(src->symbol); 1244 1245 /* Ensure that immediate makes sense for this source */ 1246 type_check(src->symbol, immed, opcode); 1247 1248 /* Allocate sequencer space for the instruction and fill it out */ 1249 instr = seq_alloc(); 1250 f3_instr = &instr->format.format3; 1251 if (address->symbol == NULL) { 1252 /* 'dot' referrence. Use the current instruction pointer */ 1253 addr = instruction_ptr + address->offset; 1254 } else if (address->symbol->type == UNINITIALIZED) { 1255 /* forward reference */ 1256 addr = address->offset; 1257 instr->patch_label = address->symbol; 1258 } else 1259 addr = address->symbol->info.linfo->address + address->offset; 1260 f3_instr->opcode = opcode; 1261 f3_instr->address = addr; 1262 f3_instr->source = src->symbol->info.rinfo->address 1263 + src->offset; 1264 f3_instr->immediate = immed->value; 1265 1266 if (is_download_const(immed)) 1267 f3_instr->parity = 1; 1268 1269 symlist_free(&immed->referenced_syms); 1270 instruction_ptr++; 1271 } 1272 1273 static void 1274 test_readable_symbol(symbol) 1275 symbol_t *symbol; 1276 { 1277 if (symbol->info.rinfo->mode == WO) { 1278 stop("Write Only register specified as source", 1279 EX_DATAERR); 1280 /* NOTREACHED */ 1281 } 1282 } 1283 1284 static void 1285 test_writable_symbol(symbol) 1286 symbol_t *symbol; 1287 { 1288 if (symbol->info.rinfo->mode == RO) { 1289 stop("Read Only register specified as destination", 1290 EX_DATAERR); 1291 /* NOTREACHED */ 1292 } 1293 } 1294 1295 static void 1296 type_check(symbol, expression, opcode) 1297 symbol_t *symbol; 1298 expression_t *expression; 1299 int opcode; 1300 { 1301 symbol_node_t *node; 1302 int and_op; 1303 char buf[255]; 1304 1305 and_op = FALSE; 1306 if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) 1307 and_op = TRUE; 1308 1309 /* 1310 * Make sure that we aren't attempting to write something 1311 * that hasn't been defined. If this is an and operation, 1312 * this is a mask, so "undefined" bits are okay. 1313 */ 1314 if (and_op == FALSE 1315 && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { 1316 snprintf(buf, sizeof(buf), 1317 "Invalid bit(s) 0x%x in immediate written to %s", 1318 expression->value & ~symbol->info.rinfo->valid_bitmask, 1319 symbol->name); 1320 stop(buf, EX_DATAERR); 1321 /* NOTREACHED */ 1322 } 1323 1324 /* 1325 * Now make sure that all of the symbols referenced by the 1326 * expression are defined for this register. 1327 */ 1328 if(symbol->info.rinfo->typecheck_masks != FALSE) { 1329 for(node = expression->referenced_syms.slh_first; 1330 node != NULL; 1331 node = node->links.sle_next) { 1332 if ((node->symbol->type == MASK 1333 || node->symbol->type == BIT) 1334 && symlist_search(&node->symbol->info.minfo->symrefs, 1335 symbol->name) == NULL) { 1336 snprintf(buf, sizeof(buf), 1337 "Invalid bit or mask %s " 1338 "for register %s", 1339 node->symbol->name, symbol->name); 1340 stop(buf, EX_DATAERR); 1341 /* NOTREACHED */ 1342 } 1343 } 1344 } 1345 } 1346 1347 static void 1348 make_expression(immed, value) 1349 expression_t *immed; 1350 int value; 1351 { 1352 SLIST_INIT(&immed->referenced_syms); 1353 immed->value = value & 0xff; 1354 } 1355 1356 static void 1357 add_conditional(symbol) 1358 symbol_t *symbol; 1359 { 1360 static int numfuncs; 1361 1362 if (numfuncs == 0) { 1363 /* add a special conditional, "0" */ 1364 symbol_t *false_func; 1365 1366 false_func = symtable_get("0"); 1367 if (false_func->type != UNINITIALIZED) { 1368 stop("Conditional expression '0' " 1369 "conflicts with a symbol", EX_DATAERR); 1370 /* NOTREACHED */ 1371 } 1372 false_func->type = CONDITIONAL; 1373 initialize_symbol(false_func); 1374 false_func->info.condinfo->func_num = numfuncs++; 1375 symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 1376 } 1377 1378 /* This condition has occurred before */ 1379 if (symbol->type == CONDITIONAL) 1380 return; 1381 1382 if (symbol->type != UNINITIALIZED) { 1383 stop("Conditional expression conflicts with a symbol", 1384 EX_DATAERR); 1385 /* NOTREACHED */ 1386 } 1387 1388 symbol->type = CONDITIONAL; 1389 initialize_symbol(symbol); 1390 symbol->info.condinfo->func_num = numfuncs++; 1391 symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 1392 } 1393 1394 void 1395 yyerror(string) 1396 const char *string; 1397 { 1398 stop(string, EX_DATAERR); 1399 } 1400 1401 static int 1402 is_download_const(immed) 1403 expression_t *immed; 1404 { 1405 if ((immed->referenced_syms.slh_first != NULL) 1406 && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 1407 return (TRUE); 1408 1409 return (FALSE); 1410 } 1411