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