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