xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm_gram.y (revision 32da3127)
1 %{
2 /*
3  * Parser for the Aic7xxx SCSI Host adapter sequencer assembler.
4  *
5  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions, and the following disclaimer,
13  *    without modification.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * Alternatively, this software may be distributed under the terms of the
18  * GNU Public License ("GPL").
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id$
33  *
34  * $FreeBSD$
35  */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sysexits.h>
41 
42 #include <sys/types.h>
43 #ifdef __linux__
44 #include "../queue.h"
45 #else
46 #include <sys/queue.h>
47 #endif
48 
49 #include "aicasm.h"
50 #include "aicasm_symbol.h"
51 #include "aicasm_insformat.h"
52 
53 int yylineno;
54 char *yyfilename;
55 static symbol_t *cur_symbol;
56 static symtype cur_symtype;
57 static symbol_t *accumulator;
58 static symbol_ref_t allones;
59 static symbol_ref_t allzeros;
60 static symbol_ref_t none;
61 static symbol_ref_t sindex;
62 static int instruction_ptr;
63 static int sram_or_scb_offset;
64 static int download_constant_count;
65 
66 static void process_bitmask(int mask_type, symbol_t *sym, int mask);
67 static void initialize_symbol(symbol_t *symbol);
68 static void process_register(symbol_t **p_symbol);
69 static void format_1_instr(int opcode, symbol_ref_t *dest,
70 			   expression_t *immed, symbol_ref_t *src, int ret);
71 static void format_2_instr(int opcode, symbol_ref_t *dest,
72 			   expression_t *places, symbol_ref_t *src, int ret);
73 static void format_3_instr(int opcode, symbol_ref_t *src,
74 			   expression_t *immed, symbol_ref_t *address);
75 static void test_readable_symbol(symbol_t *symbol);
76 static void test_writable_symbol(symbol_t *symbol);
77 static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
78 static void make_expression(expression_t *immed, int value);
79 static void add_conditional(symbol_t *symbol);
80 static int  is_download_const(expression_t *immed);
81 
82 #define YYDEBUG 1
83 #define SRAM_SYMNAME "SRAM_BASE"
84 #define SCB_SYMNAME "SCB_BASE"
85 %}
86 
87 %union {
88 	int		value;
89 	char		*str;
90 	symbol_t	*sym;
91 	symbol_ref_t	sym_ref;
92 	expression_t	expression;
93 }
94 
95 %token T_REGISTER
96 
97 %token <value> T_CONST
98 
99 %token T_DOWNLOAD
100 
101 %token T_SCB
102 
103 %token T_SRAM
104 
105 %token T_ALIAS
106 
107 %token T_SIZE
108 
109 %token <value> T_ADDRESS
110 
111 %token T_ACCESS_MODE
112 
113 %token <value> T_MODE
114 
115 %token T_BIT
116 
117 %token T_MASK
118 
119 %token <value> T_NUMBER
120 
121 %token <str> T_PATH
122 
123 %token <sym> T_CEXPR
124 
125 %token T_EOF T_INCLUDE
126 
127 %token <value> T_SHR T_SHL T_ROR T_ROL
128 
129 %token <value> T_MVI T_MOV T_CLR T_BMOV
130 
131 %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
132 
133 %token <value> T_ADD T_ADC
134 
135 %token <value> T_INC T_DEC
136 
137 %token <value> T_STC T_CLC
138 
139 %token <value> T_CMP T_NOT T_XOR
140 
141 %token <value> T_TEST T_AND
142 
143 %token <value> T_OR
144 
145 %token T_RET
146 
147 %token T_NOP
148 
149 %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX
150 
151 %token T_A
152 
153 %token <sym> T_SYMBOL
154 
155 %token T_NL
156 
157 %token T_IF T_ELSE T_ELSE_IF T_ENDIF
158 
159 %type <sym_ref> reg_symbol address destination source opt_source
160 
161 %type <expression> expression immediate immediate_or_a
162 
163 %type <value> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
164 
165 %type <value> numerical_value
166 
167 %left '|'
168 %left '&'
169 %left '+' '-'
170 %right '~'
171 %nonassoc UMINUS
172 %%
173 
174 program:
175 	include
176 |	program include
177 |	register
178 |	program register
179 |	constant
180 |	program constant
181 |	scratch_ram
182 |	program scratch_ram
183 |	scb
184 |	program scb
185 |	label
186 |	program label
187 |	conditional
188 |	program conditional
189 |	code
190 |	program code
191 ;
192 
193 include:
194 	T_INCLUDE '<' T_PATH '>'
195 	{ include_file($3, BRACKETED_INCLUDE); }
196 |	T_INCLUDE '"' T_PATH '"'
197 	{ include_file($3, QUOTED_INCLUDE); }
198 ;
199 
200 register:
201 	T_REGISTER { cur_symtype = REGISTER; } reg_definition
202 ;
203 
204 reg_definition:
205 	T_SYMBOL '{'
206 		{
207 			if ($1->type != UNINITIALIZED) {
208 				stop("Register multiply defined", EX_DATAERR);
209 				/* NOTREACHED */
210 			}
211 			cur_symbol = $1;
212 			cur_symbol->type = cur_symtype;
213 			initialize_symbol(cur_symbol);
214 		}
215 		reg_attribute_list
216 	'}'
217 		{
218 			/*
219 			 * Default to allowing everything in for registers
220 			 * with no bit or mask definitions.
221 			 */
222 			if (cur_symbol->info.rinfo->valid_bitmask == 0)
223 				cur_symbol->info.rinfo->valid_bitmask = 0xFF;
224 
225 			if (cur_symbol->info.rinfo->size == 0)
226 				cur_symbol->info.rinfo->size = 1;
227 
228 			/*
229 			 * This might be useful for registers too.
230 			 */
231 			if (cur_symbol->type != REGISTER) {
232 				if (cur_symbol->info.rinfo->address == 0)
233 					cur_symbol->info.rinfo->address =
234 					    sram_or_scb_offset;
235 				sram_or_scb_offset +=
236 				    cur_symbol->info.rinfo->size;
237 			}
238 			cur_symbol = NULL;
239 		}
240 ;
241 
242 reg_attribute_list:
243 	reg_attribute
244 |	reg_attribute_list reg_attribute
245 ;
246 
247 reg_attribute:
248 	reg_address
249 |	size
250 |	access_mode
251 |	bit_defn
252 |	mask_defn
253 |	alias
254 |	accumulator
255 |	allones
256 |	allzeros
257 |	none
258 |	sindex
259 ;
260 
261 reg_address:
262 	T_ADDRESS T_NUMBER
263 	{
264 		cur_symbol->info.rinfo->address = $2;
265 	}
266 ;
267 
268 size:
269 	T_SIZE T_NUMBER
270 	{
271 		cur_symbol->info.rinfo->size = $2;
272 	}
273 ;
274 
275 access_mode:
276 	T_ACCESS_MODE T_MODE
277 	{
278 		cur_symbol->info.rinfo->mode = $2;
279 	}
280 ;
281 
282 bit_defn:
283 	T_BIT T_SYMBOL T_NUMBER
284 	{
285 		process_bitmask(BIT, $2, $3);
286 	}
287 ;
288 
289 mask_defn:
290 	T_MASK T_SYMBOL expression
291 	{
292 		process_bitmask(MASK, $2, $3.value);
293 	}
294 ;
295 
296 alias:
297 	T_ALIAS	T_SYMBOL
298 	{
299 		if ($2->type != UNINITIALIZED) {
300 			stop("Re-definition of register alias",
301 			     EX_DATAERR);
302 			/* NOTREACHED */
303 		}
304 		$2->type = ALIAS;
305 		initialize_symbol($2);
306 		$2->info.ainfo->parent = cur_symbol;
307 	}
308 ;
309 
310 accumulator:
311 	T_ACCUM
312 	{
313 		if (accumulator != NULL) {
314 			stop("Only one accumulator definition allowed",
315 			     EX_DATAERR);
316 			/* NOTREACHED */
317 		}
318 		accumulator = cur_symbol;
319 	}
320 ;
321 
322 allones:
323 	T_ALLONES
324 	{
325 		if (allones.symbol != NULL) {
326 			stop("Only one definition of allones allowed",
327 			     EX_DATAERR);
328 			/* NOTREACHED */
329 		}
330 		allones.symbol = cur_symbol;
331 	}
332 ;
333 
334 allzeros:
335 	T_ALLZEROS
336 	{
337 		if (allzeros.symbol != NULL) {
338 			stop("Only one definition of allzeros allowed",
339 			     EX_DATAERR);
340 			/* NOTREACHED */
341 		}
342 		allzeros.symbol = cur_symbol;
343 	}
344 ;
345 
346 none:
347 	T_NONE
348 	{
349 		if (none.symbol != NULL) {
350 			stop("Only one definition of none allowed",
351 			     EX_DATAERR);
352 			/* NOTREACHED */
353 		}
354 		none.symbol = cur_symbol;
355 	}
356 ;
357 
358 sindex:
359 	T_SINDEX
360 	{
361 		if (sindex.symbol != NULL) {
362 			stop("Only one definition of sindex allowed",
363 			     EX_DATAERR);
364 			/* NOTREACHED */
365 		}
366 		sindex.symbol = cur_symbol;
367 	}
368 ;
369 
370 expression:
371 	expression '|' expression
372 	{
373 		 $$.value = $1.value | $3.value;
374 		 symlist_merge(&$$.referenced_syms,
375 			       &$1.referenced_syms,
376 			       &$3.referenced_syms);
377 	}
378 |	expression '&' expression
379 	{
380 		$$.value = $1.value & $3.value;
381 		symlist_merge(&$$.referenced_syms,
382 			       &$1.referenced_syms,
383 			       &$3.referenced_syms);
384 	}
385 |	expression '+' expression
386 	{
387 		$$.value = $1.value + $3.value;
388 		symlist_merge(&$$.referenced_syms,
389 			       &$1.referenced_syms,
390 			       &$3.referenced_syms);
391 	}
392 |	expression '-' expression
393 	{
394 		$$.value = $1.value - $3.value;
395 		symlist_merge(&($$.referenced_syms),
396 			       &($1.referenced_syms),
397 			       &($3.referenced_syms));
398 	}
399 |	'(' expression ')'
400 	{
401 		$$ = $2;
402 	}
403 |	'~' expression
404 	{
405 		$$ = $2;
406 		$$.value = (~$$.value) & 0xFF;
407 	}
408 |	'-' expression %prec UMINUS
409 	{
410 		$$ = $2;
411 		$$.value = -$$.value;
412 	}
413 |	T_NUMBER
414 	{
415 		$$.value = $1;
416 		SLIST_INIT(&$$.referenced_syms);
417 	}
418 |	T_SYMBOL
419 	{
420 		symbol_t *symbol;
421 
422 		symbol = $1;
423 		switch (symbol->type) {
424 		case ALIAS:
425 			symbol = $1->info.ainfo->parent;
426 		case REGISTER:
427 		case SCBLOC:
428 		case SRAMLOC:
429 			$$.value = symbol->info.rinfo->address;
430 			break;
431 		case MASK:
432 		case BIT:
433 			$$.value = symbol->info.minfo->mask;
434 			break;
435 		case DOWNLOAD_CONST:
436 		case CONST:
437 			$$.value = symbol->info.cinfo->value;
438 			break;
439 		case UNINITIALIZED:
440 		default:
441 		{
442 			char buf[255];
443 
444 			snprintf(buf, sizeof(buf),
445 				 "Undefined symbol %s referenced",
446 				 symbol->name);
447 			stop(buf, EX_DATAERR);
448 			/* NOTREACHED */
449 			break;
450 		}
451 		}
452 		SLIST_INIT(&$$.referenced_syms);
453 		symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD);
454 	}
455 ;
456 
457 constant:
458 	T_CONST T_SYMBOL numerical_value
459 	{
460 		if ($2->type != UNINITIALIZED) {
461 			stop("Re-definition of symbol as a constant",
462 			     EX_DATAERR);
463 			/* NOTREACHED */
464 		}
465 		$2->type = CONST;
466 		initialize_symbol($2);
467 		$2->info.cinfo->value = $3;
468 		$2->info.cinfo->define = $1;
469 	}
470 |	T_CONST T_SYMBOL T_DOWNLOAD
471 	{
472 		if ($1) {
473 			stop("Invalid downloaded constant declaration",
474 			     EX_DATAERR);
475 			/* NOTREACHED */
476 		}
477 		if ($2->type != UNINITIALIZED) {
478 			stop("Re-definition of symbol as a downloaded constant",
479 			     EX_DATAERR);
480 			/* NOTREACHED */
481 		}
482 		$2->type = DOWNLOAD_CONST;
483 		initialize_symbol($2);
484 		$2->info.cinfo->value = download_constant_count++;
485 		$2->info.cinfo->define = FALSE;
486 	}
487 ;
488 
489 numerical_value:
490 	T_NUMBER
491 	{
492 		$$ = $1;
493 	}
494 |	'-' T_NUMBER
495 	{
496 		$$ = -$2;
497 	}
498 ;
499 
500 scratch_ram:
501 	T_SRAM '{'
502 		{
503 			cur_symbol = symtable_get(SRAM_SYMNAME);
504 			cur_symtype = SRAMLOC;
505 			if (cur_symbol->type != UNINITIALIZED) {
506 				stop("Only one SRAM definition allowed",
507 				     EX_DATAERR);
508 				/* NOTREACHED */
509 			}
510 			cur_symbol->type = SRAMLOC;
511 			initialize_symbol(cur_symbol);
512 		}
513 		reg_address
514 		{
515 			sram_or_scb_offset = cur_symbol->info.rinfo->address;
516 		}
517 		scb_or_sram_reg_list
518 	'}'
519 		{
520 			cur_symbol = NULL;
521 		}
522 ;
523 
524 scb:
525 	T_SCB '{'
526 		{
527 			cur_symbol = symtable_get(SCB_SYMNAME);
528 			cur_symtype = SCBLOC;
529 			if (cur_symbol->type != UNINITIALIZED) {
530 				stop("Only one SRAM definition allowed",
531 				     EX_SOFTWARE);
532 				/* NOTREACHED */
533 			}
534 			cur_symbol->type = SCBLOC;
535 			initialize_symbol(cur_symbol);
536 			/* 64 bytes of SCB space */
537 			cur_symbol->info.rinfo->size = 64;
538 		}
539 		reg_address
540 		{
541 			sram_or_scb_offset = cur_symbol->info.rinfo->address;
542 		}
543 		scb_or_sram_reg_list
544 	'}'
545 		{
546 			cur_symbol = NULL;
547 		}
548 ;
549 
550 scb_or_sram_reg_list:
551 	reg_definition
552 |	scb_or_sram_reg_list reg_definition
553 ;
554 
555 reg_symbol:
556 	T_SYMBOL
557 	{
558 		process_register(&$1);
559 		$$.symbol = $1;
560 		$$.offset = 0;
561 	}
562 |	T_SYMBOL '[' T_SYMBOL ']'
563 	{
564 		process_register(&$1);
565 		if ($3->type != CONST) {
566 			stop("register offset must be a constant", EX_DATAERR);
567 			/* NOTREACHED */
568 		}
569 		if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) {
570 			stop("Accessing offset beyond range of register",
571 			     EX_DATAERR);
572 			/* NOTREACHED */
573 		}
574 		$$.symbol = $1;
575 		$$.offset = $3->info.cinfo->value;
576 	}
577 |	T_SYMBOL '[' T_NUMBER ']'
578 	{
579 		process_register(&$1);
580 		if (($3 + 1) > $1->info.rinfo->size) {
581 			stop("Accessing offset beyond range of register",
582 			     EX_DATAERR);
583 			/* NOTREACHED */
584 		}
585 		$$.symbol = $1;
586 		$$.offset = $3;
587 	}
588 |	T_A
589 	{
590 		if (accumulator == NULL) {
591 			stop("No accumulator has been defined", EX_DATAERR);
592 			/* NOTREACHED */
593 		}
594 		$$.symbol = accumulator;
595 		$$.offset = 0;
596 	}
597 ;
598 
599 destination:
600 	reg_symbol
601 	{
602 		test_writable_symbol($1.symbol);
603 		$$ = $1;
604 	}
605 ;
606 
607 immediate:
608 	expression
609 	{ $$ = $1; }
610 ;
611 
612 immediate_or_a:
613 	expression
614 	{
615 		$$ = $1;
616 	}
617 |	T_A
618 	{
619 		SLIST_INIT(&$$.referenced_syms);
620 		$$.value = 0;
621 	}
622 ;
623 
624 source:
625 	reg_symbol
626 	{
627 		test_readable_symbol($1.symbol);
628 		$$ = $1;
629 	}
630 ;
631 
632 opt_source:
633 	{
634 		$$.symbol = NULL;
635 		$$.offset = 0;
636 	}
637 |	',' source
638 	{ $$ = $2; }
639 ;
640 
641 ret:
642 	{ $$ = 0; }
643 |	T_RET
644 	{ $$ = 1; }
645 ;
646 
647 label:
648 	T_SYMBOL ':'
649 	{
650 		if ($1->type != UNINITIALIZED) {
651 			stop("Program label multiply defined", EX_DATAERR);
652 			/* NOTREACHED */
653 		}
654 		$1->type = LABEL;
655 		initialize_symbol($1);
656 		$1->info.linfo->address = instruction_ptr;
657 	}
658 ;
659 
660 address:
661 	T_SYMBOL
662 	{
663 		$$.symbol = $1;
664 		$$.offset = 0;
665 	}
666 |	T_SYMBOL '+' T_NUMBER
667 	{
668 		$$.symbol = $1;
669 		$$.offset = $3;
670 	}
671 |	T_SYMBOL '-' T_NUMBER
672 	{
673 		$$.symbol = $1;
674 		$$.offset = -$3;
675 	}
676 |	'.'
677 	{
678 		$$.symbol = NULL;
679 		$$.offset = 0;
680 	}
681 |	'.' '+' T_NUMBER
682 	{
683 		$$.symbol = NULL;
684 		$$.offset = $3;
685 	}
686 |	'.' '-' T_NUMBER
687 	{
688 		$$.symbol = NULL;
689 		$$.offset = -$3;
690 	}
691 ;
692 
693 conditional:
694 	T_IF T_CEXPR '{'
695 	{
696 		scope_t *new_scope;
697 
698 		add_conditional($2);
699 		new_scope = scope_alloc();
700 		new_scope->type = SCOPE_IF;
701 		new_scope->begin_addr = instruction_ptr;
702 		new_scope->func_num = $2->info.condinfo->func_num;
703 	}
704 |	T_ELSE T_IF T_CEXPR '{'
705 	{
706 		scope_t *new_scope;
707 		scope_t *scope_context;
708 		scope_t *last_scope;
709 
710 		/*
711 		 * Ensure that the previous scope is either an
712 		 * if or and else if.
713 		 */
714 		scope_context = SLIST_FIRST(&scope_stack);
715 		last_scope = TAILQ_LAST(&scope_context->inner_scope,
716 					scope_tailq);
717 		if (last_scope == NULL
718 		 || last_scope->type == T_ELSE) {
719 
720 			stop("'else if' without leading 'if'", EX_DATAERR);
721 			/* NOTREACHED */
722 		}
723 		add_conditional($3);
724 		new_scope = scope_alloc();
725 		new_scope->type = SCOPE_ELSE_IF;
726 		new_scope->begin_addr = instruction_ptr;
727 		new_scope->func_num = $3->info.condinfo->func_num;
728 	}
729 |	T_ELSE '{'
730 	{
731 		scope_t *new_scope;
732 		scope_t *scope_context;
733 		scope_t *last_scope;
734 
735 		/*
736 		 * Ensure that the previous scope is either an
737 		 * if or and else if.
738 		 */
739 		scope_context = SLIST_FIRST(&scope_stack);
740 		last_scope = TAILQ_LAST(&scope_context->inner_scope,
741 					scope_tailq);
742 		if (last_scope == NULL
743 		 || last_scope->type == SCOPE_ELSE) {
744 
745 			stop("'else' without leading 'if'", EX_DATAERR);
746 			/* NOTREACHED */
747 		}
748 		new_scope = scope_alloc();
749 		new_scope->type = SCOPE_ELSE;
750 		new_scope->begin_addr = instruction_ptr;
751 	}
752 ;
753 
754 conditional:
755 	'}'
756 	{
757 		scope_t *scope_context;
758 
759 		scope_context = SLIST_FIRST(&scope_stack);
760 		if (scope_context->type == SCOPE_ROOT) {
761 			stop("Unexpected '}' encountered", EX_DATAERR);
762 			/* NOTREACHED */
763 		}
764 
765 		scope_context->end_addr = instruction_ptr;
766 
767 		/* Pop the scope */
768 		SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
769 
770 		process_scope(scope_context);
771 
772 		if (SLIST_FIRST(&scope_stack) == NULL) {
773 			stop("Unexpected '}' encountered", EX_DATAERR);
774 			/* NOTREACHED */
775 		}
776 	}
777 ;
778 
779 f1_opcode:
780 	T_AND { $$ = AIC_OP_AND; }
781 |	T_XOR { $$ = AIC_OP_XOR; }
782 |	T_ADD { $$ = AIC_OP_ADD; }
783 |	T_ADC { $$ = AIC_OP_ADC; }
784 ;
785 
786 code:
787 	f1_opcode destination ',' immediate_or_a opt_source ret ';'
788 	{
789 		format_1_instr($1, &$2, &$4, &$5, $6);
790 	}
791 ;
792 
793 code:
794 	T_OR reg_symbol ',' immediate_or_a opt_source ret ';'
795 	{
796 		format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6);
797 	}
798 ;
799 
800 code:
801 	T_INC destination opt_source ret ';'
802 	{
803 		expression_t immed;
804 
805 		make_expression(&immed, 1);
806 		format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
807 	}
808 ;
809 
810 code:
811 	T_DEC destination opt_source ret ';'
812 	{
813 		expression_t immed;
814 
815 		make_expression(&immed, -1);
816 		format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
817 	}
818 ;
819 
820 code:
821 	T_CLC ret ';'
822 	{
823 		expression_t immed;
824 
825 		make_expression(&immed, -1);
826 		format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2);
827 	}
828 |	T_CLC T_MVI destination ',' immediate_or_a ret ';'
829 	{
830 		format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6);
831 	}
832 ;
833 
834 code:
835 	T_STC ret ';'
836 	{
837 		expression_t immed;
838 
839 		make_expression(&immed, 1);
840 		format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2);
841 	}
842 |	T_STC destination ret ';'
843 	{
844 		expression_t immed;
845 
846 		make_expression(&immed, 1);
847 		format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3);
848 	}
849 ;
850 
851 code:
852 	T_BMOV destination ',' source ',' immediate_or_a ret ';'
853 	{
854 		format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
855 	}
856 ;
857 
858 code:
859 	T_MOV destination ',' source ret ';'
860 	{
861 		expression_t immed;
862 
863 		make_expression(&immed, 0xff);
864 		format_1_instr(AIC_OP_AND, &$2, &immed, &$4, $5);
865 	}
866 ;
867 
868 code:
869 	T_MVI destination ',' immediate_or_a ret ';'
870 	{
871 		format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
872 	}
873 ;
874 
875 code:
876 	T_NOT destination opt_source ret ';'
877 	{
878 		expression_t immed;
879 
880 		make_expression(&immed, 0xff);
881 		format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4);
882 	}
883 ;
884 
885 code:
886 	T_CLR destination ret ';'
887 	{
888 		expression_t immed;
889 
890 		make_expression(&immed, 0xff);
891 		format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3);
892 	}
893 ;
894 
895 code:
896 	T_NOP ret ';'
897 	{
898 		expression_t immed;
899 
900 		make_expression(&immed, 0xff);
901 		format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2);
902 	}
903 ;
904 
905 code:
906 	T_RET ';'
907 	{
908 		expression_t immed;
909 
910 		make_expression(&immed, 0xff);
911 		format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE);
912 	}
913 ;
914 
915 	/*
916 	 * This grammer differs from the one in the aic7xxx
917 	 * reference manual since the grammer listed there is
918 	 * ambiguous and causes a shift/reduce conflict.
919 	 * It also seems more logical as the "immediate"
920 	 * argument is listed as the second arg like the
921 	 * other formats.
922 	 */
923 
924 f2_opcode:
925 	T_SHL { $$ = AIC_OP_SHL; }
926 |	T_SHR { $$ = AIC_OP_SHR; }
927 |	T_ROL { $$ = AIC_OP_ROL; }
928 |	T_ROR { $$ = AIC_OP_ROR; }
929 ;
930 
931 code:
932 	f2_opcode destination ',' expression opt_source ret ';'
933 	{
934 		format_2_instr($1, &$2, &$4, &$5, $6);
935 	}
936 ;
937 
938 jmp_jc_jnc_call:
939 	T_JMP	{ $$ = AIC_OP_JMP; }
940 |	T_JC	{ $$ = AIC_OP_JC; }
941 |	T_JNC	{ $$ = AIC_OP_JNC; }
942 |	T_CALL	{ $$ = AIC_OP_CALL; }
943 ;
944 
945 jz_jnz:
946 	T_JZ	{ $$ = AIC_OP_JZ; }
947 |	T_JNZ	{ $$ = AIC_OP_JNZ; }
948 ;
949 
950 je_jne:
951 	T_JE	{ $$ = AIC_OP_JE; }
952 |	T_JNE	{ $$ = AIC_OP_JNE; }
953 ;
954 
955 code:
956 	jmp_jc_jnc_call address ';'
957 	{
958 		expression_t immed;
959 
960 		make_expression(&immed, 0);
961 		format_3_instr($1, &sindex, &immed, &$2);
962 	}
963 ;
964 
965 code:
966 	T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
967 	{
968 		format_3_instr($5, &$2, &$4, &$6);
969 	}
970 ;
971 
972 code:
973 	T_TEST source ',' immediate_or_a jz_jnz address ';'
974 	{
975 		format_3_instr($5, &$2, &$4, &$6);
976 	}
977 ;
978 
979 code:
980 	T_CMP source ',' immediate_or_a je_jne address ';'
981 	{
982 		format_3_instr($5, &$2, &$4, &$6);
983 	}
984 ;
985 
986 code:
987 	T_MOV source jmp_jc_jnc_call address ';'
988 	{
989 		expression_t immed;
990 
991 		make_expression(&immed, 0);
992 		format_3_instr($3, &$2, &immed, &$4);
993 	}
994 ;
995 
996 code:
997 	T_MVI immediate jmp_jc_jnc_call address ';'
998 	{
999 		format_3_instr($3, &allzeros, &$2, &$4);
1000 	}
1001 ;
1002 
1003 %%
1004 
1005 static void
1006 process_bitmask(int mask_type, symbol_t *sym, int mask)
1007 {
1008 	/*
1009 	 * Add the current register to its
1010 	 * symbol list, if it already exists,
1011 	 * warn if we are setting it to a
1012 	 * different value, or in the bit to
1013 	 * the "allowed bits" of this register.
1014 	 */
1015 	if (sym->type == UNINITIALIZED) {
1016 		sym->type = mask_type;
1017 		initialize_symbol(sym);
1018 		if (mask_type == BIT) {
1019 			if (mask == 0) {
1020 				stop("Bitmask with no bits set", EX_DATAERR);
1021 				/* NOTREACHED */
1022 			}
1023 			if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) {
1024 				stop("Bitmask with more than one bit set",
1025 				     EX_DATAERR);
1026 				/* NOTREACHED */
1027 			}
1028 		}
1029 		sym->info.minfo->mask = mask;
1030 	} else if (sym->type != mask_type) {
1031 		stop("Bit definition mirrors a definition of the same "
1032 		     " name, but a different type", EX_DATAERR);
1033 		/* NOTREACHED */
1034 	} else if (mask != sym->info.minfo->mask) {
1035 		stop("Bitmask redefined with a conflicting value", EX_DATAERR);
1036 		/* NOTREACHED */
1037 	}
1038 	/* Fail if this symbol is already listed */
1039 	if (symlist_search(&(sym->info.minfo->symrefs),
1040 			   cur_symbol->name) != NULL) {
1041 		stop("Bitmask defined multiple times for register", EX_DATAERR);
1042 		/* NOTREACHED */
1043 	}
1044 	symlist_add(&(sym->info.minfo->symrefs), cur_symbol,
1045 		    SYMLIST_INSERT_HEAD);
1046 	cur_symbol->info.rinfo->valid_bitmask |= mask;
1047 	cur_symbol->info.rinfo->typecheck_masks = TRUE;
1048 }
1049 
1050 static void
1051 initialize_symbol(symbol_t *symbol)
1052 {
1053 	switch (symbol->type) {
1054         case UNINITIALIZED:
1055 		stop("Call to initialize_symbol with type field unset",
1056 		     EX_SOFTWARE);
1057 		/* NOTREACHED */
1058 		break;
1059         case REGISTER:
1060         case SRAMLOC:
1061         case SCBLOC:
1062 		symbol->info.rinfo =
1063 		    (struct reg_info *)malloc(sizeof(struct reg_info));
1064 		if (symbol->info.rinfo == NULL) {
1065 			stop("Can't create register info", EX_SOFTWARE);
1066 			/* NOTREACHED */
1067 		}
1068 		memset(symbol->info.rinfo, 0,
1069 		       sizeof(struct reg_info));
1070 		break;
1071         case ALIAS:
1072 		symbol->info.ainfo =
1073 		    (struct alias_info *)malloc(sizeof(struct alias_info));
1074 		if (symbol->info.ainfo == NULL) {
1075 			stop("Can't create alias info", EX_SOFTWARE);
1076 			/* NOTREACHED */
1077 		}
1078 		memset(symbol->info.ainfo, 0,
1079 		       sizeof(struct alias_info));
1080 		break;
1081         case MASK:
1082         case BIT:
1083 		symbol->info.minfo =
1084 		    (struct mask_info *)malloc(sizeof(struct mask_info));
1085 		if (symbol->info.minfo == NULL) {
1086 			stop("Can't create bitmask info", EX_SOFTWARE);
1087 			/* NOTREACHED */
1088 		}
1089 		memset(symbol->info.minfo, 0, sizeof(struct mask_info));
1090 		SLIST_INIT(&(symbol->info.minfo->symrefs));
1091 		break;
1092         case CONST:
1093         case DOWNLOAD_CONST:
1094 		symbol->info.cinfo =
1095 		    (struct const_info *)malloc(sizeof(struct const_info));
1096 		if (symbol->info.cinfo == NULL) {
1097 			stop("Can't create alias info", EX_SOFTWARE);
1098 			/* NOTREACHED */
1099 		}
1100 		memset(symbol->info.cinfo, 0,
1101 		       sizeof(struct const_info));
1102 		break;
1103 	case LABEL:
1104 		symbol->info.linfo =
1105 		    (struct label_info *)malloc(sizeof(struct label_info));
1106 		if (symbol->info.linfo == NULL) {
1107 			stop("Can't create label info", EX_SOFTWARE);
1108 			/* NOTREACHED */
1109 		}
1110 		memset(symbol->info.linfo, 0,
1111 		       sizeof(struct label_info));
1112 		break;
1113 	case CONDITIONAL:
1114 		symbol->info.condinfo =
1115 		    (struct cond_info *)malloc(sizeof(struct cond_info));
1116 		if (symbol->info.condinfo == NULL) {
1117 			stop("Can't create conditional info", EX_SOFTWARE);
1118 			/* NOTREACHED */
1119 		}
1120 		memset(symbol->info.condinfo, 0,
1121 		       sizeof(struct cond_info));
1122 		break;
1123 	default:
1124 		stop("Call to initialize_symbol with invalid symbol type",
1125 		     EX_SOFTWARE);
1126 		/* NOTREACHED */
1127 		break;
1128 	}
1129 }
1130 
1131 static void
1132 process_register(symbol_t **p_symbol)
1133 {
1134 	char buf[255];
1135 	symbol_t *symbol = *p_symbol;
1136 
1137 	if (symbol->type == UNINITIALIZED) {
1138 		snprintf(buf, sizeof(buf), "Undefined register %s",
1139 			 symbol->name);
1140 		stop(buf, EX_DATAERR);
1141 		/* NOTREACHED */
1142 	} else if (symbol->type == ALIAS) {
1143 		*p_symbol = symbol->info.ainfo->parent;
1144 	} else if ((symbol->type != REGISTER)
1145 		&& (symbol->type != SCBLOC)
1146 		&& (symbol->type != SRAMLOC)) {
1147 		snprintf(buf, sizeof(buf),
1148 			 "Specified symbol %s is not a register",
1149 			 symbol->name);
1150 		stop(buf, EX_DATAERR);
1151 	}
1152 }
1153 
1154 static void
1155 format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
1156 	       symbol_ref_t *src, int ret)
1157 {
1158 	struct instruction *instr;
1159 	struct ins_format1 *f1_instr;
1160 
1161 	if (src->symbol == NULL)
1162 		src = dest;
1163 
1164 	/* Test register permissions */
1165 	test_writable_symbol(dest->symbol);
1166 	test_readable_symbol(src->symbol);
1167 
1168 	/* Ensure that immediate makes sense for this destination */
1169 	type_check(dest->symbol, immed, opcode);
1170 
1171 	/* Allocate sequencer space for the instruction and fill it out */
1172 	instr = seq_alloc();
1173 	f1_instr = &instr->format.format1;
1174 	f1_instr->ret = ret ? 1 : 0;
1175 	f1_instr->opcode = opcode;
1176 	f1_instr->destination = dest->symbol->info.rinfo->address
1177 			      + dest->offset;
1178 	f1_instr->source = src->symbol->info.rinfo->address
1179 			 + src->offset;
1180 	f1_instr->immediate = immed->value;
1181 
1182 	if (is_download_const(immed))
1183 		f1_instr->parity = 1;
1184 
1185 	symlist_free(&immed->referenced_syms);
1186 	instruction_ptr++;
1187 }
1188 
1189 static void
1190 format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places,
1191 	       symbol_ref_t *src, int ret)
1192 {
1193 	struct instruction *instr;
1194 	struct ins_format2 *f2_instr;
1195 	uint8_t shift_control;
1196 
1197 	if (src->symbol == NULL)
1198 		src = dest;
1199 
1200 	/* Test register permissions */
1201 	test_writable_symbol(dest->symbol);
1202 	test_readable_symbol(src->symbol);
1203 
1204 	/* Allocate sequencer space for the instruction and fill it out */
1205 	instr = seq_alloc();
1206 	f2_instr = &instr->format.format2;
1207 	f2_instr->ret = ret ? 1 : 0;
1208 	f2_instr->opcode = AIC_OP_ROL;
1209 	f2_instr->destination = dest->symbol->info.rinfo->address
1210 			      + dest->offset;
1211 	f2_instr->source = src->symbol->info.rinfo->address
1212 			 + src->offset;
1213 	if (places->value > 8 || places->value <= 0) {
1214 		stop("illegal shift value", EX_DATAERR);
1215 		/* NOTREACHED */
1216 	}
1217 	switch (opcode) {
1218 	case AIC_OP_SHL:
1219 		if (places->value == 8)
1220 			shift_control = 0xf0;
1221 		else
1222 			shift_control = (places->value << 4) | places->value;
1223 		break;
1224 	case AIC_OP_SHR:
1225 		if (places->value == 8) {
1226 			shift_control = 0xf8;
1227 		} else {
1228 			shift_control = (places->value << 4)
1229 				      | (8 - places->value)
1230 				      | 0x08;
1231 		}
1232 		break;
1233 	case AIC_OP_ROL:
1234 		shift_control = places->value & 0x7;
1235 		break;
1236 	case AIC_OP_ROR:
1237 		shift_control = (8 - places->value) | 0x08;
1238 		break;
1239 	default:
1240 		shift_control = 0; /* Quiet Compiler */
1241 		stop("Invalid shift operation specified", EX_SOFTWARE);
1242 		/* NOTREACHED */
1243 		break;
1244 	};
1245 	f2_instr->shift_control = shift_control;
1246 	symlist_free(&places->referenced_syms);
1247 	instruction_ptr++;
1248 }
1249 
1250 static void
1251 format_3_instr(int opcode, symbol_ref_t *src,
1252 	       expression_t *immed, symbol_ref_t *address)
1253 {
1254 	struct instruction *instr;
1255 	struct ins_format3 *f3_instr;
1256 	int addr;
1257 
1258 	/* Test register permissions */
1259 	test_readable_symbol(src->symbol);
1260 
1261 	/* Ensure that immediate makes sense for this source */
1262 	type_check(src->symbol, immed, opcode);
1263 
1264 	/* Allocate sequencer space for the instruction and fill it out */
1265 	instr = seq_alloc();
1266 	f3_instr = &instr->format.format3;
1267 	if (address->symbol == NULL) {
1268 		/* 'dot' referrence.  Use the current instruction pointer */
1269 		addr = instruction_ptr + address->offset;
1270 	} else if (address->symbol->type == UNINITIALIZED) {
1271 		/* forward reference */
1272 		addr = address->offset;
1273 		instr->patch_label = address->symbol;
1274 	} else
1275 		addr = address->symbol->info.linfo->address + address->offset;
1276 	f3_instr->opcode = opcode;
1277 	f3_instr->address = addr;
1278 	f3_instr->source = src->symbol->info.rinfo->address
1279 			 + src->offset;
1280 	f3_instr->immediate = immed->value;
1281 
1282 	if (is_download_const(immed))
1283 		f3_instr->parity = 1;
1284 
1285 	symlist_free(&immed->referenced_syms);
1286 	instruction_ptr++;
1287 }
1288 
1289 static void
1290 test_readable_symbol(symbol_t *symbol)
1291 {
1292 	if (symbol->info.rinfo->mode == WO) {
1293 		stop("Write Only register specified as source",
1294 		     EX_DATAERR);
1295 		/* NOTREACHED */
1296 	}
1297 }
1298 
1299 static void
1300 test_writable_symbol(symbol_t *symbol)
1301 {
1302 	if (symbol->info.rinfo->mode == RO) {
1303 		stop("Read Only register specified as destination",
1304 		     EX_DATAERR);
1305 		/* NOTREACHED */
1306 	}
1307 }
1308 
1309 static void
1310 type_check(symbol_t *symbol, expression_t *expression, int opcode)
1311 {
1312 	symbol_node_t *node;
1313 	int and_op;
1314 	char buf[255];
1315 
1316 	and_op = FALSE;
1317 	if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
1318 		and_op = TRUE;
1319 
1320 	/*
1321 	 * Make sure that we aren't attempting to write something
1322 	 * that hasn't been defined.  If this is an and operation,
1323 	 * this is a mask, so "undefined" bits are okay.
1324 	 */
1325 	if (and_op == FALSE
1326 	 && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
1327 		snprintf(buf, sizeof(buf),
1328 			 "Invalid bit(s) 0x%x in immediate written to %s",
1329 			 expression->value & ~symbol->info.rinfo->valid_bitmask,
1330 			 symbol->name);
1331 		stop(buf, EX_DATAERR);
1332 		/* NOTREACHED */
1333 	}
1334 
1335 	/*
1336 	 * Now make sure that all of the symbols referenced by the
1337 	 * expression are defined for this register.
1338 	 */
1339 	if(symbol->info.rinfo->typecheck_masks != FALSE) {
1340 		for(node = expression->referenced_syms.slh_first;
1341 		    node != NULL;
1342 		    node = node->links.sle_next) {
1343 			if ((node->symbol->type == MASK
1344 			  || node->symbol->type == BIT)
1345 			 && symlist_search(&node->symbol->info.minfo->symrefs,
1346 					   symbol->name) == NULL) {
1347 				snprintf(buf, sizeof(buf),
1348 					 "Invalid bit or mask %s "
1349 					 "for register %s",
1350 					 node->symbol->name, symbol->name);
1351 				stop(buf, EX_DATAERR);
1352 				/* NOTREACHED */
1353 			}
1354 		}
1355 	}
1356 }
1357 
1358 static void
1359 make_expression(expression_t *immed, int value)
1360 {
1361 	SLIST_INIT(&immed->referenced_syms);
1362 	immed->value = value & 0xff;
1363 }
1364 
1365 static void
1366 add_conditional(symbol_t *symbol)
1367 {
1368 	static int numfuncs;
1369 
1370 	if (numfuncs == 0) {
1371 		/* add a special conditional, "0" */
1372 		symbol_t *false_func;
1373 
1374 		false_func = symtable_get("0");
1375 		if (false_func->type != UNINITIALIZED) {
1376 			stop("Conditional expression '0' "
1377 			     "conflicts with a symbol", EX_DATAERR);
1378 			/* NOTREACHED */
1379 		}
1380 		false_func->type = CONDITIONAL;
1381 		initialize_symbol(false_func);
1382 		false_func->info.condinfo->func_num = numfuncs++;
1383 		symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
1384 	}
1385 
1386 	/* This condition has occurred before */
1387 	if (symbol->type == CONDITIONAL)
1388 		return;
1389 
1390 	if (symbol->type != UNINITIALIZED) {
1391 		stop("Conditional expression conflicts with a symbol",
1392 		     EX_DATAERR);
1393 		/* NOTREACHED */
1394 	}
1395 
1396 	symbol->type = CONDITIONAL;
1397 	initialize_symbol(symbol);
1398 	symbol->info.condinfo->func_num = numfuncs++;
1399 	symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
1400 }
1401 
1402 void
1403 yyerror(const char *string)
1404 {
1405 	stop(string, EX_DATAERR);
1406 }
1407 
1408 static int
1409 is_download_const(expression_t *immed)
1410 {
1411 	if ((immed->referenced_syms.slh_first != NULL)
1412 	 && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST))
1413 		return (TRUE);
1414 
1415 	return (FALSE);
1416 }
1417