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