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