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