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