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