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