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