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