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