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