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