Annotation of sys/dev/microcode/aic7xxx/aicasm_gram.y, Revision 1.1
1.1 ! nbrk 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: }
CVSweb