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