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