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