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