1 %{ 2 /* $OpenBSD: aicasm_gram.y,v 1.16 2007/07/07 23:59:36 krw Exp $ */ 3 /* $NetBSD: aicasm_gram.y,v 1.3 2003/04/19 19:26:11 fvdl Exp $ */ 4 5 /* 6 * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 7 * 8 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 9 * Copyright (c) 2001, 2002 Adaptec Inc. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 * 44 * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.23 2003/01/20 18:02:11 gibbs Exp $ 45 */ 46 47 #include <sys/types.h> 48 49 #include <inttypes.h> 50 #include <regex.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <sysexits.h> 55 56 #ifdef __linux__ 57 #include "../queue.h" 58 #else 59 #include <sys/queue.h> 60 #endif 61 62 #include "aicasm.h" 63 #include "aicasm_symbol.h" 64 #include "aicasm_insformat.h" 65 66 int yylineno; 67 char *yyfilename; 68 char stock_prefix[] = "aic_"; 69 char *prefix = stock_prefix; 70 char *patch_arg_list; 71 char *versions; 72 static char errbuf[255]; 73 static char regex_pattern[255]; 74 static symbol_t *cur_symbol; 75 static symbol_t *field_symbol; 76 static symbol_t *scb_or_sram_symbol; 77 static symtype cur_symtype; 78 static symbol_ref_t accumulator; 79 static symbol_ref_t mode_ptr; 80 static symbol_ref_t allones; 81 static symbol_ref_t allzeros; 82 static symbol_ref_t none; 83 static symbol_ref_t sindex; 84 static int instruction_ptr; 85 static int num_srams; 86 static int sram_or_scb_offset; 87 static int download_constant_count; 88 static int in_critical_section; 89 static u_int enum_increment; 90 static u_int enum_next_value; 91 92 static void process_field(int field_type, symbol_t *sym, int mask); 93 static void initialize_symbol(symbol_t *symbol); 94 static void add_macro_arg(const char *argtext, int position); 95 static void add_macro_body(const char *bodytext); 96 static void process_register(symbol_t **p_symbol); 97 static void format_1_instr(int opcode, symbol_ref_t *dest, 98 expression_t *immed, symbol_ref_t *src, int ret); 99 static void format_2_instr(int opcode, symbol_ref_t *dest, 100 expression_t *places, symbol_ref_t *src, int ret); 101 static void format_3_instr(int opcode, symbol_ref_t *src, 102 expression_t *immed, symbol_ref_t *address); 103 static void test_readable_symbol(symbol_t *symbol); 104 static void test_writable_symbol(symbol_t *symbol); 105 static void type_check(symbol_t *symbol, expression_t *expression, int and_op); 106 static void make_expression(expression_t *immed, int value); 107 static void add_conditional(symbol_t *symbol); 108 static void add_version(const char *verstring); 109 static int is_download_const(expression_t *immed); 110 111 #define SRAM_SYMNAME "SRAM_BASE" 112 #define SCB_SYMNAME "SCB_BASE" 113 %} 114 115 %union { 116 u_int value; 117 char *str; 118 symbol_t *sym; 119 symbol_ref_t sym_ref; 120 expression_t expression; 121 } 122 123 %token T_REGISTER 124 125 %token <value> T_CONST 126 127 %token T_EXPORT 128 129 %token T_DOWNLOAD 130 131 %token T_SCB 132 133 %token T_SRAM 134 135 %token T_ALIAS 136 137 %token T_SIZE 138 139 %token T_EXPR_LSHIFT 140 141 %token T_EXPR_RSHIFT 142 143 %token <value> T_ADDRESS 144 145 %token T_ACCESS_MODE 146 147 %token T_MODES 148 149 %token T_DEFINE 150 151 %token T_SET_SRC_MODE 152 153 %token T_SET_DST_MODE 154 155 %token <value> T_MODE 156 157 %token T_BEGIN_CS 158 159 %token T_END_CS 160 161 %token T_FIELD 162 163 %token T_ENUM 164 165 %token T_MASK 166 167 %token <value> T_NUMBER 168 169 %token <str> T_PATH T_STRING T_ARG T_MACROBODY 170 171 %token <sym> T_CEXPR 172 173 %token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST 174 175 %token <value> T_SHR T_SHL T_ROR T_ROL 176 177 %token <value> T_MVI T_MOV T_CLR T_BMOV 178 179 %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 180 181 %token <value> T_ADD T_ADC 182 183 %token <value> T_INC T_DEC 184 185 %token <value> T_STC T_CLC 186 187 %token <value> T_CMP T_NOT T_XOR 188 189 %token <value> T_TEST T_AND 190 191 %token <value> T_OR 192 193 %token T_RET 194 195 %token T_NOP 196 197 %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR 198 199 %token T_A 200 201 %token <sym> T_SYMBOL 202 203 %token T_NL 204 205 %token T_IF T_ELSE T_ELSE_IF T_ENDIF 206 207 %type <sym_ref> reg_symbol address destination source opt_source 208 209 %type <expression> expression immediate immediate_or_a 210 211 %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 212 213 %type <value> mode_value mode_list macro_arglist 214 215 %left '|' 216 %left '&' 217 %left T_EXPR_LSHIFT T_EXPR_RSHIFT 218 %left '+' '-' 219 %left '*' '/' 220 %right '~' 221 %nonassoc UMINUS 222 %% 223 224 program: 225 include 226 | program include 227 | prefix 228 | program prefix 229 | patch_arg_list 230 | program patch_arg_list 231 | version 232 | program version 233 | register 234 | program register 235 | constant 236 | program constant 237 | macrodefn 238 | program macrodefn 239 | scratch_ram 240 | program scratch_ram 241 | scb 242 | program scb 243 | label 244 | program label 245 | set_src_mode 246 | program set_src_mode 247 | set_dst_mode 248 | program set_dst_mode 249 | critical_section_start 250 | program critical_section_start 251 | critical_section_end 252 | program critical_section_end 253 | conditional 254 | program conditional 255 | code 256 | program code 257 ; 258 259 include: 260 T_INCLUDE '<' T_PATH '>' 261 { 262 include_file($3, BRACKETED_INCLUDE); 263 } 264 | T_INCLUDE '"' T_PATH '"' 265 { 266 include_file($3, QUOTED_INCLUDE); 267 } 268 ; 269 270 prefix: 271 T_PREFIX '=' T_STRING 272 { 273 if (prefix != stock_prefix) 274 stop("Prefix multiply defined", 275 EX_DATAERR); 276 prefix = strdup($3); 277 if (prefix == NULL) 278 stop("Unable to record prefix", EX_SOFTWARE); 279 } 280 ; 281 282 patch_arg_list: 283 T_PATCH_ARG_LIST '=' T_STRING 284 { 285 if (patch_arg_list != NULL) 286 stop("Patch argument list multiply defined", 287 EX_DATAERR); 288 patch_arg_list = strdup($3); 289 if (patch_arg_list == NULL) 290 stop("Unable to record patch arg list", EX_SOFTWARE); 291 } 292 ; 293 294 version: 295 T_VERSION '=' T_STRING 296 { add_version($3); } 297 ; 298 299 register: 300 T_REGISTER { cur_symtype = REGISTER; } reg_definition 301 ; 302 303 reg_definition: 304 T_SYMBOL '{' 305 { 306 if ($1->type != UNINITIALIZED) { 307 stop("Register multiply defined", EX_DATAERR); 308 /* NOTREACHED */ 309 } 310 cur_symbol = $1; 311 cur_symbol->type = cur_symtype; 312 initialize_symbol(cur_symbol); 313 } 314 reg_attribute_list 315 '}' 316 { 317 /* 318 * Default to allowing everything in for registers 319 * with no bit or mask definitions. 320 */ 321 if (cur_symbol->info.rinfo->valid_bitmask == 0) 322 cur_symbol->info.rinfo->valid_bitmask = 0xFF; 323 324 if (cur_symbol->info.rinfo->size == 0) 325 cur_symbol->info.rinfo->size = 1; 326 327 /* 328 * This might be useful for registers too. 329 */ 330 if (cur_symbol->type != REGISTER) { 331 if (cur_symbol->info.rinfo->address == 0) 332 cur_symbol->info.rinfo->address = 333 sram_or_scb_offset; 334 sram_or_scb_offset += 335 cur_symbol->info.rinfo->size; 336 } 337 cur_symbol = NULL; 338 } 339 ; 340 341 reg_attribute_list: 342 reg_attribute 343 | reg_attribute_list reg_attribute 344 ; 345 346 reg_attribute: 347 reg_address 348 | size 349 | access_mode 350 | modes 351 | field_defn 352 | enum_defn 353 | mask_defn 354 | alias 355 | accumulator 356 | mode_pointer 357 | allones 358 | allzeros 359 | none 360 | sindex 361 ; 362 363 reg_address: 364 T_ADDRESS T_NUMBER 365 { 366 cur_symbol->info.rinfo->address = $2; 367 } 368 ; 369 370 size: 371 T_SIZE T_NUMBER 372 { 373 cur_symbol->info.rinfo->size = $2; 374 if (scb_or_sram_symbol != NULL) { 375 u_int max_addr; 376 u_int sym_max_addr; 377 378 max_addr = scb_or_sram_symbol->info.rinfo->address 379 + scb_or_sram_symbol->info.rinfo->size; 380 sym_max_addr = cur_symbol->info.rinfo->address 381 + cur_symbol->info.rinfo->size; 382 383 if (sym_max_addr > max_addr) 384 stop("SCB or SRAM space exhausted", EX_DATAERR); 385 } 386 } 387 ; 388 389 access_mode: 390 T_ACCESS_MODE T_MODE 391 { 392 cur_symbol->info.rinfo->mode = $2; 393 } 394 ; 395 396 modes: 397 T_MODES mode_list 398 { 399 cur_symbol->info.rinfo->modes = $2; 400 } 401 ; 402 403 mode_list: 404 mode_value 405 { 406 $$ = $1; 407 } 408 | mode_list ',' mode_value 409 { 410 $$ = $1 | $3; 411 } 412 ; 413 414 mode_value: 415 T_NUMBER 416 { 417 if ($1 > 4) { 418 stop("Valid register modes range between 0 and 4.", 419 EX_DATAERR); 420 /* NOTREACHED */ 421 } 422 423 $$ = (0x1 << $1); 424 } 425 | T_SYMBOL 426 { 427 symbol_t *symbol; 428 429 symbol = $1; 430 if (symbol->type != CONST) { 431 stop("Only \"const\" symbols allowed in " 432 "mode definitions.", EX_DATAERR); 433 /* NOTREACHED */ 434 } 435 if (symbol->info.cinfo->value > 4) { 436 stop("Valid register modes range between 0 and 4.", 437 EX_DATAERR); 438 /* NOTREACHED */ 439 } 440 $$ = (0x1 << symbol->info.cinfo->value); 441 } 442 ; 443 444 field_defn: 445 T_FIELD 446 { 447 field_symbol = NULL; 448 enum_next_value = 0; 449 enum_increment = 1; 450 } 451 '{' enum_entry_list '}' 452 | T_FIELD T_SYMBOL expression 453 { 454 process_field(FIELD, $2, $3.value); 455 field_symbol = $2; 456 enum_next_value = 0; 457 enum_increment = 0x01 << (ffs($3.value) - 1); 458 } 459 '{' enum_entry_list '}' 460 | T_FIELD T_SYMBOL expression 461 { 462 process_field(FIELD, $2, $3.value); 463 } 464 ; 465 466 enum_defn: 467 T_ENUM 468 { 469 field_symbol = NULL; 470 enum_next_value = 0; 471 enum_increment = 1; 472 } 473 '{' enum_entry_list '}' 474 | T_ENUM T_SYMBOL expression 475 { 476 process_field(ENUM, $2, $3.value); 477 field_symbol = $2; 478 enum_next_value = 0; 479 enum_increment = 0x01 << (ffs($3.value) - 1); 480 } 481 '{' enum_entry_list '}' 482 ; 483 484 enum_entry_list: 485 enum_entry 486 | enum_entry_list ',' enum_entry 487 ; 488 489 enum_entry: 490 T_SYMBOL 491 { 492 process_field(ENUM_ENTRY, $1, enum_next_value); 493 enum_next_value += enum_increment; 494 } 495 | T_SYMBOL expression 496 { 497 process_field(ENUM_ENTRY, $1, $2.value); 498 enum_next_value = $2.value + enum_increment; 499 } 500 ; 501 502 mask_defn: 503 T_MASK T_SYMBOL expression 504 { 505 process_field(MASK, $2, $3.value); 506 } 507 ; 508 509 alias: 510 T_ALIAS T_SYMBOL 511 { 512 if ($2->type != UNINITIALIZED) { 513 stop("Re-definition of register alias", 514 EX_DATAERR); 515 /* NOTREACHED */ 516 } 517 $2->type = ALIAS; 518 initialize_symbol($2); 519 $2->info.ainfo->parent = cur_symbol; 520 } 521 ; 522 523 accumulator: 524 T_ACCUM 525 { 526 if (accumulator.symbol != NULL) { 527 stop("Only one accumulator definition allowed", 528 EX_DATAERR); 529 /* NOTREACHED */ 530 } 531 accumulator.symbol = cur_symbol; 532 } 533 ; 534 535 mode_pointer: 536 T_MODE_PTR 537 { 538 if (mode_ptr.symbol != NULL) { 539 stop("Only one mode pointer definition allowed", 540 EX_DATAERR); 541 /* NOTREACHED */ 542 } 543 mode_ptr.symbol = cur_symbol; 544 } 545 ; 546 547 allones: 548 T_ALLONES 549 { 550 if (allones.symbol != NULL) { 551 stop("Only one definition of allones allowed", 552 EX_DATAERR); 553 /* NOTREACHED */ 554 } 555 allones.symbol = cur_symbol; 556 } 557 ; 558 559 allzeros: 560 T_ALLZEROS 561 { 562 if (allzeros.symbol != NULL) { 563 stop("Only one definition of allzeros allowed", 564 EX_DATAERR); 565 /* NOTREACHED */ 566 } 567 allzeros.symbol = cur_symbol; 568 } 569 ; 570 571 none: 572 T_NONE 573 { 574 if (none.symbol != NULL) { 575 stop("Only one definition of none allowed", 576 EX_DATAERR); 577 /* NOTREACHED */ 578 } 579 none.symbol = cur_symbol; 580 } 581 ; 582 583 sindex: 584 T_SINDEX 585 { 586 if (sindex.symbol != NULL) { 587 stop("Only one definition of sindex allowed", 588 EX_DATAERR); 589 /* NOTREACHED */ 590 } 591 sindex.symbol = cur_symbol; 592 } 593 ; 594 595 expression: 596 expression '|' expression 597 { 598 $$.value = $1.value | $3.value; 599 symlist_merge(&$$.referenced_syms, 600 &$1.referenced_syms, 601 &$3.referenced_syms); 602 } 603 | expression '&' expression 604 { 605 $$.value = $1.value & $3.value; 606 symlist_merge(&$$.referenced_syms, 607 &$1.referenced_syms, 608 &$3.referenced_syms); 609 } 610 | expression '+' expression 611 { 612 $$.value = $1.value + $3.value; 613 symlist_merge(&$$.referenced_syms, 614 &$1.referenced_syms, 615 &$3.referenced_syms); 616 } 617 | expression '-' expression 618 { 619 $$.value = $1.value - $3.value; 620 symlist_merge(&($$.referenced_syms), 621 &($1.referenced_syms), 622 &($3.referenced_syms)); 623 } 624 | expression '*' expression 625 { 626 $$.value = $1.value * $3.value; 627 symlist_merge(&($$.referenced_syms), 628 &($1.referenced_syms), 629 &($3.referenced_syms)); 630 } 631 | expression '/' expression 632 { 633 $$.value = $1.value / $3.value; 634 symlist_merge(&($$.referenced_syms), 635 &($1.referenced_syms), 636 &($3.referenced_syms)); 637 } 638 | expression T_EXPR_LSHIFT expression 639 { 640 $$.value = $1.value << $3.value; 641 symlist_merge(&$$.referenced_syms, 642 &$1.referenced_syms, 643 &$3.referenced_syms); 644 } 645 | expression T_EXPR_RSHIFT expression 646 { 647 $$.value = $1.value >> $3.value; 648 symlist_merge(&$$.referenced_syms, 649 &$1.referenced_syms, 650 &$3.referenced_syms); 651 } 652 | '(' expression ')' 653 { 654 $$ = $2; 655 } 656 | '~' expression 657 { 658 $$ = $2; 659 $$.value = (~$$.value) & 0xFF; 660 } 661 | '-' expression %prec UMINUS 662 { 663 $$ = $2; 664 $$.value = -$$.value; 665 } 666 | T_NUMBER 667 { 668 $$.value = $1; 669 SLIST_INIT(&$$.referenced_syms); 670 } 671 | T_SYMBOL 672 { 673 symbol_t *symbol; 674 675 symbol = $1; 676 switch (symbol->type) { 677 case ALIAS: 678 symbol = $1->info.ainfo->parent; 679 case REGISTER: 680 case SCBLOC: 681 case SRAMLOC: 682 $$.value = symbol->info.rinfo->address; 683 break; 684 case MASK: 685 case FIELD: 686 case ENUM: 687 case ENUM_ENTRY: 688 $$.value = symbol->info.finfo->value; 689 break; 690 case DOWNLOAD_CONST: 691 case CONST: 692 $$.value = symbol->info.cinfo->value; 693 break; 694 case UNINITIALIZED: 695 default: 696 { 697 snprintf(errbuf, sizeof(errbuf), 698 "Undefined symbol %s referenced", 699 symbol->name); 700 stop(errbuf, EX_DATAERR); 701 /* NOTREACHED */ 702 break; 703 } 704 } 705 SLIST_INIT(&$$.referenced_syms); 706 symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 707 } 708 ; 709 710 constant: 711 T_CONST T_SYMBOL expression 712 { 713 if ($2->type != UNINITIALIZED) { 714 stop("Re-definition of symbol as a constant", 715 EX_DATAERR); 716 /* NOTREACHED */ 717 } 718 $2->type = CONST; 719 initialize_symbol($2); 720 $2->info.cinfo->value = $3.value; 721 } 722 | T_CONST T_SYMBOL T_DOWNLOAD 723 { 724 if ($1) { 725 stop("Invalid downloaded constant declaration", 726 EX_DATAERR); 727 /* NOTREACHED */ 728 } 729 if ($2->type != UNINITIALIZED) { 730 stop("Re-definition of symbol as a downloaded constant", 731 EX_DATAERR); 732 /* NOTREACHED */ 733 } 734 $2->type = DOWNLOAD_CONST; 735 initialize_symbol($2); 736 $2->info.cinfo->value = download_constant_count++; 737 } 738 ; 739 740 macrodefn_prologue: 741 T_DEFINE T_SYMBOL 742 { 743 if ($2->type != UNINITIALIZED) { 744 stop("Re-definition of symbol as a macro", 745 EX_DATAERR); 746 /* NOTREACHED */ 747 } 748 cur_symbol = $2; 749 cur_symbol->type = MACRO; 750 initialize_symbol(cur_symbol); 751 } 752 ; 753 754 macrodefn: 755 macrodefn_prologue T_MACROBODY 756 { 757 add_macro_body($2); 758 } 759 | macrodefn_prologue '(' macro_arglist ')' T_MACROBODY 760 { 761 add_macro_body($5); 762 cur_symbol->info.macroinfo->narg = $3; 763 } 764 ; 765 766 macro_arglist: 767 { 768 /* Macros can take no arguments */ 769 $$ = 0; 770 } 771 | T_ARG 772 { 773 $$ = 1; 774 add_macro_arg($1, 0); 775 } 776 | macro_arglist ',' T_ARG 777 { 778 if ($1 == 0) { 779 stop("Comma without preceding argument in arg list", 780 EX_DATAERR); 781 /* NOTREACHED */ 782 } 783 $$ = $1 + 1; 784 add_macro_arg($3, $1); 785 } 786 ; 787 788 scratch_ram: 789 T_SRAM '{' 790 { 791 snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 792 num_srams); 793 cur_symbol = symtable_get(SRAM_SYMNAME); 794 cur_symtype = SRAMLOC; 795 cur_symbol->type = SRAMLOC; 796 initialize_symbol(cur_symbol); 797 } 798 reg_address 799 { 800 sram_or_scb_offset = cur_symbol->info.rinfo->address; 801 } 802 size 803 { 804 scb_or_sram_symbol = cur_symbol; 805 } 806 scb_or_sram_attributes 807 '}' 808 { 809 cur_symbol = NULL; 810 scb_or_sram_symbol = NULL; 811 } 812 ; 813 814 scb: 815 T_SCB '{' 816 { 817 cur_symbol = symtable_get(SCB_SYMNAME); 818 cur_symtype = SCBLOC; 819 if (cur_symbol->type != UNINITIALIZED) { 820 stop("Only one SRAM definition allowed", 821 EX_SOFTWARE); 822 /* NOTREACHED */ 823 } 824 cur_symbol->type = SCBLOC; 825 initialize_symbol(cur_symbol); 826 /* 64 bytes of SCB space */ 827 cur_symbol->info.rinfo->size = 64; 828 } 829 reg_address 830 { 831 sram_or_scb_offset = cur_symbol->info.rinfo->address; 832 } 833 size 834 { 835 scb_or_sram_symbol = cur_symbol; 836 } 837 scb_or_sram_attributes 838 '}' 839 { 840 cur_symbol = NULL; 841 scb_or_sram_symbol = NULL; 842 } 843 ; 844 845 scb_or_sram_attributes: 846 /* NULL definition is okay */ 847 | modes 848 | scb_or_sram_reg_list 849 | modes scb_or_sram_reg_list 850 ; 851 852 scb_or_sram_reg_list: 853 reg_definition 854 | scb_or_sram_reg_list reg_definition 855 ; 856 857 reg_symbol: 858 T_SYMBOL 859 { 860 process_register(&$1); 861 $$.symbol = $1; 862 $$.offset = 0; 863 } 864 | T_SYMBOL '[' T_SYMBOL ']' 865 { 866 process_register(&$1); 867 if ($3->type != CONST) { 868 stop("register offset must be a constant", EX_DATAERR); 869 /* NOTREACHED */ 870 } 871 if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { 872 stop("Accessing offset beyond range of register", 873 EX_DATAERR); 874 /* NOTREACHED */ 875 } 876 $$.symbol = $1; 877 $$.offset = $3->info.cinfo->value; 878 } 879 | T_SYMBOL '[' T_NUMBER ']' 880 { 881 process_register(&$1); 882 if (($3 + 1) > $1->info.rinfo->size) { 883 stop("Accessing offset beyond range of register", 884 EX_DATAERR); 885 /* NOTREACHED */ 886 } 887 $$.symbol = $1; 888 $$.offset = $3; 889 } 890 | T_A 891 { 892 if (accumulator.symbol == NULL) { 893 stop("No accumulator has been defined", EX_DATAERR); 894 /* NOTREACHED */ 895 } 896 $$.symbol = accumulator.symbol; 897 $$.offset = 0; 898 } 899 ; 900 901 destination: 902 reg_symbol 903 { 904 test_writable_symbol($1.symbol); 905 $$ = $1; 906 } 907 ; 908 909 immediate: 910 expression 911 { $$ = $1; } 912 ; 913 914 immediate_or_a: 915 expression 916 { 917 if ($1.value == 0 && is_download_const(&$1) == 0) { 918 snprintf(errbuf, sizeof(errbuf), 919 "\nExpression evaluates to 0 and thus " 920 "references the accumulator.\n " 921 "If this is the desired effect, use 'A' " 922 "instead.\n"); 923 stop(errbuf, EX_DATAERR); 924 } 925 $$ = $1; 926 } 927 | T_A 928 { 929 SLIST_INIT(&$$.referenced_syms); 930 symlist_add(&$$.referenced_syms, accumulator.symbol, 931 SYMLIST_INSERT_HEAD); 932 $$.value = 0; 933 } 934 ; 935 936 source: 937 reg_symbol 938 { 939 test_readable_symbol($1.symbol); 940 $$ = $1; 941 } 942 ; 943 944 opt_source: 945 { 946 $$.symbol = NULL; 947 $$.offset = 0; 948 } 949 | ',' source 950 { $$ = $2; } 951 ; 952 953 ret: 954 { $$ = 0; } 955 | T_RET 956 { $$ = 1; } 957 ; 958 959 set_src_mode: 960 T_SET_SRC_MODE T_NUMBER ';' 961 { 962 src_mode = $2; 963 } 964 ; 965 966 set_dst_mode: 967 T_SET_DST_MODE T_NUMBER ';' 968 { 969 dst_mode = $2; 970 } 971 ; 972 973 critical_section_start: 974 T_BEGIN_CS ';' 975 { 976 critical_section_t *cs; 977 978 if (in_critical_section != FALSE) { 979 stop("Critical Section within Critical Section", 980 EX_DATAERR); 981 /* NOTREACHED */ 982 } 983 cs = cs_alloc(); 984 cs->begin_addr = instruction_ptr; 985 in_critical_section = TRUE; 986 } 987 ; 988 989 critical_section_end: 990 T_END_CS ';' 991 { 992 critical_section_t *cs; 993 994 if (in_critical_section == FALSE) { 995 stop("Unballanced 'end_cs'", EX_DATAERR); 996 /* NOTREACHED */ 997 } 998 cs = TAILQ_LAST(&cs_tailq, cs_tailq); 999 cs->end_addr = instruction_ptr; 1000 in_critical_section = FALSE; 1001 } 1002 ; 1003 1004 export: 1005 { $$ = 0; } 1006 | T_EXPORT 1007 { $$ = 1; } 1008 ; 1009 1010 label: 1011 export T_SYMBOL ':' 1012 { 1013 if ($2->type != UNINITIALIZED) { 1014 stop("Program label multiply defined", EX_DATAERR); 1015 /* NOTREACHED */ 1016 } 1017 $2->type = LABEL; 1018 initialize_symbol($2); 1019 $2->info.linfo->address = instruction_ptr; 1020 $2->info.linfo->exported = $1; 1021 } 1022 ; 1023 1024 address: 1025 T_SYMBOL 1026 { 1027 $$.symbol = $1; 1028 $$.offset = 0; 1029 } 1030 | T_SYMBOL '+' T_NUMBER 1031 { 1032 $$.symbol = $1; 1033 $$.offset = $3; 1034 } 1035 | T_SYMBOL '-' T_NUMBER 1036 { 1037 $$.symbol = $1; 1038 $$.offset = -$3; 1039 } 1040 | '.' 1041 { 1042 $$.symbol = NULL; 1043 $$.offset = 0; 1044 } 1045 | '.' '+' T_NUMBER 1046 { 1047 $$.symbol = NULL; 1048 $$.offset = $3; 1049 } 1050 | '.' '-' T_NUMBER 1051 { 1052 $$.symbol = NULL; 1053 $$.offset = -$3; 1054 } 1055 ; 1056 1057 conditional: 1058 T_IF T_CEXPR '{' 1059 { 1060 scope_t *new_scope; 1061 1062 add_conditional($2); 1063 new_scope = scope_alloc(); 1064 new_scope->type = SCOPE_IF; 1065 new_scope->begin_addr = instruction_ptr; 1066 new_scope->func_num = $2->info.condinfo->func_num; 1067 } 1068 | T_ELSE T_IF T_CEXPR '{' 1069 { 1070 scope_t *new_scope; 1071 scope_t *scope_context; 1072 scope_t *last_scope; 1073 1074 /* 1075 * Ensure that the previous scope is either an 1076 * if or and else if. 1077 */ 1078 scope_context = SLIST_FIRST(&scope_stack); 1079 last_scope = TAILQ_LAST(&scope_context->inner_scope, 1080 scope_tailq); 1081 if (last_scope == NULL 1082 || last_scope->type == T_ELSE) { 1083 1084 stop("'else if' without leading 'if'", EX_DATAERR); 1085 /* NOTREACHED */ 1086 } 1087 add_conditional($3); 1088 new_scope = scope_alloc(); 1089 new_scope->type = SCOPE_ELSE_IF; 1090 new_scope->begin_addr = instruction_ptr; 1091 new_scope->func_num = $3->info.condinfo->func_num; 1092 } 1093 | T_ELSE '{' 1094 { 1095 scope_t *new_scope; 1096 scope_t *scope_context; 1097 scope_t *last_scope; 1098 1099 /* 1100 * Ensure that the previous scope is either an 1101 * if or and else if. 1102 */ 1103 scope_context = SLIST_FIRST(&scope_stack); 1104 last_scope = TAILQ_LAST(&scope_context->inner_scope, 1105 scope_tailq); 1106 if (last_scope == NULL 1107 || last_scope->type == SCOPE_ELSE) { 1108 1109 stop("'else' without leading 'if'", EX_DATAERR); 1110 /* NOTREACHED */ 1111 } 1112 new_scope = scope_alloc(); 1113 new_scope->type = SCOPE_ELSE; 1114 new_scope->begin_addr = instruction_ptr; 1115 } 1116 ; 1117 1118 conditional: 1119 '}' 1120 { 1121 scope_t *scope_context; 1122 1123 scope_context = SLIST_FIRST(&scope_stack); 1124 if (scope_context->type == SCOPE_ROOT) { 1125 stop("Unexpected '}' encountered", EX_DATAERR); 1126 /* NOTREACHED */ 1127 } 1128 1129 scope_context->end_addr = instruction_ptr; 1130 1131 /* Pop the scope */ 1132 SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 1133 1134 process_scope(scope_context); 1135 1136 if (SLIST_FIRST(&scope_stack) == NULL) { 1137 stop("Unexpected '}' encountered", EX_DATAERR); 1138 /* NOTREACHED */ 1139 } 1140 } 1141 ; 1142 1143 f1_opcode: 1144 T_AND { $$ = AIC_OP_AND; } 1145 | T_XOR { $$ = AIC_OP_XOR; } 1146 | T_ADD { $$ = AIC_OP_ADD; } 1147 | T_ADC { $$ = AIC_OP_ADC; } 1148 ; 1149 1150 code: 1151 f1_opcode destination ',' immediate_or_a opt_source ret ';' 1152 { 1153 format_1_instr($1, &$2, &$4, &$5, $6); 1154 } 1155 ; 1156 1157 code: 1158 T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 1159 { 1160 format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 1161 } 1162 ; 1163 1164 code: 1165 T_INC destination opt_source ret ';' 1166 { 1167 expression_t immed; 1168 1169 make_expression(&immed, 1); 1170 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1171 } 1172 ; 1173 1174 code: 1175 T_DEC destination opt_source ret ';' 1176 { 1177 expression_t immed; 1178 1179 make_expression(&immed, -1); 1180 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1181 } 1182 ; 1183 1184 code: 1185 T_CLC ret ';' 1186 { 1187 expression_t immed; 1188 1189 make_expression(&immed, -1); 1190 format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 1191 } 1192 | T_CLC T_MVI destination ',' immediate_or_a ret ';' 1193 { 1194 format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 1195 } 1196 ; 1197 1198 code: 1199 T_STC ret ';' 1200 { 1201 expression_t immed; 1202 1203 make_expression(&immed, 1); 1204 format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 1205 } 1206 | T_STC destination ret ';' 1207 { 1208 expression_t immed; 1209 1210 make_expression(&immed, 1); 1211 format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 1212 } 1213 ; 1214 1215 code: 1216 T_BMOV destination ',' source ',' immediate ret ';' 1217 { 1218 format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 1219 } 1220 ; 1221 1222 code: 1223 T_MOV destination ',' source ret ';' 1224 { 1225 expression_t immed; 1226 1227 make_expression(&immed, 1); 1228 format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 1229 } 1230 ; 1231 1232 code: 1233 T_MVI destination ',' immediate ret ';' 1234 { 1235 if ($4.value == 0 1236 && is_download_const(&$4) == 0) { 1237 expression_t immed; 1238 1239 /* 1240 * Allow move immediates of 0 so that macros, 1241 * that can't know the immediate's value and 1242 * otherwise compensate, still work. 1243 */ 1244 make_expression(&immed, 1); 1245 format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5); 1246 } else { 1247 format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 1248 } 1249 } 1250 ; 1251 1252 code: 1253 T_NOT destination opt_source ret ';' 1254 { 1255 expression_t immed; 1256 1257 make_expression(&immed, 0xff); 1258 format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 1259 } 1260 ; 1261 1262 code: 1263 T_CLR destination ret ';' 1264 { 1265 expression_t immed; 1266 1267 make_expression(&immed, 0xff); 1268 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 1269 } 1270 ; 1271 1272 code: 1273 T_NOP ret ';' 1274 { 1275 expression_t immed; 1276 1277 make_expression(&immed, 0xff); 1278 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 1279 } 1280 ; 1281 1282 code: 1283 T_RET ';' 1284 { 1285 expression_t immed; 1286 1287 make_expression(&immed, 0xff); 1288 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 1289 } 1290 ; 1291 1292 /* 1293 * This grammer differs from the one in the aic7xxx 1294 * reference manual since the grammer listed there is 1295 * ambiguous and causes a shift/reduce conflict. 1296 * It also seems more logical as the "immediate" 1297 * argument is listed as the second arg like the 1298 * other formats. 1299 */ 1300 1301 f2_opcode: 1302 T_SHL { $$ = AIC_OP_SHL; } 1303 | T_SHR { $$ = AIC_OP_SHR; } 1304 | T_ROL { $$ = AIC_OP_ROL; } 1305 | T_ROR { $$ = AIC_OP_ROR; } 1306 ; 1307 1308 code: 1309 f2_opcode destination ',' expression opt_source ret ';' 1310 { 1311 format_2_instr($1, &$2, &$4, &$5, $6); 1312 } 1313 ; 1314 1315 jmp_jc_jnc_call: 1316 T_JMP { $$ = AIC_OP_JMP; } 1317 | T_JC { $$ = AIC_OP_JC; } 1318 | T_JNC { $$ = AIC_OP_JNC; } 1319 | T_CALL { $$ = AIC_OP_CALL; } 1320 ; 1321 1322 jz_jnz: 1323 T_JZ { $$ = AIC_OP_JZ; } 1324 | T_JNZ { $$ = AIC_OP_JNZ; } 1325 ; 1326 1327 je_jne: 1328 T_JE { $$ = AIC_OP_JE; } 1329 | T_JNE { $$ = AIC_OP_JNE; } 1330 ; 1331 1332 code: 1333 jmp_jc_jnc_call address ';' 1334 { 1335 expression_t immed; 1336 1337 make_expression(&immed, 0); 1338 format_3_instr($1, &sindex, &immed, &$2); 1339 } 1340 ; 1341 1342 code: 1343 T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 1344 { 1345 format_3_instr($5, &$2, &$4, &$6); 1346 } 1347 ; 1348 1349 code: 1350 T_TEST source ',' immediate_or_a jz_jnz address ';' 1351 { 1352 format_3_instr($5, &$2, &$4, &$6); 1353 } 1354 ; 1355 1356 code: 1357 T_CMP source ',' immediate_or_a je_jne address ';' 1358 { 1359 format_3_instr($5, &$2, &$4, &$6); 1360 } 1361 ; 1362 1363 code: 1364 T_MOV source jmp_jc_jnc_call address ';' 1365 { 1366 expression_t immed; 1367 1368 make_expression(&immed, 0); 1369 format_3_instr($3, &$2, &immed, &$4); 1370 } 1371 ; 1372 1373 code: 1374 T_MVI immediate jmp_jc_jnc_call address ';' 1375 { 1376 format_3_instr($3, &allzeros, &$2, &$4); 1377 } 1378 ; 1379 1380 %% 1381 1382 static void 1383 process_field(int field_type, symbol_t *sym, int value) 1384 { 1385 /* 1386 * Add the current register to its 1387 * symbol list, if it already exists, 1388 * warn if we are setting it to a 1389 * different value, or in the bit to 1390 * the "allowed bits" of this register. 1391 */ 1392 if (sym->type == UNINITIALIZED) { 1393 sym->type = field_type; 1394 initialize_symbol(sym); 1395 sym->info.finfo->value = value; 1396 if (field_type != ENUM_ENTRY) { 1397 if (field_type != MASK && value == 0) { 1398 stop("Empty Field, or Enum", EX_DATAERR); 1399 /* NOTREACHED */ 1400 } 1401 sym->info.finfo->value = value; 1402 sym->info.finfo->mask = value; 1403 } else if (field_symbol != NULL) { 1404 sym->info.finfo->mask = field_symbol->info.finfo->value; 1405 } else { 1406 sym->info.finfo->mask = 0xFF; 1407 } 1408 } else if (sym->type != field_type) { 1409 stop("Field definition mirrors a definition of the same " 1410 " name, but a different type", EX_DATAERR); 1411 /* NOTREACHED */ 1412 } else if (value != sym->info.finfo->value) { 1413 stop("Field redefined with a conflicting value", EX_DATAERR); 1414 /* NOTREACHED */ 1415 } 1416 /* Fail if this symbol is already listed */ 1417 if (symlist_search(&(sym->info.finfo->symrefs), 1418 cur_symbol->name) != NULL) { 1419 stop("Field defined multiple times for register", EX_DATAERR); 1420 /* NOTREACHED */ 1421 } 1422 symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 1423 SYMLIST_INSERT_HEAD); 1424 cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 1425 cur_symbol->info.rinfo->typecheck_masks = TRUE; 1426 symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 1427 } 1428 1429 static void 1430 initialize_symbol(symbol_t *symbol) 1431 { 1432 switch (symbol->type) { 1433 case UNINITIALIZED: 1434 stop("Call to initialize_symbol with type field unset", 1435 EX_SOFTWARE); 1436 /* NOTREACHED */ 1437 break; 1438 case REGISTER: 1439 case SRAMLOC: 1440 case SCBLOC: 1441 symbol->info.rinfo = 1442 (struct reg_info *)malloc(sizeof(struct reg_info)); 1443 if (symbol->info.rinfo == NULL) { 1444 stop("Can't create register info", EX_SOFTWARE); 1445 /* NOTREACHED */ 1446 } 1447 memset(symbol->info.rinfo, 0, 1448 sizeof(struct reg_info)); 1449 SLIST_INIT(&(symbol->info.rinfo->fields)); 1450 /* 1451 * Default to allowing access in all register modes 1452 * or to the mode specified by the SCB or SRAM space 1453 * we are in. 1454 */ 1455 if (scb_or_sram_symbol != NULL) 1456 symbol->info.rinfo->modes = 1457 scb_or_sram_symbol->info.rinfo->modes; 1458 else 1459 symbol->info.rinfo->modes = ~0; 1460 break; 1461 case ALIAS: 1462 symbol->info.ainfo = 1463 (struct alias_info *)malloc(sizeof(struct alias_info)); 1464 if (symbol->info.ainfo == NULL) { 1465 stop("Can't create alias info", EX_SOFTWARE); 1466 /* NOTREACHED */ 1467 } 1468 memset(symbol->info.ainfo, 0, 1469 sizeof(struct alias_info)); 1470 break; 1471 case MASK: 1472 case FIELD: 1473 case ENUM: 1474 case ENUM_ENTRY: 1475 symbol->info.finfo = 1476 (struct field_info *)malloc(sizeof(struct field_info)); 1477 if (symbol->info.finfo == NULL) { 1478 stop("Can't create field info", EX_SOFTWARE); 1479 /* NOTREACHED */ 1480 } 1481 memset(symbol->info.finfo, 0, sizeof(struct field_info)); 1482 SLIST_INIT(&(symbol->info.finfo->symrefs)); 1483 break; 1484 case CONST: 1485 case DOWNLOAD_CONST: 1486 symbol->info.cinfo = 1487 (struct const_info *)malloc(sizeof(struct const_info)); 1488 if (symbol->info.cinfo == NULL) { 1489 stop("Can't create alias info", EX_SOFTWARE); 1490 /* NOTREACHED */ 1491 } 1492 memset(symbol->info.cinfo, 0, 1493 sizeof(struct const_info)); 1494 break; 1495 case LABEL: 1496 symbol->info.linfo = 1497 (struct label_info *)malloc(sizeof(struct label_info)); 1498 if (symbol->info.linfo == NULL) { 1499 stop("Can't create label info", EX_SOFTWARE); 1500 /* NOTREACHED */ 1501 } 1502 memset(symbol->info.linfo, 0, 1503 sizeof(struct label_info)); 1504 break; 1505 case CONDITIONAL: 1506 symbol->info.condinfo = 1507 (struct cond_info *)malloc(sizeof(struct cond_info)); 1508 if (symbol->info.condinfo == NULL) { 1509 stop("Can't create conditional info", EX_SOFTWARE); 1510 /* NOTREACHED */ 1511 } 1512 memset(symbol->info.condinfo, 0, 1513 sizeof(struct cond_info)); 1514 break; 1515 case MACRO: 1516 symbol->info.macroinfo = 1517 (struct macro_info *)malloc(sizeof(struct macro_info)); 1518 if (symbol->info.macroinfo == NULL) { 1519 stop("Can't create macro info", EX_SOFTWARE); 1520 /* NOTREACHED */ 1521 } 1522 memset(symbol->info.macroinfo, 0, 1523 sizeof(struct macro_info)); 1524 TAILQ_INIT(&symbol->info.macroinfo->args); 1525 break; 1526 default: 1527 stop("Call to initialize_symbol with invalid symbol type", 1528 EX_SOFTWARE); 1529 /* NOTREACHED */ 1530 break; 1531 } 1532 } 1533 1534 static void 1535 add_macro_arg(const char *argtext, int argnum) 1536 { 1537 struct macro_arg *marg; 1538 int i; 1539 int retval; 1540 1541 1542 if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1543 stop("Invalid current symbol for adding macro arg", 1544 EX_SOFTWARE); 1545 /* NOTREACHED */ 1546 } 1547 1548 marg = (struct macro_arg *)malloc(sizeof(*marg)); 1549 if (marg == NULL) { 1550 stop("Can't create macro_arg structure", EX_SOFTWARE); 1551 /* NOTREACHED */ 1552 } 1553 marg->replacement_text = NULL; 1554 retval = snprintf(regex_pattern, sizeof(regex_pattern), 1555 "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 1556 argtext); 1557 if (retval == -1 || retval >= sizeof(regex_pattern)) { 1558 stop("Regex text buffer too small for arg", 1559 EX_SOFTWARE); 1560 /* NOTREACHED */ 1561 } 1562 retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 1563 if (retval != 0) { 1564 stop("Regex compilation failed", EX_SOFTWARE); 1565 /* NOTREACHED */ 1566 } 1567 TAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 1568 } 1569 1570 static void 1571 add_macro_body(const char *bodytext) 1572 { 1573 if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1574 stop("Invalid current symbol for adding macro arg", 1575 EX_SOFTWARE); 1576 /* NOTREACHED */ 1577 } 1578 cur_symbol->info.macroinfo->body = strdup(bodytext); 1579 if (cur_symbol->info.macroinfo->body == NULL) { 1580 stop("Can't duplicate macro body text", EX_SOFTWARE); 1581 /* NOTREACHED */ 1582 } 1583 } 1584 1585 static void 1586 process_register(symbol_t **p_symbol) 1587 { 1588 symbol_t *symbol = *p_symbol; 1589 1590 if (symbol->type == UNINITIALIZED) { 1591 snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 1592 symbol->name); 1593 stop(errbuf, EX_DATAERR); 1594 /* NOTREACHED */ 1595 } else if (symbol->type == ALIAS) { 1596 *p_symbol = symbol->info.ainfo->parent; 1597 } else if ((symbol->type != REGISTER) 1598 && (symbol->type != SCBLOC) 1599 && (symbol->type != SRAMLOC)) { 1600 snprintf(errbuf, sizeof(errbuf), 1601 "Specified symbol %s is not a register", 1602 symbol->name); 1603 stop(errbuf, EX_DATAERR); 1604 } 1605 } 1606 1607 static void 1608 format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 1609 symbol_ref_t *src, int ret) 1610 { 1611 struct instruction *instr; 1612 struct ins_format1 *f1_instr; 1613 1614 if (src->symbol == NULL) 1615 src = dest; 1616 1617 /* Test register permissions */ 1618 test_writable_symbol(dest->symbol); 1619 test_readable_symbol(src->symbol); 1620 1621 /* Ensure that immediate makes sense for this destination */ 1622 type_check(dest->symbol, immed, opcode); 1623 1624 /* Allocate sequencer space for the instruction and fill it out */ 1625 instr = seq_alloc(); 1626 f1_instr = &instr->format.format1; 1627 f1_instr->ret = ret ? 1 : 0; 1628 f1_instr->opcode = opcode; 1629 f1_instr->destination = dest->symbol->info.rinfo->address 1630 + dest->offset; 1631 f1_instr->source = src->symbol->info.rinfo->address 1632 + src->offset; 1633 f1_instr->immediate = immed->value; 1634 1635 if (is_download_const(immed)) 1636 f1_instr->parity = 1; 1637 else if (dest->symbol == mode_ptr.symbol) { 1638 u_int src_value; 1639 u_int dst_value; 1640 1641 /* 1642 * Attempt to update mode information if 1643 * we are operating on the mode register. 1644 */ 1645 if (src->symbol == allones.symbol) 1646 src_value = 0xFF; 1647 else if (src->symbol == allzeros.symbol) 1648 src_value = 0; 1649 else if (src->symbol == mode_ptr.symbol) 1650 src_value = (dst_mode << 4) | src_mode; 1651 else 1652 goto cant_update; 1653 1654 switch (opcode) { 1655 case AIC_OP_AND: 1656 dst_value = src_value & immed->value; 1657 break; 1658 case AIC_OP_XOR: 1659 dst_value = src_value ^ immed->value; 1660 break; 1661 case AIC_OP_ADD: 1662 dst_value = (src_value + immed->value) & 0xFF; 1663 break; 1664 case AIC_OP_OR: 1665 dst_value = src_value | immed->value; 1666 break; 1667 case AIC_OP_BMOV: 1668 dst_value = src_value; 1669 break; 1670 default: 1671 goto cant_update; 1672 } 1673 src_mode = dst_value & 0xF; 1674 dst_mode = (dst_value >> 4) & 0xF; 1675 } 1676 1677 cant_update: 1678 symlist_free(&immed->referenced_syms); 1679 instruction_ptr++; 1680 } 1681 1682 static void 1683 format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 1684 symbol_ref_t *src, int ret) 1685 { 1686 struct instruction *instr; 1687 struct ins_format2 *f2_instr; 1688 uint8_t shift_control; 1689 1690 if (src->symbol == NULL) 1691 src = dest; 1692 1693 /* Test register permissions */ 1694 test_writable_symbol(dest->symbol); 1695 test_readable_symbol(src->symbol); 1696 1697 /* Allocate sequencer space for the instruction and fill it out */ 1698 instr = seq_alloc(); 1699 f2_instr = &instr->format.format2; 1700 f2_instr->ret = ret ? 1 : 0; 1701 f2_instr->opcode = AIC_OP_ROL; 1702 f2_instr->destination = dest->symbol->info.rinfo->address 1703 + dest->offset; 1704 f2_instr->source = src->symbol->info.rinfo->address 1705 + src->offset; 1706 if (places->value > 8 || places->value <= 0) { 1707 stop("illegal shift value", EX_DATAERR); 1708 /* NOTREACHED */ 1709 } 1710 switch (opcode) { 1711 case AIC_OP_SHL: 1712 if (places->value == 8) 1713 shift_control = 0xf0; 1714 else 1715 shift_control = (places->value << 4) | places->value; 1716 break; 1717 case AIC_OP_SHR: 1718 if (places->value == 8) { 1719 shift_control = 0xf8; 1720 } else { 1721 shift_control = (places->value << 4) 1722 | (8 - places->value) 1723 | 0x08; 1724 } 1725 break; 1726 case AIC_OP_ROL: 1727 shift_control = places->value & 0x7; 1728 break; 1729 case AIC_OP_ROR: 1730 shift_control = (8 - places->value) | 0x08; 1731 break; 1732 default: 1733 shift_control = 0; /* Quiet Compiler */ 1734 stop("Invalid shift operation specified", EX_SOFTWARE); 1735 /* NOTREACHED */ 1736 break; 1737 }; 1738 f2_instr->shift_control = shift_control; 1739 symlist_free(&places->referenced_syms); 1740 instruction_ptr++; 1741 } 1742 1743 static void 1744 format_3_instr(int opcode, symbol_ref_t *src, 1745 expression_t *immed, symbol_ref_t *address) 1746 { 1747 struct instruction *instr; 1748 struct ins_format3 *f3_instr; 1749 int addr; 1750 1751 /* Test register permissions */ 1752 test_readable_symbol(src->symbol); 1753 1754 /* Ensure that immediate makes sense for this source */ 1755 type_check(src->symbol, immed, opcode); 1756 1757 /* Allocate sequencer space for the instruction and fill it out */ 1758 instr = seq_alloc(); 1759 f3_instr = &instr->format.format3; 1760 if (address->symbol == NULL) { 1761 /* 'dot' referrence. Use the current instruction pointer */ 1762 addr = instruction_ptr + address->offset; 1763 } else if (address->symbol->type == UNINITIALIZED) { 1764 /* forward reference */ 1765 addr = address->offset; 1766 instr->patch_label = address->symbol; 1767 } else 1768 addr = address->symbol->info.linfo->address + address->offset; 1769 f3_instr->opcode = opcode; 1770 f3_instr->address = addr; 1771 f3_instr->source = src->symbol->info.rinfo->address 1772 + src->offset; 1773 f3_instr->immediate = immed->value; 1774 1775 if (is_download_const(immed)) 1776 f3_instr->parity = 1; 1777 1778 symlist_free(&immed->referenced_syms); 1779 instruction_ptr++; 1780 } 1781 1782 static void 1783 test_readable_symbol(symbol_t *symbol) 1784 { 1785 1786 if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 1787 snprintf(errbuf, sizeof(errbuf), 1788 "Register %s unavailable in source reg mode %d", 1789 symbol->name, src_mode); 1790 stop(errbuf, EX_DATAERR); 1791 } 1792 1793 if (symbol->info.rinfo->mode == WO) { 1794 stop("Write Only register specified as source", 1795 EX_DATAERR); 1796 /* NOTREACHED */ 1797 } 1798 } 1799 1800 static void 1801 test_writable_symbol(symbol_t *symbol) 1802 { 1803 1804 if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 1805 snprintf(errbuf, sizeof(errbuf), 1806 "Register %s unavailable in destination reg mode %d", 1807 symbol->name, dst_mode); 1808 stop(errbuf, EX_DATAERR); 1809 } 1810 1811 if (symbol->info.rinfo->mode == RO) { 1812 stop("Read Only register specified as destination", 1813 EX_DATAERR); 1814 /* NOTREACHED */ 1815 } 1816 } 1817 1818 static void 1819 type_check(symbol_t *symbol, expression_t *expression, int opcode) 1820 { 1821 symbol_node_t *node; 1822 int and_op; 1823 1824 and_op = FALSE; 1825 if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) 1826 and_op = TRUE; 1827 1828 /* 1829 * Make sure that we aren't attempting to write something 1830 * that hasn't been defined. If this is an and operation, 1831 * this is a mask, so "undefined" bits are okay. 1832 */ 1833 if (and_op == FALSE 1834 && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { 1835 snprintf(errbuf, sizeof(errbuf), 1836 "Invalid bit(s) 0x%x in immediate written to %s", 1837 expression->value & ~symbol->info.rinfo->valid_bitmask, 1838 symbol->name); 1839 stop(errbuf, EX_DATAERR); 1840 /* NOTREACHED */ 1841 } 1842 1843 /* 1844 * Now make sure that all of the symbols referenced by the 1845 * expression are defined for this register. 1846 */ 1847 if (symbol->info.rinfo->typecheck_masks != FALSE) { 1848 SLIST_FOREACH(node, &expression->referenced_syms, links) { 1849 if ((node->symbol->type == MASK 1850 || node->symbol->type == FIELD 1851 || node->symbol->type == ENUM 1852 || node->symbol->type == ENUM_ENTRY) 1853 && symlist_search(&node->symbol->info.finfo->symrefs, 1854 symbol->name) == NULL) { 1855 snprintf(errbuf, sizeof(errbuf), 1856 "Invalid field or mask %s " 1857 "for register %s", 1858 node->symbol->name, symbol->name); 1859 stop(errbuf, EX_DATAERR); 1860 /* NOTREACHED */ 1861 } 1862 } 1863 } 1864 } 1865 1866 static void 1867 make_expression(expression_t *immed, int value) 1868 { 1869 SLIST_INIT(&immed->referenced_syms); 1870 immed->value = value & 0xff; 1871 } 1872 1873 static void 1874 add_conditional(symbol_t *symbol) 1875 { 1876 static int numfuncs; 1877 1878 if (numfuncs == 0) { 1879 /* add a special conditional, "0" */ 1880 symbol_t *false_func; 1881 1882 false_func = symtable_get("0"); 1883 if (false_func->type != UNINITIALIZED) { 1884 stop("Conditional expression '0' " 1885 "conflicts with a symbol", EX_DATAERR); 1886 /* NOTREACHED */ 1887 } 1888 false_func->type = CONDITIONAL; 1889 initialize_symbol(false_func); 1890 false_func->info.condinfo->func_num = numfuncs++; 1891 symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 1892 } 1893 1894 /* This condition has occurred before */ 1895 if (symbol->type == CONDITIONAL) 1896 return; 1897 1898 if (symbol->type != UNINITIALIZED) { 1899 stop("Conditional expression conflicts with a symbol", 1900 EX_DATAERR); 1901 /* NOTREACHED */ 1902 } 1903 1904 symbol->type = CONDITIONAL; 1905 initialize_symbol(symbol); 1906 symbol->info.condinfo->func_num = numfuncs++; 1907 symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 1908 } 1909 1910 static void 1911 add_version(const char *verstring) 1912 { 1913 const char *q, prefix[] = " * "; 1914 char *p; 1915 int newlen; 1916 int oldlen; 1917 1918 newlen = strlen(verstring) + strlen(prefix); 1919 oldlen = 0; 1920 if (versions != NULL) 1921 oldlen = strlen(versions); 1922 versions = realloc(versions, newlen + oldlen + 2); 1923 if (versions == NULL) 1924 stop("Can't allocate version string", EX_SOFTWARE); 1925 strcpy(&versions[oldlen], prefix); 1926 for (p = &versions[oldlen + strlen(prefix)], q = verstring; *q; q++) { 1927 if (*q == '$') 1928 continue; 1929 *p++ = *q; 1930 } 1931 *p++ = '\n'; 1932 *p = '\0'; 1933 } 1934 1935 void 1936 yyerror(const char *string) 1937 { 1938 stop(string, EX_DATAERR); 1939 } 1940 1941 static int 1942 is_download_const(expression_t *immed) 1943 { 1944 if ((!SLIST_EMPTY(&immed->referenced_syms)) 1945 && (SLIST_FIRST(&immed->referenced_syms)->symbol->type == DOWNLOAD_CONST)) 1946 return (TRUE); 1947 1948 return (FALSE); 1949 } 1950