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