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