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