[BACK]Return to aicasm_gram.y CVS log [TXT][DIR] Up to [local] / sys / dev / microcode / aic7xxx

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