brintos

brintos / linux-shallow public Read only

0
0
Text · 40.9 KiB · 65182ad Raw
2000 lines · plain
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 without10 * modification, are permitted provided that the following conditions11 * are met:12 * 1. Redistributions of source code must retain the above copyright13 *    notice, this list of conditions, and the following disclaimer,14 *    without modification.15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer16 *    substantially similar to the "NO WARRANTY" disclaimer below17 *    ("Disclaimer") and any redistribution must be conditioned upon18 *    including a substantially similar Disclaimer requirement for further19 *    binary redistribution.20 * 3. Neither the names of the above-listed copyright holders nor the names21 *    of any contributors may be used to endorse or promote products derived22 *    from this software without specific prior written permission.23 *24 * Alternatively, this software may be distributed under the terms of the25 * GNU General Public License ("GPL") version 2 as published by the Free26 * Software Foundation.27 *28 * NO WARRANTY29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT33 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35 * 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) ARISING38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE39 * 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_REGISTER120 121%token <value> T_CONST122 123%token T_EXPORT124 125%token T_DOWNLOAD126 127%token T_SCB128 129%token T_SRAM130 131%token T_ALIAS132 133%token T_SIZE134 135%token T_EXPR_LSHIFT136 137%token T_EXPR_RSHIFT138 139%token <value> T_ADDRESS140 141%token T_COUNT142 143%token T_ACCESS_MODE144 145%token T_DONT_GENERATE_DEBUG_CODE146 147%token T_MODES148 149%token T_DEFINE150 151%token T_SET_SRC_MODE152 153%token T_SET_DST_MODE154 155%token <value> T_MODE156 157%token T_BEGIN_CS158 159%token T_END_CS160 161%token T_PAD_PAGE162 163%token T_FIELD164 165%token T_ENUM166 167%token T_MASK168 169%token <value> T_NUMBER170 171%token <str> T_PATH T_STRING T_ARG T_MACROBODY172 173%token <sym> T_CEXPR174 175%token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST176 177%token <value> T_SHR T_SHL T_ROR T_ROL178 179%token <value> T_MVI T_MOV T_CLR T_BMOV180 181%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL182 183%token <value> T_ADD T_ADC184 185%token <value> T_INC T_DEC186 187%token <value> T_STC T_CLC188 189%token <value> T_CMP T_NOT T_XOR190 191%token <value> T_TEST T_AND192 193%token <value> T_OR194 195/* 16 bit extensions, not implemented196 * %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16197 * %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG198 */199%token T_RET200 201%token T_NOP202 203%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR204 205%token T_A206 207%token <sym> T_SYMBOL208 209%token T_NL210 211%token T_IF T_ELSE T_ELSE_IF T_ENDIF212 213%type <sym_ref> reg_symbol address destination source opt_source214 215%type <expression> expression immediate immediate_or_a216 217%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne218 219%type <value> mode_value mode_list macro_arglist220 221%left '|'222%left '&'223%left T_EXPR_LSHIFT T_EXPR_RSHIFT224%left '+' '-'225%left '*' '/'226%right '~'227%nonassoc UMINUS228%%229 230program:231	include232|	program include233|	prefix234|	program prefix235|	patch_arg_list236|	program patch_arg_list237|	version238|	program version239|	register240|	program register241|	constant242|	program constant243|	macrodefn244|	program macrodefn245|	scratch_ram246|	program scratch_ram247|	scb248|	program scb249|	label250|	program label251|	set_src_mode252|	program set_src_mode253|	set_dst_mode254|	program set_dst_mode255|	critical_section_start256|	program critical_section_start257|	critical_section_end258|	program critical_section_end259|	conditional260|	program conditional261|	code262|	program code263;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_STRING278	{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_STRING290	{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_STRING302	{ add_version($3); }303;304 305register:306	T_REGISTER { cur_symtype = REGISTER; } reg_definition307;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_list321	'}'322		{323			/*324			 * Default to allowing everything in for registers325			 * 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_attribute349|	reg_attribute_list reg_attribute350;351 352reg_attribute:353	reg_address354|	size355|	count356|	access_mode357|	dont_generate_debug_code358|	modes359|	field_defn360|	enum_defn361|	mask_defn362|	alias363|	accumulator364|	mode_pointer365|	allones366|	allzeros367|	none368|	sindex369;370 371reg_address:372	T_ADDRESS T_NUMBER373	{374		cur_symbol->info.rinfo->address = $2;375	}376;377 378size:379	T_SIZE T_NUMBER380	{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->address387				 + scb_or_sram_symbol->info.rinfo->size;388			sym_max_addr = cur_symbol->info.rinfo->address389				     + 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_NUMBER399	{400		cur_symbol->count += $2;401	}402;403 404access_mode:405	T_ACCESS_MODE T_MODE406	{407		cur_symbol->info.rinfo->mode = $2;408	}409;410 411dont_generate_debug_code:412	T_DONT_GENERATE_DEBUG_CODE413	{414		cur_symbol->dont_generate_debug_code = 1;415	}416;417 418modes:419	T_MODES mode_list420	{421		cur_symbol->info.rinfo->modes = $2;422	}423;424 425mode_list:426	mode_value427	{428		$$ = $1;429	}430|	mode_list ',' mode_value431	{432		$$ = $1 | $3;433	}434;435 436mode_value:437	T_NUMBER438	{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_SYMBOL448	{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_FIELD468		{469			field_symbol = NULL;470			enum_next_value = 0;471			enum_increment = 1;472		}473	'{' enum_entry_list '}'474|	T_FIELD T_SYMBOL expression475		{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 expression483	{484		process_field(FIELD, $2, $3.value);485	}486;487 488enum_defn:489	T_ENUM490		{491			field_symbol = NULL;492			enum_next_value = 0;493			enum_increment = 1;494		}495	'{' enum_entry_list '}'496|	T_ENUM T_SYMBOL expression497		{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_entry508|	enum_entry_list ',' enum_entry509;510 511enum_entry:512	T_SYMBOL513	{514		process_field(ENUM_ENTRY, $1, enum_next_value);515		enum_next_value += enum_increment;516	}517|	T_SYMBOL expression518	{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 expression526	{527		process_field(MASK, $2, $3.value);528	}529;530 531alias:532	T_ALIAS	T_SYMBOL533	{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_ACCUM547	{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_PTR559	{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_ALLONES571	{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_ALLZEROS583	{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_NONE595	{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_SINDEX607	{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 '|' expression619	{620		 $$.value = $1.value | $3.value;621		 symlist_merge(&$$.referenced_syms,622			       &$1.referenced_syms,623			       &$3.referenced_syms);624	}625|	expression '&' expression626	{627		$$.value = $1.value & $3.value;628		symlist_merge(&$$.referenced_syms,629			       &$1.referenced_syms,630			       &$3.referenced_syms);631	}632|	expression '+' expression633	{634		$$.value = $1.value + $3.value;635		symlist_merge(&$$.referenced_syms,636			       &$1.referenced_syms,637			       &$3.referenced_syms);638	}639|	expression '-' expression640	{641		$$.value = $1.value - $3.value;642		symlist_merge(&($$.referenced_syms),643			       &($1.referenced_syms),644			       &($3.referenced_syms));645	}646|	expression '*' expression647	{648		$$.value = $1.value * $3.value;649		symlist_merge(&($$.referenced_syms),650			       &($1.referenced_syms),651			       &($3.referenced_syms));652	}653|	expression '/' expression654	{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 expression661	{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 expression668	{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|	'~' expression679	{680		$$ = $2;681		$$.value = (~$$.value) & 0xFF;682	}683|	'-' expression %prec UMINUS684	{685		$$ = $2;686		$$.value = -$$.value;687	}688|	T_NUMBER689	{690		$$.value = $1;691		SLIST_INIT(&$$.referenced_syms);692	}693|	T_SYMBOL694	{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 expression734	{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_DOWNLOAD745	{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_SYMBOL764	{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_MACROBODY778	{779		add_macro_body($2);780	}781|	macrodefn_prologue '(' macro_arglist ')' T_MACROBODY782	{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_ARG794	{795		$$ = 1;796		add_macro_arg($1, 0);797	}798|	macro_arglist ',' T_ARG799	{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_address822		{823			sram_or_scb_offset = cur_symbol->info.rinfo->address;824		}825		size826		{827			scb_or_sram_symbol = cur_symbol;828		}829		scb_or_sram_attributes830	'}'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_address854		{855			sram_or_scb_offset = cur_symbol->info.rinfo->address;856		}857		size858		{859			scb_or_sram_symbol = cur_symbol;860		}861		scb_or_sram_attributes862	'}'863		{864			cur_symbol = NULL;865			scb_or_sram_symbol = NULL;866		}867;868 869scb_or_sram_attributes:870	/* NULL definition is okay */871|	modes872|	scb_or_sram_reg_list873|	modes scb_or_sram_reg_list874;875 876scb_or_sram_reg_list:877	reg_definition878|	scb_or_sram_reg_list reg_definition879;880 881reg_symbol:882	T_SYMBOL883	{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_A915	{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_symbol927	{928		test_writable_symbol($1.symbol);929		$$ = $1;930	}931;932 933immediate:934	expression935	{ $$ = $1; }936;937 938immediate_or_a:939	expression940	{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_A952	{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_symbol962	{963		test_readable_symbol($1.symbol);964		$$ = $1;965	}966;967 968opt_source:969	{970		$$.symbol = NULL;971		$$.offset = 0;972	}973|	',' source974	{ $$ = $2; }975;976 977ret:978	{ $$ = 0; }979|	T_RET980	{ $$ = 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_EXPORT1031	{ $$ = 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_SYMBOL1050	{1051		$$.symbol = $1;1052		$$.offset = 0;1053	}1054|	T_SYMBOL '+' T_NUMBER1055	{1056		$$.symbol = $1;1057		$$.offset = $3;1058	}1059|	T_SYMBOL '-' T_NUMBER1060	{1061		$$.symbol = $1;1062		$$.offset = -$3;1063	}1064|	'.'1065	{1066		$$.symbol = NULL;1067		$$.offset = 0;1068	}1069|	'.' '+' T_NUMBER1070	{1071		$$.symbol = NULL;1072		$$.offset = $3;1073	}1074|	'.' '-' T_NUMBER1075	{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 an1100		 * 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 == NULL1106		 || 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 an1125		 * 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 == NULL1131		 || 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 == 01260		 && 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 and1266			 * 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 aic7xxx1318	 * reference manual since the grammar listed there is1319	 * 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 the1322	 * 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 used1334 *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 void1421process_field(int field_type, symbol_t *sym, int value)1422{1423	/*1424	 * Add the current register to its1425	 * symbol list, if it already exists,1426	 * warn if we are setting it to a1427	 * different value, or in the bit to1428	 * 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 void1468initialize_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 modes1490		 * or to the mode specified by the SCB or SRAM space1491		 * 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		else1497			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 void1573add_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 void1608add_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 void1623process_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 void1645format_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->address1669			      + dest->offset;1670	f1_instr->source = src->symbol->info.rinfo->address1671			 + 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 if1682		 * 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		else1691			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 void1722format_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->address1742			      + dest->offset;1743	f2_instr->source = src->symbol->info.rinfo->address1744			 + 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		else1754			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 void1783format_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	} else1804		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->address1808			 + 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 void1819test_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 void1836test_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 void1853type_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 something1863	 * 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 logic1873	 */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 the1888	 * 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 == MASK1895			  || node->symbol->type == FIELD1896			  || node->symbol->type == ENUM1897			  || 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 void1912make_expression(expression_t *immed, int value)1913{1914	SLIST_INIT(&immed->referenced_syms);1915	immed->value = value & 0xff;1916}1917 1918static void1919add_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 void1956add_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 1975void1976yyerror(const char *string)1977{1978	stop(string, EX_DATAERR);1979}1980 1981static int1982is_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 int1992is_location_address(symbol_t *sym)1993{1994	if (sym->type == SCBLOC ||1995	    sym->type == SRAMLOC)1996		return (TRUE);1997	return (FALSE);1998}1999 2000