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