aicasm_gram.y revision 50477
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, immediately at the beginning of the file.
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: head/sys/dev/aic7xxx/aicasm/aicasm_gram.y 50477 1999-08-28 01:08:13Z peter $
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
44int yylineno;
45char *yyfilename;
46static symbol_t *cur_symbol;
47static symtype cur_symtype;
48static symbol_t *accumulator;
49static symbol_ref_t allones;
50static symbol_ref_t allzeros;
51static symbol_ref_t none;
52static symbol_ref_t sindex;
53static int instruction_ptr;
54static int sram_or_scb_offset;
55static int download_constant_count;
56
57static void process_bitmask __P((int mask_type, symbol_t *sym, int mask));
58static void initialize_symbol __P((symbol_t *symbol));
59static void process_register __P((symbol_t **p_symbol));
60static void format_1_instr __P((int opcode, symbol_ref_t *dest,
61				expression_t *immed, symbol_ref_t *src,
62				int ret));
63static void format_2_instr __P((int opcode, symbol_ref_t *dest,
64				expression_t *places, symbol_ref_t *src,
65				int ret));
66static void format_3_instr __P((int opcode, symbol_ref_t *src,
67				expression_t *immed, symbol_ref_t *address));
68static void test_readable_symbol __P((symbol_t *symbol));
69static void test_writable_symbol __P((symbol_t *symbol));
70static void type_check __P((symbol_t *symbol, expression_t *expression,
71			    int and_op));
72static void make_expression __P((expression_t *immed, int value));
73static void add_conditional __P((symbol_t *symbol));
74static 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
168program:
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
187include:
188	T_INCLUDE '<' T_PATH '>'
189	{ include_file($3, BRACKETED_INCLUDE); }
190|	T_INCLUDE '"' T_PATH '"'
191	{ include_file($3, QUOTED_INCLUDE); }
192;
193
194register:
195	T_REGISTER { cur_symtype = REGISTER; } reg_definition
196;
197
198reg_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
236reg_attribute_list:
237	reg_attribute
238|	reg_attribute_list reg_attribute
239;
240
241reg_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
255reg_address:
256	T_ADDRESS T_NUMBER
257	{
258		cur_symbol->info.rinfo->address = $2;
259	}
260;
261
262size:
263	T_SIZE T_NUMBER
264	{
265		cur_symbol->info.rinfo->size = $2;
266	}
267;
268
269access_mode:
270	T_ACCESS_MODE T_MODE
271	{
272		cur_symbol->info.rinfo->mode = $2;
273	}
274;
275
276bit_defn:
277	T_BIT T_SYMBOL T_NUMBER
278	{
279		process_bitmask(BIT, $2, $3);
280	}
281;
282
283mask_defn:
284	T_MASK T_SYMBOL expression
285	{
286		process_bitmask(MASK, $2, $3.value);
287	}
288;
289
290alias:
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
304accumulator:
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
316allones:
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
328allzeros:
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
340none:
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
352sindex:
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
364expression:
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
451constant:
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
483numerical_value:
484	T_NUMBER
485	{
486		$$ = $1;
487	}
488|	'-' T_NUMBER
489	{
490		$$ = -$2;
491	}
492;
493
494scratch_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
518scb:
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
542scb_or_sram_reg_list:
543	reg_definition
544|	scb_or_sram_reg_list reg_definition
545;
546
547reg_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
576destination:
577	reg_symbol
578	{
579		test_writable_symbol($1.symbol);
580		$$ = $1;
581	}
582;
583
584immediate:
585	expression
586	{ $$ = $1; }
587;
588
589immediate_or_a:
590	expression
591	{
592		$$ = $1;
593	}
594|	T_A
595	{
596		SLIST_INIT(&$$.referenced_syms);
597		$$.value = 0;
598	}
599;
600
601source:
602	reg_symbol
603	{
604		test_readable_symbol($1.symbol);
605		$$ = $1;
606	}
607;
608
609opt_source:
610	{
611		$$.symbol = NULL;
612		$$.offset = 0;
613	}
614|	',' source
615	{ $$ = $2; }
616;
617
618ret:
619	{ $$ = 0; }
620|	T_RET
621	{ $$ = 1; }
622;
623
624label:
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
637address:
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
670conditional:
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
731conditional:
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
757f1_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
764code:
765	f1_opcode destination ',' immediate_or_a opt_source ret ';'
766	{
767		format_1_instr($1, &$2, &$4, &$5, $6);
768	}
769;
770
771code:
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
778code:
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
788code:
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
798code:
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
812code:
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
829code:
830	T_BMOV destination ',' source ',' immediate ret ';'
831	{
832		format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
833	}
834;
835
836code:
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
846code:
847	T_MVI destination ',' immediate_or_a ret ';'
848	{
849		format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
850	}
851;
852
853code:
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
863code:
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
873code:
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
892f2_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
899code:
900	f2_opcode destination ',' expression opt_source ret ';'
901	{
902		format_2_instr($1, &$2, &$4, &$5, $6);
903	}
904;
905
906jmp_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
913jz_jnz:
914	T_JZ	{ $$ = AIC_OP_JZ; }
915|	T_JNZ	{ $$ = AIC_OP_JNZ; }
916;
917
918je_jne:
919	T_JE	{ $$ = AIC_OP_JE; }
920|	T_JNE	{ $$ = AIC_OP_JNE; }
921;
922
923code:
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
933code:
934	T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
935	{
936		format_3_instr($5, &$2, &$4, &$6);
937	}
938;
939
940code:
941	T_TEST source ',' immediate_or_a jz_jnz address ';'
942	{
943		format_3_instr($5, &$2, &$4, &$6);
944	}
945;
946
947code:
948	T_CMP source ',' immediate_or_a je_jne address ';'
949	{
950		format_3_instr($5, &$2, &$4, &$6);
951	}
952;
953
954code:
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
964code:
965	T_MVI immediate jmp_jc_jnc_call address ';'
966	{
967		format_3_instr($3, &allzeros, &$2, &$4);
968	}
969;
970
971%%
972
973static void
974process_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
1021static void
1022initialize_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
1103static void
1104process_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
1127static void
1128format_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
1166static void
1167format_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
1231static void
1232format_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
1273static void
1274test_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
1284static void
1285test_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
1295static void
1296type_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
1347static void
1348make_expression(immed, value)
1349	expression_t *immed;
1350	int	     value;
1351{
1352	SLIST_INIT(&immed->referenced_syms);
1353	immed->value = value & 0xff;
1354}
1355
1356static void
1357add_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
1394void
1395yyerror(string)
1396	const char *string;
1397{
1398	stop(string, EX_DATAERR);
1399}
1400
1401static int
1402is_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