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