aicasm_gram.y revision 104019
1%{ 2/* 3 * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 4 * 5 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 6 * Copyright (c) 2001, 2002 Adaptec Inc. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions, and the following disclaimer, 14 * without modification. 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16 * substantially similar to the "NO WARRANTY" disclaimer below 17 * ("Disclaimer") and any redistribution must be conditioned upon 18 * including a substantially similar Disclaimer requirement for further 19 * binary redistribution. 20 * 3. Neither the names of the above-listed copyright holders nor the names 21 * of any contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * Alternatively, this software may be distributed under the terms of the 25 * GNU General Public License ("GPL") version 2 as published by the Free 26 * Software Foundation. 27 * 28 * NO WARRANTY 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGES. 40 * 41 * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#24 $ 42 * 43 * $FreeBSD: head/sys/dev/aic7xxx/aicasm/aicasm_gram.y 104019 2002-09-26 21:46:19Z gibbs $ 44 */ 45 46#include <inttypes.h> 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 66int yylineno; 67char *yyfilename; 68char stock_prefix[] = "aic_"; 69char *prefix = stock_prefix; 70char *patch_arg_list; 71char *versions; 72static char errbuf[255]; 73static char regex_pattern[255]; 74static symbol_t *cur_symbol; 75static symbol_t *field_symbol; 76static symbol_t *scb_or_sram_symbol; 77static symtype cur_symtype; 78static symbol_ref_t accumulator; 79static symbol_ref_t mode_ptr; 80static symbol_ref_t allones; 81static symbol_ref_t allzeros; 82static symbol_ref_t none; 83static symbol_ref_t sindex; 84static int instruction_ptr; 85static int num_srams; 86static int sram_or_scb_offset; 87static int download_constant_count; 88static int in_critical_section; 89static u_int enum_increment; 90static u_int enum_next_value; 91 92static void process_field(int field_type, symbol_t *sym, int mask); 93static void initialize_symbol(symbol_t *symbol); 94static void add_macro_arg(const char *argtext, int position); 95static void add_macro_body(const char *bodytext); 96static void process_register(symbol_t **p_symbol); 97static void format_1_instr(int opcode, symbol_ref_t *dest, 98 expression_t *immed, symbol_ref_t *src, int ret); 99static void format_2_instr(int opcode, symbol_ref_t *dest, 100 expression_t *places, symbol_ref_t *src, int ret); 101static void format_3_instr(int opcode, symbol_ref_t *src, 102 expression_t *immed, symbol_ref_t *address); 103static void test_readable_symbol(symbol_t *symbol); 104static void test_writable_symbol(symbol_t *symbol); 105static void type_check(symbol_t *symbol, expression_t *expression, int and_op); 106static void make_expression(expression_t *immed, int value); 107static void add_conditional(symbol_t *symbol); 108static void add_version(const char *verstring); 109static 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> numerical_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 224program: 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 259include: 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 270prefix: 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 282patch_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 294version: 295 T_VERSION '=' T_STRING 296 { add_version($3); } 297; 298 299register: 300 T_REGISTER { cur_symtype = REGISTER; } reg_definition 301; 302 303reg_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 341reg_attribute_list: 342 reg_attribute 343| reg_attribute_list reg_attribute 344; 345 346reg_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 363reg_address: 364 T_ADDRESS T_NUMBER 365 { 366 cur_symbol->info.rinfo->address = $2; 367 } 368; 369 370size: 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 389access_mode: 390 T_ACCESS_MODE T_MODE 391 { 392 cur_symbol->info.rinfo->mode = $2; 393 } 394; 395 396modes: 397 T_MODES mode_list 398 { 399 cur_symbol->info.rinfo->modes = $2; 400 } 401; 402 403mode_list: 404 mode_value 405 { 406 $$ = $1; 407 } 408| mode_list ',' mode_value 409 { 410 $$ = $1 | $3; 411 } 412; 413 414mode_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 444field_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 466enum_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 484enum_entry_list: 485 enum_entry 486| enum_entry_list ',' enum_entry 487; 488 489enum_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 502mask_defn: 503 T_MASK T_SYMBOL expression 504 { 505 process_field(MASK, $2, $3.value); 506 } 507; 508 509alias: 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 523accumulator: 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 535mode_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 547allones: 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 559allzeros: 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 571none: 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 583sindex: 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 595expression: 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 710constant: 711 T_CONST T_SYMBOL numerical_value 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; 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 740macrodefn_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 754macrodefn: 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 766macro_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 preceeding argument in arg list", 780 EX_DATAERR); 781 /* NOTREACHED */ 782 } 783 $$ = $1 + 1; 784 add_macro_arg($3, $1); 785 } 786; 787 788numerical_value: 789 T_NUMBER 790 { 791 $$ = $1; 792 } 793| '-' T_NUMBER 794 { 795 $$ = -$2; 796 } 797; 798 799scratch_ram: 800 T_SRAM '{' 801 { 802 snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 803 num_srams); 804 cur_symbol = symtable_get(SRAM_SYMNAME); 805 cur_symtype = SRAMLOC; 806 cur_symbol->type = SRAMLOC; 807 initialize_symbol(cur_symbol); 808 } 809 reg_address 810 { 811 sram_or_scb_offset = cur_symbol->info.rinfo->address; 812 } 813 size 814 { 815 scb_or_sram_symbol = cur_symbol; 816 } 817 scb_or_sram_attributes 818 '}' 819 { 820 cur_symbol = NULL; 821 scb_or_sram_symbol = NULL; 822 } 823; 824 825scb: 826 T_SCB '{' 827 { 828 cur_symbol = symtable_get(SCB_SYMNAME); 829 cur_symtype = SCBLOC; 830 if (cur_symbol->type != UNINITIALIZED) { 831 stop("Only one SRAM definition allowed", 832 EX_SOFTWARE); 833 /* NOTREACHED */ 834 } 835 cur_symbol->type = SCBLOC; 836 initialize_symbol(cur_symbol); 837 /* 64 bytes of SCB space */ 838 cur_symbol->info.rinfo->size = 64; 839 } 840 reg_address 841 { 842 sram_or_scb_offset = cur_symbol->info.rinfo->address; 843 } 844 size 845 { 846 scb_or_sram_symbol = cur_symbol; 847 } 848 scb_or_sram_attributes 849 '}' 850 { 851 cur_symbol = NULL; 852 scb_or_sram_symbol = NULL; 853 } 854; 855 856scb_or_sram_attributes: 857 /* NULL definition is okay */ 858| modes 859| scb_or_sram_reg_list 860| modes scb_or_sram_reg_list 861; 862 863scb_or_sram_reg_list: 864 reg_definition 865| scb_or_sram_reg_list reg_definition 866; 867 868reg_symbol: 869 T_SYMBOL 870 { 871 process_register(&$1); 872 $$.symbol = $1; 873 $$.offset = 0; 874 } 875| T_SYMBOL '[' T_SYMBOL ']' 876 { 877 process_register(&$1); 878 if ($3->type != CONST) { 879 stop("register offset must be a constant", EX_DATAERR); 880 /* NOTREACHED */ 881 } 882 if (($3->info.cinfo->value + 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->info.cinfo->value; 889 } 890| T_SYMBOL '[' T_NUMBER ']' 891 { 892 process_register(&$1); 893 if (($3 + 1) > $1->info.rinfo->size) { 894 stop("Accessing offset beyond range of register", 895 EX_DATAERR); 896 /* NOTREACHED */ 897 } 898 $$.symbol = $1; 899 $$.offset = $3; 900 } 901| T_A 902 { 903 if (accumulator.symbol == NULL) { 904 stop("No accumulator has been defined", EX_DATAERR); 905 /* NOTREACHED */ 906 } 907 $$.symbol = accumulator.symbol; 908 $$.offset = 0; 909 } 910; 911 912destination: 913 reg_symbol 914 { 915 test_writable_symbol($1.symbol); 916 $$ = $1; 917 } 918; 919 920immediate: 921 expression 922 { $$ = $1; } 923; 924 925immediate_or_a: 926 expression 927 { 928 if ($1.value == 0 && is_download_const(&$1) == 0) { 929 snprintf(errbuf, sizeof(errbuf), 930 "\nExpression evaluates to 0 and thus " 931 "references the accumulator.\n " 932 "If this is the desired effect, use 'A' " 933 "instead.\n"); 934 stop(errbuf, EX_DATAERR); 935 } 936 $$ = $1; 937 } 938| T_A 939 { 940 SLIST_INIT(&$$.referenced_syms); 941 symlist_add(&$$.referenced_syms, accumulator.symbol, 942 SYMLIST_INSERT_HEAD); 943 $$.value = 0; 944 } 945; 946 947source: 948 reg_symbol 949 { 950 test_readable_symbol($1.symbol); 951 $$ = $1; 952 } 953; 954 955opt_source: 956 { 957 $$.symbol = NULL; 958 $$.offset = 0; 959 } 960| ',' source 961 { $$ = $2; } 962; 963 964ret: 965 { $$ = 0; } 966| T_RET 967 { $$ = 1; } 968; 969 970set_src_mode: 971 T_SET_SRC_MODE T_NUMBER ';' 972 { 973 src_mode = $2; 974 } 975; 976 977set_dst_mode: 978 T_SET_DST_MODE T_NUMBER ';' 979 { 980 dst_mode = $2; 981 } 982; 983 984critical_section_start: 985 T_BEGIN_CS ';' 986 { 987 critical_section_t *cs; 988 989 if (in_critical_section != FALSE) { 990 stop("Critical Section within Critical Section", 991 EX_DATAERR); 992 /* NOTREACHED */ 993 } 994 cs = cs_alloc(); 995 cs->begin_addr = instruction_ptr; 996 in_critical_section = TRUE; 997 } 998 999critical_section_end: 1000 T_END_CS ';' 1001 { 1002 critical_section_t *cs; 1003 1004 if (in_critical_section == FALSE) { 1005 stop("Unballanced 'end_cs'", EX_DATAERR); 1006 /* NOTREACHED */ 1007 } 1008 cs = TAILQ_LAST(&cs_tailq, cs_tailq); 1009 cs->end_addr = instruction_ptr; 1010 in_critical_section = FALSE; 1011 } 1012 1013export: 1014 { $$ = 0; } 1015| T_EXPORT 1016 { $$ = 1; } 1017; 1018 1019label: 1020 export T_SYMBOL ':' 1021 { 1022 if ($2->type != UNINITIALIZED) { 1023 stop("Program label multiply defined", EX_DATAERR); 1024 /* NOTREACHED */ 1025 } 1026 $2->type = LABEL; 1027 initialize_symbol($2); 1028 $2->info.linfo->address = instruction_ptr; 1029 $2->info.linfo->exported = $1; 1030 } 1031; 1032 1033address: 1034 T_SYMBOL 1035 { 1036 $$.symbol = $1; 1037 $$.offset = 0; 1038 } 1039| T_SYMBOL '+' T_NUMBER 1040 { 1041 $$.symbol = $1; 1042 $$.offset = $3; 1043 } 1044| T_SYMBOL '-' T_NUMBER 1045 { 1046 $$.symbol = $1; 1047 $$.offset = -$3; 1048 } 1049| '.' 1050 { 1051 $$.symbol = NULL; 1052 $$.offset = 0; 1053 } 1054| '.' '+' T_NUMBER 1055 { 1056 $$.symbol = NULL; 1057 $$.offset = $3; 1058 } 1059| '.' '-' T_NUMBER 1060 { 1061 $$.symbol = NULL; 1062 $$.offset = -$3; 1063 } 1064; 1065 1066conditional: 1067 T_IF T_CEXPR '{' 1068 { 1069 scope_t *new_scope; 1070 1071 add_conditional($2); 1072 new_scope = scope_alloc(); 1073 new_scope->type = SCOPE_IF; 1074 new_scope->begin_addr = instruction_ptr; 1075 new_scope->func_num = $2->info.condinfo->func_num; 1076 } 1077| T_ELSE T_IF T_CEXPR '{' 1078 { 1079 scope_t *new_scope; 1080 scope_t *scope_context; 1081 scope_t *last_scope; 1082 1083 /* 1084 * Ensure that the previous scope is either an 1085 * if or and else if. 1086 */ 1087 scope_context = SLIST_FIRST(&scope_stack); 1088 last_scope = TAILQ_LAST(&scope_context->inner_scope, 1089 scope_tailq); 1090 if (last_scope == NULL 1091 || last_scope->type == T_ELSE) { 1092 1093 stop("'else if' without leading 'if'", EX_DATAERR); 1094 /* NOTREACHED */ 1095 } 1096 add_conditional($3); 1097 new_scope = scope_alloc(); 1098 new_scope->type = SCOPE_ELSE_IF; 1099 new_scope->begin_addr = instruction_ptr; 1100 new_scope->func_num = $3->info.condinfo->func_num; 1101 } 1102| T_ELSE '{' 1103 { 1104 scope_t *new_scope; 1105 scope_t *scope_context; 1106 scope_t *last_scope; 1107 1108 /* 1109 * Ensure that the previous scope is either an 1110 * if or and else if. 1111 */ 1112 scope_context = SLIST_FIRST(&scope_stack); 1113 last_scope = TAILQ_LAST(&scope_context->inner_scope, 1114 scope_tailq); 1115 if (last_scope == NULL 1116 || last_scope->type == SCOPE_ELSE) { 1117 1118 stop("'else' without leading 'if'", EX_DATAERR); 1119 /* NOTREACHED */ 1120 } 1121 new_scope = scope_alloc(); 1122 new_scope->type = SCOPE_ELSE; 1123 new_scope->begin_addr = instruction_ptr; 1124 } 1125; 1126 1127conditional: 1128 '}' 1129 { 1130 scope_t *scope_context; 1131 1132 scope_context = SLIST_FIRST(&scope_stack); 1133 if (scope_context->type == SCOPE_ROOT) { 1134 stop("Unexpected '}' encountered", EX_DATAERR); 1135 /* NOTREACHED */ 1136 } 1137 1138 scope_context->end_addr = instruction_ptr; 1139 1140 /* Pop the scope */ 1141 SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 1142 1143 process_scope(scope_context); 1144 1145 if (SLIST_FIRST(&scope_stack) == NULL) { 1146 stop("Unexpected '}' encountered", EX_DATAERR); 1147 /* NOTREACHED */ 1148 } 1149 } 1150; 1151 1152f1_opcode: 1153 T_AND { $$ = AIC_OP_AND; } 1154| T_XOR { $$ = AIC_OP_XOR; } 1155| T_ADD { $$ = AIC_OP_ADD; } 1156| T_ADC { $$ = AIC_OP_ADC; } 1157; 1158 1159code: 1160 f1_opcode destination ',' immediate_or_a opt_source ret ';' 1161 { 1162 format_1_instr($1, &$2, &$4, &$5, $6); 1163 } 1164; 1165 1166code: 1167 T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 1168 { 1169 format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 1170 } 1171; 1172 1173code: 1174 T_INC destination opt_source ret ';' 1175 { 1176 expression_t immed; 1177 1178 make_expression(&immed, 1); 1179 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1180 } 1181; 1182 1183code: 1184 T_DEC destination opt_source ret ';' 1185 { 1186 expression_t immed; 1187 1188 make_expression(&immed, -1); 1189 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1190 } 1191; 1192 1193code: 1194 T_CLC ret ';' 1195 { 1196 expression_t immed; 1197 1198 make_expression(&immed, -1); 1199 format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 1200 } 1201| T_CLC T_MVI destination ',' immediate_or_a ret ';' 1202 { 1203 format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 1204 } 1205; 1206 1207code: 1208 T_STC ret ';' 1209 { 1210 expression_t immed; 1211 1212 make_expression(&immed, 1); 1213 format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 1214 } 1215| T_STC destination ret ';' 1216 { 1217 expression_t immed; 1218 1219 make_expression(&immed, 1); 1220 format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 1221 } 1222; 1223 1224code: 1225 T_BMOV destination ',' source ',' immediate ret ';' 1226 { 1227 format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 1228 } 1229; 1230 1231code: 1232 T_MOV destination ',' source ret ';' 1233 { 1234 expression_t immed; 1235 1236 make_expression(&immed, 1); 1237 format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 1238 } 1239; 1240 1241code: 1242 T_MVI destination ',' immediate ret ';' 1243 { 1244 if ($4.value == 0 1245 && is_download_const(&$4) == 0) { 1246 expression_t immed; 1247 1248 /* 1249 * Allow move immediates of 0 so that macros, 1250 * that can't know the immediate's value and 1251 * otherwise compensate, still work. 1252 */ 1253 make_expression(&immed, 0xff); 1254 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $5); 1255 } else { 1256 format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 1257 } 1258 } 1259; 1260 1261code: 1262 T_NOT destination opt_source ret ';' 1263 { 1264 expression_t immed; 1265 1266 make_expression(&immed, 0xff); 1267 format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 1268 } 1269; 1270 1271code: 1272 T_CLR destination ret ';' 1273 { 1274 expression_t immed; 1275 1276 make_expression(&immed, 0xff); 1277 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 1278 } 1279; 1280 1281code: 1282 T_NOP ret ';' 1283 { 1284 expression_t immed; 1285 1286 make_expression(&immed, 0xff); 1287 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 1288 } 1289; 1290 1291code: 1292 T_RET ';' 1293 { 1294 expression_t immed; 1295 1296 make_expression(&immed, 0xff); 1297 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 1298 } 1299; 1300 1301 /* 1302 * This grammer differs from the one in the aic7xxx 1303 * reference manual since the grammer listed there is 1304 * ambiguous and causes a shift/reduce conflict. 1305 * It also seems more logical as the "immediate" 1306 * argument is listed as the second arg like the 1307 * other formats. 1308 */ 1309 1310f2_opcode: 1311 T_SHL { $$ = AIC_OP_SHL; } 1312| T_SHR { $$ = AIC_OP_SHR; } 1313| T_ROL { $$ = AIC_OP_ROL; } 1314| T_ROR { $$ = AIC_OP_ROR; } 1315; 1316 1317code: 1318 f2_opcode destination ',' expression opt_source ret ';' 1319 { 1320 format_2_instr($1, &$2, &$4, &$5, $6); 1321 } 1322; 1323 1324jmp_jc_jnc_call: 1325 T_JMP { $$ = AIC_OP_JMP; } 1326| T_JC { $$ = AIC_OP_JC; } 1327| T_JNC { $$ = AIC_OP_JNC; } 1328| T_CALL { $$ = AIC_OP_CALL; } 1329; 1330 1331jz_jnz: 1332 T_JZ { $$ = AIC_OP_JZ; } 1333| T_JNZ { $$ = AIC_OP_JNZ; } 1334; 1335 1336je_jne: 1337 T_JE { $$ = AIC_OP_JE; } 1338| T_JNE { $$ = AIC_OP_JNE; } 1339; 1340 1341code: 1342 jmp_jc_jnc_call address ';' 1343 { 1344 expression_t immed; 1345 1346 make_expression(&immed, 0); 1347 format_3_instr($1, &sindex, &immed, &$2); 1348 } 1349; 1350 1351code: 1352 T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 1353 { 1354 format_3_instr($5, &$2, &$4, &$6); 1355 } 1356; 1357 1358code: 1359 T_TEST source ',' immediate_or_a jz_jnz address ';' 1360 { 1361 format_3_instr($5, &$2, &$4, &$6); 1362 } 1363; 1364 1365code: 1366 T_CMP source ',' immediate_or_a je_jne address ';' 1367 { 1368 format_3_instr($5, &$2, &$4, &$6); 1369 } 1370; 1371 1372code: 1373 T_MOV source jmp_jc_jnc_call address ';' 1374 { 1375 expression_t immed; 1376 1377 make_expression(&immed, 0); 1378 format_3_instr($3, &$2, &immed, &$4); 1379 } 1380; 1381 1382code: 1383 T_MVI immediate jmp_jc_jnc_call address ';' 1384 { 1385 format_3_instr($3, &allzeros, &$2, &$4); 1386 } 1387; 1388 1389%% 1390 1391static void 1392process_field(int field_type, symbol_t *sym, int value) 1393{ 1394 /* 1395 * Add the current register to its 1396 * symbol list, if it already exists, 1397 * warn if we are setting it to a 1398 * different value, or in the bit to 1399 * the "allowed bits" of this register. 1400 */ 1401 if (sym->type == UNINITIALIZED) { 1402 sym->type = field_type; 1403 initialize_symbol(sym); 1404 sym->info.finfo->value = value; 1405 if (field_type != ENUM_ENTRY) { 1406 if (field_type != MASK && value == 0) { 1407 stop("Empty Field, or Enum", EX_DATAERR); 1408 /* NOTREACHED */ 1409 } 1410 sym->info.finfo->value = value; 1411 sym->info.finfo->mask = value; 1412 } else if (field_symbol != NULL) { 1413 sym->info.finfo->mask = field_symbol->info.finfo->value; 1414 } else { 1415 sym->info.finfo->mask = 0xFF; 1416 } 1417 } else if (sym->type != field_type) { 1418 stop("Field definition mirrors a definition of the same " 1419 " name, but a different type", EX_DATAERR); 1420 /* NOTREACHED */ 1421 } else if (value != sym->info.finfo->value) { 1422 stop("Field redefined with a conflicting value", EX_DATAERR); 1423 /* NOTREACHED */ 1424 } 1425 /* Fail if this symbol is already listed */ 1426 if (symlist_search(&(sym->info.finfo->symrefs), 1427 cur_symbol->name) != NULL) { 1428 stop("Field defined multiple times for register", EX_DATAERR); 1429 /* NOTREACHED */ 1430 } 1431 symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 1432 SYMLIST_INSERT_HEAD); 1433 cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 1434 cur_symbol->info.rinfo->typecheck_masks = TRUE; 1435 symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 1436} 1437 1438static void 1439initialize_symbol(symbol_t *symbol) 1440{ 1441 switch (symbol->type) { 1442 case UNINITIALIZED: 1443 stop("Call to initialize_symbol with type field unset", 1444 EX_SOFTWARE); 1445 /* NOTREACHED */ 1446 break; 1447 case REGISTER: 1448 case SRAMLOC: 1449 case SCBLOC: 1450 symbol->info.rinfo = 1451 (struct reg_info *)malloc(sizeof(struct reg_info)); 1452 if (symbol->info.rinfo == NULL) { 1453 stop("Can't create register info", EX_SOFTWARE); 1454 /* NOTREACHED */ 1455 } 1456 memset(symbol->info.rinfo, 0, 1457 sizeof(struct reg_info)); 1458 SLIST_INIT(&(symbol->info.rinfo->fields)); 1459 /* 1460 * Default to allowing access in all register modes 1461 * or to the mode specified by the SCB or SRAM space 1462 * we are in. 1463 */ 1464 if (scb_or_sram_symbol != NULL) 1465 symbol->info.rinfo->modes = 1466 scb_or_sram_symbol->info.rinfo->modes; 1467 else 1468 symbol->info.rinfo->modes = ~0; 1469 break; 1470 case ALIAS: 1471 symbol->info.ainfo = 1472 (struct alias_info *)malloc(sizeof(struct alias_info)); 1473 if (symbol->info.ainfo == NULL) { 1474 stop("Can't create alias info", EX_SOFTWARE); 1475 /* NOTREACHED */ 1476 } 1477 memset(symbol->info.ainfo, 0, 1478 sizeof(struct alias_info)); 1479 break; 1480 case MASK: 1481 case FIELD: 1482 case ENUM: 1483 case ENUM_ENTRY: 1484 symbol->info.finfo = 1485 (struct field_info *)malloc(sizeof(struct field_info)); 1486 if (symbol->info.finfo == NULL) { 1487 stop("Can't create field info", EX_SOFTWARE); 1488 /* NOTREACHED */ 1489 } 1490 memset(symbol->info.finfo, 0, sizeof(struct field_info)); 1491 SLIST_INIT(&(symbol->info.finfo->symrefs)); 1492 break; 1493 case CONST: 1494 case DOWNLOAD_CONST: 1495 symbol->info.cinfo = 1496 (struct const_info *)malloc(sizeof(struct const_info)); 1497 if (symbol->info.cinfo == NULL) { 1498 stop("Can't create alias info", EX_SOFTWARE); 1499 /* NOTREACHED */ 1500 } 1501 memset(symbol->info.cinfo, 0, 1502 sizeof(struct const_info)); 1503 break; 1504 case LABEL: 1505 symbol->info.linfo = 1506 (struct label_info *)malloc(sizeof(struct label_info)); 1507 if (symbol->info.linfo == NULL) { 1508 stop("Can't create label info", EX_SOFTWARE); 1509 /* NOTREACHED */ 1510 } 1511 memset(symbol->info.linfo, 0, 1512 sizeof(struct label_info)); 1513 break; 1514 case CONDITIONAL: 1515 symbol->info.condinfo = 1516 (struct cond_info *)malloc(sizeof(struct cond_info)); 1517 if (symbol->info.condinfo == NULL) { 1518 stop("Can't create conditional info", EX_SOFTWARE); 1519 /* NOTREACHED */ 1520 } 1521 memset(symbol->info.condinfo, 0, 1522 sizeof(struct cond_info)); 1523 break; 1524 case MACRO: 1525 symbol->info.macroinfo = 1526 (struct macro_info *)malloc(sizeof(struct macro_info)); 1527 if (symbol->info.macroinfo == NULL) { 1528 stop("Can't create macro info", EX_SOFTWARE); 1529 /* NOTREACHED */ 1530 } 1531 memset(symbol->info.macroinfo, 0, 1532 sizeof(struct macro_info)); 1533 STAILQ_INIT(&symbol->info.macroinfo->args); 1534 break; 1535 default: 1536 stop("Call to initialize_symbol with invalid symbol type", 1537 EX_SOFTWARE); 1538 /* NOTREACHED */ 1539 break; 1540 } 1541} 1542 1543static void 1544add_macro_arg(const char *argtext, int argnum) 1545{ 1546 struct macro_arg *marg; 1547 int i; 1548 int retval; 1549 1550 1551 if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1552 stop("Invalid current symbol for adding macro arg", 1553 EX_SOFTWARE); 1554 /* NOTREACHED */ 1555 } 1556 1557 marg = (struct macro_arg *)malloc(sizeof(*marg)); 1558 if (marg == NULL) { 1559 stop("Can't create macro_arg structure", EX_SOFTWARE); 1560 /* NOTREACHED */ 1561 } 1562 marg->replacement_text = NULL; 1563 retval = snprintf(regex_pattern, sizeof(regex_pattern), 1564 "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 1565 argtext); 1566 if (retval >= sizeof(regex_pattern)) { 1567 stop("Regex text buffer too small for arg", 1568 EX_SOFTWARE); 1569 /* NOTREACHED */ 1570 } 1571 retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 1572 if (retval != 0) { 1573 stop("Regex compilation failed", EX_SOFTWARE); 1574 /* NOTREACHED */ 1575 } 1576 STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 1577} 1578 1579static void 1580add_macro_body(const char *bodytext) 1581{ 1582 if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1583 stop("Invalid current symbol for adding macro arg", 1584 EX_SOFTWARE); 1585 /* NOTREACHED */ 1586 } 1587 cur_symbol->info.macroinfo->body = strdup(bodytext); 1588 if (cur_symbol->info.macroinfo->body == NULL) { 1589 stop("Can't duplicate macro body text", EX_SOFTWARE); 1590 /* NOTREACHED */ 1591 } 1592} 1593 1594static void 1595process_register(symbol_t **p_symbol) 1596{ 1597 symbol_t *symbol = *p_symbol; 1598 1599 if (symbol->type == UNINITIALIZED) { 1600 snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 1601 symbol->name); 1602 stop(errbuf, EX_DATAERR); 1603 /* NOTREACHED */ 1604 } else if (symbol->type == ALIAS) { 1605 *p_symbol = symbol->info.ainfo->parent; 1606 } else if ((symbol->type != REGISTER) 1607 && (symbol->type != SCBLOC) 1608 && (symbol->type != SRAMLOC)) { 1609 snprintf(errbuf, sizeof(errbuf), 1610 "Specified symbol %s is not a register", 1611 symbol->name); 1612 stop(errbuf, EX_DATAERR); 1613 } 1614} 1615 1616static void 1617format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 1618 symbol_ref_t *src, int ret) 1619{ 1620 struct instruction *instr; 1621 struct ins_format1 *f1_instr; 1622 1623 if (src->symbol == NULL) 1624 src = dest; 1625 1626 /* Test register permissions */ 1627 test_writable_symbol(dest->symbol); 1628 test_readable_symbol(src->symbol); 1629 1630 /* Ensure that immediate makes sense for this destination */ 1631 type_check(dest->symbol, immed, opcode); 1632 1633 /* Allocate sequencer space for the instruction and fill it out */ 1634 instr = seq_alloc(); 1635 f1_instr = &instr->format.format1; 1636 f1_instr->ret = ret ? 1 : 0; 1637 f1_instr->opcode = opcode; 1638 f1_instr->destination = dest->symbol->info.rinfo->address 1639 + dest->offset; 1640 f1_instr->source = src->symbol->info.rinfo->address 1641 + src->offset; 1642 f1_instr->immediate = immed->value; 1643 1644 if (is_download_const(immed)) 1645 f1_instr->parity = 1; 1646 else if (dest->symbol == mode_ptr.symbol) { 1647 u_int src_value; 1648 u_int dst_value; 1649 1650 /* 1651 * Attempt to update mode information if 1652 * we are operating on the mode register. 1653 */ 1654 if (src->symbol == allones.symbol) 1655 src_value = 0xFF; 1656 else if (src->symbol == allzeros.symbol) 1657 src_value = 0; 1658 else if (src->symbol == mode_ptr.symbol) 1659 src_value = (dst_mode << 4) | src_mode; 1660 else 1661 goto cant_update; 1662 1663 switch (opcode) { 1664 case AIC_OP_AND: 1665 dst_value = src_value & immed->value; 1666 break; 1667 case AIC_OP_XOR: 1668 dst_value = src_value ^ immed->value; 1669 break; 1670 case AIC_OP_ADD: 1671 dst_value = (src_value + immed->value) & 0xFF; 1672 break; 1673 case AIC_OP_OR: 1674 dst_value = src_value | immed->value; 1675 break; 1676 case AIC_OP_BMOV: 1677 dst_value = src_value; 1678 break; 1679 default: 1680 goto cant_update; 1681 } 1682 src_mode = dst_value & 0xF; 1683 dst_mode = (dst_value >> 4) & 0xF; 1684 } 1685 1686cant_update: 1687 symlist_free(&immed->referenced_syms); 1688 instruction_ptr++; 1689} 1690 1691static void 1692format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 1693 symbol_ref_t *src, int ret) 1694{ 1695 struct instruction *instr; 1696 struct ins_format2 *f2_instr; 1697 uint8_t shift_control; 1698 1699 if (src->symbol == NULL) 1700 src = dest; 1701 1702 /* Test register permissions */ 1703 test_writable_symbol(dest->symbol); 1704 test_readable_symbol(src->symbol); 1705 1706 /* Allocate sequencer space for the instruction and fill it out */ 1707 instr = seq_alloc(); 1708 f2_instr = &instr->format.format2; 1709 f2_instr->ret = ret ? 1 : 0; 1710 f2_instr->opcode = AIC_OP_ROL; 1711 f2_instr->destination = dest->symbol->info.rinfo->address 1712 + dest->offset; 1713 f2_instr->source = src->symbol->info.rinfo->address 1714 + src->offset; 1715 if (places->value > 8 || places->value <= 0) { 1716 stop("illegal shift value", EX_DATAERR); 1717 /* NOTREACHED */ 1718 } 1719 switch (opcode) { 1720 case AIC_OP_SHL: 1721 if (places->value == 8) 1722 shift_control = 0xf0; 1723 else 1724 shift_control = (places->value << 4) | places->value; 1725 break; 1726 case AIC_OP_SHR: 1727 if (places->value == 8) { 1728 shift_control = 0xf8; 1729 } else { 1730 shift_control = (places->value << 4) 1731 | (8 - places->value) 1732 | 0x08; 1733 } 1734 break; 1735 case AIC_OP_ROL: 1736 shift_control = places->value & 0x7; 1737 break; 1738 case AIC_OP_ROR: 1739 shift_control = (8 - places->value) | 0x08; 1740 break; 1741 default: 1742 shift_control = 0; /* Quiet Compiler */ 1743 stop("Invalid shift operation specified", EX_SOFTWARE); 1744 /* NOTREACHED */ 1745 break; 1746 }; 1747 f2_instr->shift_control = shift_control; 1748 symlist_free(&places->referenced_syms); 1749 instruction_ptr++; 1750} 1751 1752static void 1753format_3_instr(int opcode, symbol_ref_t *src, 1754 expression_t *immed, symbol_ref_t *address) 1755{ 1756 struct instruction *instr; 1757 struct ins_format3 *f3_instr; 1758 int addr; 1759 1760 /* Test register permissions */ 1761 test_readable_symbol(src->symbol); 1762 1763 /* Ensure that immediate makes sense for this source */ 1764 type_check(src->symbol, immed, opcode); 1765 1766 /* Allocate sequencer space for the instruction and fill it out */ 1767 instr = seq_alloc(); 1768 f3_instr = &instr->format.format3; 1769 if (address->symbol == NULL) { 1770 /* 'dot' referrence. Use the current instruction pointer */ 1771 addr = instruction_ptr + address->offset; 1772 } else if (address->symbol->type == UNINITIALIZED) { 1773 /* forward reference */ 1774 addr = address->offset; 1775 instr->patch_label = address->symbol; 1776 } else 1777 addr = address->symbol->info.linfo->address + address->offset; 1778 f3_instr->opcode = opcode; 1779 f3_instr->address = addr; 1780 f3_instr->source = src->symbol->info.rinfo->address 1781 + src->offset; 1782 f3_instr->immediate = immed->value; 1783 1784 if (is_download_const(immed)) 1785 f3_instr->parity = 1; 1786 1787 symlist_free(&immed->referenced_syms); 1788 instruction_ptr++; 1789} 1790 1791static void 1792test_readable_symbol(symbol_t *symbol) 1793{ 1794 1795 if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 1796 snprintf(errbuf, sizeof(errbuf), 1797 "Register %s unavailable in source reg mode %d", 1798 symbol->name, src_mode); 1799 stop(errbuf, EX_DATAERR); 1800 } 1801 1802 if (symbol->info.rinfo->mode == WO) { 1803 stop("Write Only register specified as source", 1804 EX_DATAERR); 1805 /* NOTREACHED */ 1806 } 1807} 1808 1809static void 1810test_writable_symbol(symbol_t *symbol) 1811{ 1812 1813 if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 1814 snprintf(errbuf, sizeof(errbuf), 1815 "Register %s unavailable in destination reg mode %d", 1816 symbol->name, dst_mode); 1817 stop(errbuf, EX_DATAERR); 1818 } 1819 1820 if (symbol->info.rinfo->mode == RO) { 1821 stop("Read Only register specified as destination", 1822 EX_DATAERR); 1823 /* NOTREACHED */ 1824 } 1825} 1826 1827static void 1828type_check(symbol_t *symbol, expression_t *expression, int opcode) 1829{ 1830 symbol_node_t *node; 1831 int and_op; 1832 1833 and_op = FALSE; 1834 if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) 1835 and_op = TRUE; 1836 1837 /* 1838 * Make sure that we aren't attempting to write something 1839 * that hasn't been defined. If this is an and operation, 1840 * this is a mask, so "undefined" bits are okay. 1841 */ 1842 if (and_op == FALSE 1843 && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { 1844 snprintf(errbuf, sizeof(errbuf), 1845 "Invalid bit(s) 0x%x in immediate written to %s", 1846 expression->value & ~symbol->info.rinfo->valid_bitmask, 1847 symbol->name); 1848 stop(errbuf, EX_DATAERR); 1849 /* NOTREACHED */ 1850 } 1851 1852 /* 1853 * Now make sure that all of the symbols referenced by the 1854 * expression are defined for this register. 1855 */ 1856 if (symbol->info.rinfo->typecheck_masks != FALSE) { 1857 for(node = expression->referenced_syms.slh_first; 1858 node != NULL; 1859 node = node->links.sle_next) { 1860 if ((node->symbol->type == MASK 1861 || node->symbol->type == FIELD 1862 || node->symbol->type == ENUM 1863 || node->symbol->type == ENUM_ENTRY) 1864 && symlist_search(&node->symbol->info.finfo->symrefs, 1865 symbol->name) == NULL) { 1866 snprintf(errbuf, sizeof(errbuf), 1867 "Invalid field or mask %s " 1868 "for register %s", 1869 node->symbol->name, symbol->name); 1870 stop(errbuf, EX_DATAERR); 1871 /* NOTREACHED */ 1872 } 1873 } 1874 } 1875} 1876 1877static void 1878make_expression(expression_t *immed, int value) 1879{ 1880 SLIST_INIT(&immed->referenced_syms); 1881 immed->value = value & 0xff; 1882} 1883 1884static void 1885add_conditional(symbol_t *symbol) 1886{ 1887 static int numfuncs; 1888 1889 if (numfuncs == 0) { 1890 /* add a special conditional, "0" */ 1891 symbol_t *false_func; 1892 1893 false_func = symtable_get("0"); 1894 if (false_func->type != UNINITIALIZED) { 1895 stop("Conditional expression '0' " 1896 "conflicts with a symbol", EX_DATAERR); 1897 /* NOTREACHED */ 1898 } 1899 false_func->type = CONDITIONAL; 1900 initialize_symbol(false_func); 1901 false_func->info.condinfo->func_num = numfuncs++; 1902 symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 1903 } 1904 1905 /* This condition has occurred before */ 1906 if (symbol->type == CONDITIONAL) 1907 return; 1908 1909 if (symbol->type != UNINITIALIZED) { 1910 stop("Conditional expression conflicts with a symbol", 1911 EX_DATAERR); 1912 /* NOTREACHED */ 1913 } 1914 1915 symbol->type = CONDITIONAL; 1916 initialize_symbol(symbol); 1917 symbol->info.condinfo->func_num = numfuncs++; 1918 symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 1919} 1920 1921static void 1922add_version(const char *verstring) 1923{ 1924 const char prefix[] = " * "; 1925 int newlen; 1926 int oldlen; 1927 1928 newlen = strlen(verstring) + strlen(prefix); 1929 oldlen = 0; 1930 if (versions != NULL) 1931 oldlen = strlen(versions); 1932 versions = realloc(versions, newlen + oldlen + 2); 1933 if (versions == NULL) 1934 stop("Can't allocate version string", EX_SOFTWARE); 1935 strcpy(&versions[oldlen], prefix); 1936 strcpy(&versions[oldlen + strlen(prefix)], verstring); 1937 versions[newlen + oldlen] = '\n'; 1938 versions[newlen + oldlen + 1] = '\0'; 1939} 1940 1941void 1942yyerror(const char *string) 1943{ 1944 stop(string, EX_DATAERR); 1945} 1946 1947static int 1948is_download_const(expression_t *immed) 1949{ 1950 if ((immed->referenced_syms.slh_first != NULL) 1951 && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 1952 return (TRUE); 1953 1954 return (FALSE); 1955} 1956