aicasm_gram.y revision 63457
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: head/sys/dev/aic7xxx/aicasm/aicasm_gram.y 63457 2000-07-18 20:12:14Z gibbs $
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
47int yylineno;
48char *yyfilename;
49static symbol_t *cur_symbol;
50static symtype cur_symtype;
51static symbol_t *accumulator;
52static symbol_ref_t allones;
53static symbol_ref_t allzeros;
54static symbol_ref_t none;
55static symbol_ref_t sindex;
56static int instruction_ptr;
57static int sram_or_scb_offset;
58static int download_constant_count;
59
60static void process_bitmask __P((int mask_type, symbol_t *sym, int mask));
61static void initialize_symbol __P((symbol_t *symbol));
62static void process_register __P((symbol_t **p_symbol));
63static void format_1_instr __P((int opcode, symbol_ref_t *dest,
64				expression_t *immed, symbol_ref_t *src,
65				int ret));
66static void format_2_instr __P((int opcode, symbol_ref_t *dest,
67				expression_t *places, symbol_ref_t *src,
68				int ret));
69static void format_3_instr __P((int opcode, symbol_ref_t *src,
70				expression_t *immed, symbol_ref_t *address));
71static void test_readable_symbol __P((symbol_t *symbol));
72static void test_writable_symbol __P((symbol_t *symbol));
73static void type_check __P((symbol_t *symbol, expression_t *expression,
74			    int and_op));
75static void make_expression __P((expression_t *immed, int value));
76static void add_conditional __P((symbol_t *symbol));
77static 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
171program:
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
190include:
191	T_INCLUDE '<' T_PATH '>'
192	{ include_file($3, BRACKETED_INCLUDE); }
193|	T_INCLUDE '"' T_PATH '"'
194	{ include_file($3, QUOTED_INCLUDE); }
195;
196
197register:
198	T_REGISTER { cur_symtype = REGISTER; } reg_definition
199;
200
201reg_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
239reg_attribute_list:
240	reg_attribute
241|	reg_attribute_list reg_attribute
242;
243
244reg_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
258reg_address:
259	T_ADDRESS T_NUMBER
260	{
261		cur_symbol->info.rinfo->address = $2;
262	}
263;
264
265size:
266	T_SIZE T_NUMBER
267	{
268		cur_symbol->info.rinfo->size = $2;
269	}
270;
271
272access_mode:
273	T_ACCESS_MODE T_MODE
274	{
275		cur_symbol->info.rinfo->mode = $2;
276	}
277;
278
279bit_defn:
280	T_BIT T_SYMBOL T_NUMBER
281	{
282		process_bitmask(BIT, $2, $3);
283	}
284;
285
286mask_defn:
287	T_MASK T_SYMBOL expression
288	{
289		process_bitmask(MASK, $2, $3.value);
290	}
291;
292
293alias:
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
307accumulator:
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
319allones:
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
331allzeros:
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
343none:
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
355sindex:
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
367expression:
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
454constant:
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
486numerical_value:
487	T_NUMBER
488	{
489		$$ = $1;
490	}
491|	'-' T_NUMBER
492	{
493		$$ = -$2;
494	}
495;
496
497scratch_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
521scb:
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
545scb_or_sram_reg_list:
546	reg_definition
547|	scb_or_sram_reg_list reg_definition
548;
549
550reg_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
594destination:
595	reg_symbol
596	{
597		test_writable_symbol($1.symbol);
598		$$ = $1;
599	}
600;
601
602immediate:
603	expression
604	{ $$ = $1; }
605;
606
607immediate_or_a:
608	expression
609	{
610		$$ = $1;
611	}
612|	T_A
613	{
614		SLIST_INIT(&$$.referenced_syms);
615		$$.value = 0;
616	}
617;
618
619source:
620	reg_symbol
621	{
622		test_readable_symbol($1.symbol);
623		$$ = $1;
624	}
625;
626
627opt_source:
628	{
629		$$.symbol = NULL;
630		$$.offset = 0;
631	}
632|	',' source
633	{ $$ = $2; }
634;
635
636ret:
637	{ $$ = 0; }
638|	T_RET
639	{ $$ = 1; }
640;
641
642label:
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
655address:
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
688conditional:
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
749conditional:
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
775f1_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
782code:
783	f1_opcode destination ',' immediate_or_a opt_source ret ';'
784	{
785		format_1_instr($1, &$2, &$4, &$5, $6);
786	}
787;
788
789code:
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
796code:
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
806code:
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
816code:
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
830code:
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
847code:
848	T_BMOV destination ',' source ',' immediate_or_a ret ';'
849	{
850		format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
851	}
852;
853
854code:
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
864code:
865	T_MVI destination ',' immediate_or_a ret ';'
866	{
867		format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
868	}
869;
870
871code:
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
881code:
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
891code:
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
901code:
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
920f2_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
927code:
928	f2_opcode destination ',' expression opt_source ret ';'
929	{
930		format_2_instr($1, &$2, &$4, &$5, $6);
931	}
932;
933
934jmp_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
941jz_jnz:
942	T_JZ	{ $$ = AIC_OP_JZ; }
943|	T_JNZ	{ $$ = AIC_OP_JNZ; }
944;
945
946je_jne:
947	T_JE	{ $$ = AIC_OP_JE; }
948|	T_JNE	{ $$ = AIC_OP_JNE; }
949;
950
951code:
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
961code:
962	T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
963	{
964		format_3_instr($5, &$2, &$4, &$6);
965	}
966;
967
968code:
969	T_TEST source ',' immediate_or_a jz_jnz address ';'
970	{
971		format_3_instr($5, &$2, &$4, &$6);
972	}
973;
974
975code:
976	T_CMP source ',' immediate_or_a je_jne address ';'
977	{
978		format_3_instr($5, &$2, &$4, &$6);
979	}
980;
981
982code:
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
992code:
993	T_MVI immediate jmp_jc_jnc_call address ';'
994	{
995		format_3_instr($3, &allzeros, &$2, &$4);
996	}
997;
998
999%%
1000
1001static void
1002process_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
1049static void
1050initialize_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
1131static void
1132process_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
1155static void
1156format_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
1194static void
1195format_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
1259static void
1260format_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
1301static void
1302test_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
1312static void
1313test_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
1323static void
1324type_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
1375static void
1376make_expression(immed, value)
1377	expression_t *immed;
1378	int	     value;
1379{
1380	SLIST_INIT(&immed->referenced_syms);
1381	immed->value = value & 0xff;
1382}
1383
1384static void
1385add_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
1422void
1423yyerror(string)
1424	const char *string;
1425{
1426	stop(string, EX_DATAERR);
1427}
1428
1429static int
1430is_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