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