cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aicasm_gram.y (41868B)


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