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