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