]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/aic7xxx/aicasm/aicasm_gram.y
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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, 2000 Justin T. Gibbs.
6  * Copyright (c) 2001, 2002 Adaptec Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions, and the following disclaimer,
14  *    without modification.
15  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16  *    substantially similar to the "NO WARRANTY" disclaimer below
17  *    ("Disclaimer") and any redistribution must be conditioned upon
18  *    including a substantially similar Disclaimer requirement for further
19  *    binary redistribution.
20  * 3. Neither the names of the above-listed copyright holders nor the names
21  *    of any contributors may be used to endorse or promote products derived
22  *    from this software without specific prior written permission.
23  *
24  * Alternatively, this software may be distributed under the terms of the
25  * GNU General Public License ("GPL") version 2 as published by the Free
26  * Software Foundation.
27  *
28  * NO WARRANTY
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGES.
40  *
41  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
42  *
43  * $FreeBSD$
44  */
45
46 #include <sys/types.h>
47
48 #include <inttypes.h>
49 #include <regex.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sysexits.h>
54
55 #ifdef __linux__
56 #include "../queue.h"
57 #else
58 #include <sys/queue.h>
59 #endif
60
61 #include "aicasm.h"
62 #include "aicasm_symbol.h"
63 #include "aicasm_insformat.h"
64
65 int yylineno;
66 char *yyfilename;
67 char stock_prefix[] = "aic_";
68 char *prefix = stock_prefix;
69 char *patch_arg_list;
70 char *versions;
71 static char errbuf[255];
72 static char regex_pattern[255];
73 static symbol_t *cur_symbol;
74 static symbol_t *field_symbol;
75 static symbol_t *scb_or_sram_symbol;
76 static symtype cur_symtype;
77 static symbol_ref_t accumulator;
78 static symbol_ref_t mode_ptr;
79 static symbol_ref_t allones;
80 static symbol_ref_t allzeros;
81 static symbol_ref_t none;
82 static symbol_ref_t sindex;
83 static int instruction_ptr;
84 static int num_srams;
85 static int sram_or_scb_offset;
86 static int download_constant_count;
87 static int in_critical_section;
88 static u_int enum_increment;
89 static u_int enum_next_value;
90
91 static void process_field(int field_type, symbol_t *sym, int mask);
92 static void initialize_symbol(symbol_t *symbol);
93 static void add_macro_arg(const char *argtext, int position);
94 static void add_macro_body(const char *bodytext);
95 static void process_register(symbol_t **p_symbol);
96 static void format_1_instr(int opcode, symbol_ref_t *dest,
97                            expression_t *immed, symbol_ref_t *src, int ret);
98 static void format_2_instr(int opcode, symbol_ref_t *dest,
99                            expression_t *places, symbol_ref_t *src, int ret);
100 static void format_3_instr(int opcode, symbol_ref_t *src,
101                            expression_t *immed, symbol_ref_t *address);
102 static void test_readable_symbol(symbol_t *symbol);
103 static void test_writable_symbol(symbol_t *symbol);
104 static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
105 static void make_expression(expression_t *immed, int value);
106 static void add_conditional(symbol_t *symbol);
107 static void add_version(const char *verstring);
108 static int  is_download_const(expression_t *immed);
109
110 #define SRAM_SYMNAME "SRAM_BASE"
111 #define SCB_SYMNAME "SCB_BASE"
112 %}
113
114 %union {
115         u_int           value;
116         char            *str;
117         symbol_t        *sym;
118         symbol_ref_t    sym_ref;
119         expression_t    expression;
120 }
121
122 %token T_REGISTER
123
124 %token <value> T_CONST
125
126 %token T_EXPORT
127
128 %token T_DOWNLOAD
129
130 %token T_SCB
131
132 %token T_SRAM
133
134 %token T_ALIAS
135
136 %token T_SIZE
137
138 %token T_EXPR_LSHIFT
139
140 %token T_EXPR_RSHIFT
141
142 %token <value> T_ADDRESS
143
144 %token T_ACCESS_MODE
145
146 %token T_MODES
147
148 %token T_DEFINE
149
150 %token T_SET_SRC_MODE
151
152 %token T_SET_DST_MODE
153
154 %token <value> T_MODE
155
156 %token T_BEGIN_CS
157
158 %token T_END_CS
159
160 %token T_FIELD
161
162 %token T_ENUM
163
164 %token T_MASK
165
166 %token <value> T_NUMBER
167
168 %token <str> T_PATH T_STRING T_ARG T_MACROBODY
169
170 %token <sym> T_CEXPR
171
172 %token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST
173
174 %token <value> T_SHR T_SHL T_ROR T_ROL
175
176 %token <value> T_MVI T_MOV T_CLR T_BMOV
177
178 %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
179
180 %token <value> T_ADD T_ADC
181
182 %token <value> T_INC T_DEC
183
184 %token <value> T_STC T_CLC
185
186 %token <value> T_CMP T_NOT T_XOR
187
188 %token <value> T_TEST T_AND
189
190 %token <value> T_OR
191
192 %token T_RET
193
194 %token T_NOP
195
196 %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR
197
198 %token T_A
199
200 %token <sym> T_SYMBOL
201
202 %token T_NL
203
204 %token T_IF T_ELSE T_ELSE_IF T_ENDIF
205
206 %type <sym_ref> reg_symbol address destination source opt_source
207
208 %type <expression> expression immediate immediate_or_a
209
210 %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
211
212 %type <value> mode_value mode_list macro_arglist
213
214 %left '|'
215 %left '&'
216 %left T_EXPR_LSHIFT T_EXPR_RSHIFT
217 %left '+' '-'
218 %left '*' '/'
219 %right '~'
220 %nonassoc UMINUS
221 %%
222
223 program:
224         include
225 |       program include
226 |       prefix
227 |       program prefix
228 |       patch_arg_list
229 |       program patch_arg_list
230 |       version
231 |       program version
232 |       register
233 |       program register
234 |       constant
235 |       program constant
236 |       macrodefn
237 |       program macrodefn
238 |       scratch_ram
239 |       program scratch_ram
240 |       scb
241 |       program scb
242 |       label
243 |       program label
244 |       set_src_mode
245 |       program set_src_mode
246 |       set_dst_mode
247 |       program set_dst_mode
248 |       critical_section_start
249 |       program critical_section_start
250 |       critical_section_end
251 |       program critical_section_end
252 |       conditional
253 |       program conditional
254 |       code
255 |       program code
256 ;
257
258 include:
259         T_INCLUDE '<' T_PATH '>'
260         {
261                 include_file($3, BRACKETED_INCLUDE);
262         }
263 |       T_INCLUDE '"' T_PATH '"'
264         {
265                 include_file($3, QUOTED_INCLUDE);
266         }
267 ;
268
269 prefix:
270         T_PREFIX '=' T_STRING
271         {
272                 if (prefix != stock_prefix)
273                         stop("Prefix multiply defined",
274                              EX_DATAERR);
275                 prefix = strdup($3);
276                 if (prefix == NULL)
277                         stop("Unable to record prefix", EX_SOFTWARE);
278         }
279 ;
280
281 patch_arg_list:
282         T_PATCH_ARG_LIST '=' T_STRING
283         {
284                 if (patch_arg_list != NULL)
285                         stop("Patch argument list multiply defined",
286                              EX_DATAERR);
287                 patch_arg_list = strdup($3);
288                 if (patch_arg_list == NULL)
289                         stop("Unable to record patch arg list", EX_SOFTWARE);
290         }
291 ;
292
293 version:
294         T_VERSION '=' T_STRING
295         { add_version($3); }
296 ;
297
298 register:
299         T_REGISTER { cur_symtype = REGISTER; } reg_definition
300 ;
301
302 reg_definition:
303         T_SYMBOL '{'
304                 {
305                         if ($1->type != UNINITIALIZED) {
306                                 stop("Register multiply defined", EX_DATAERR);
307                                 /* NOTREACHED */
308                         }
309                         cur_symbol = $1; 
310                         cur_symbol->type = cur_symtype;
311                         initialize_symbol(cur_symbol);
312                 }
313                 reg_attribute_list
314         '}'
315                 {                    
316                         /*
317                          * Default to allowing everything in for registers
318                          * with no bit or mask definitions.
319                          */
320                         if (cur_symbol->info.rinfo->valid_bitmask == 0)
321                                 cur_symbol->info.rinfo->valid_bitmask = 0xFF;
322
323                         if (cur_symbol->info.rinfo->size == 0)
324                                 cur_symbol->info.rinfo->size = 1;
325
326                         /*
327                          * This might be useful for registers too.
328                          */
329                         if (cur_symbol->type != REGISTER) {
330                                 if (cur_symbol->info.rinfo->address == 0)
331                                         cur_symbol->info.rinfo->address =
332                                             sram_or_scb_offset;
333                                 sram_or_scb_offset +=
334                                     cur_symbol->info.rinfo->size;
335                         }
336                         cur_symbol = NULL;
337                 }
338 ;
339
340 reg_attribute_list:
341         reg_attribute
342 |       reg_attribute_list reg_attribute
343 ;
344
345 reg_attribute:          
346         reg_address
347 |       size
348 |       access_mode
349 |       modes
350 |       field_defn
351 |       enum_defn
352 |       mask_defn
353 |       alias
354 |       accumulator
355 |       mode_pointer
356 |       allones
357 |       allzeros
358 |       none
359 |       sindex
360 ;
361
362 reg_address:
363         T_ADDRESS T_NUMBER
364         {
365                 cur_symbol->info.rinfo->address = $2;
366         }
367 ;
368
369 size:
370         T_SIZE T_NUMBER
371         {
372                 cur_symbol->info.rinfo->size = $2;
373                 if (scb_or_sram_symbol != NULL) {
374                         u_int max_addr;
375                         u_int sym_max_addr;
376
377                         max_addr = scb_or_sram_symbol->info.rinfo->address
378                                  + scb_or_sram_symbol->info.rinfo->size;
379                         sym_max_addr = cur_symbol->info.rinfo->address
380                                      + cur_symbol->info.rinfo->size;
381
382                         if (sym_max_addr > max_addr)
383                                 stop("SCB or SRAM space exhausted", EX_DATAERR);
384                 }
385         }
386 ;
387
388 access_mode:
389         T_ACCESS_MODE T_MODE
390         {
391                 cur_symbol->info.rinfo->mode = $2;
392         }
393 ;
394
395 modes:
396         T_MODES mode_list
397         {
398                 cur_symbol->info.rinfo->modes = $2;
399         }
400 ;
401
402 mode_list:
403         mode_value
404         {
405                 $$ = $1;
406         }
407 |       mode_list ',' mode_value
408         {
409                 $$ = $1 | $3;
410         }
411 ;
412
413 mode_value:
414         T_NUMBER
415         {
416                 if ($1 > 4) {
417                         stop("Valid register modes range between 0 and 4.",
418                              EX_DATAERR);
419                         /* NOTREACHED */
420                 }
421
422                 $$ = (0x1 << $1);
423         }
424 |       T_SYMBOL
425         {
426                 symbol_t *symbol;
427
428                 symbol = $1;
429                 if (symbol->type != CONST) {
430                         stop("Only \"const\" symbols allowed in "
431                              "mode definitions.", EX_DATAERR);
432                         /* NOTREACHED */
433                 }
434                 if (symbol->info.cinfo->value > 4) {
435                         stop("Valid register modes range between 0 and 4.",
436                              EX_DATAERR);
437                         /* NOTREACHED */
438                 }
439                 $$ = (0x1 << symbol->info.cinfo->value);
440         }
441 ;
442
443 field_defn:
444         T_FIELD
445                 {
446                         field_symbol = NULL;
447                         enum_next_value = 0;
448                         enum_increment = 1;
449                 }
450         '{' enum_entry_list '}'
451 |       T_FIELD T_SYMBOL expression
452                 {
453                         process_field(FIELD, $2, $3.value);
454                         field_symbol = $2;
455                         enum_next_value = 0;
456                         enum_increment = 0x01 << (ffs($3.value) - 1);
457                 }
458         '{' enum_entry_list '}'
459 |       T_FIELD T_SYMBOL expression
460         {
461                 process_field(FIELD, $2, $3.value);
462         }
463 ;
464
465 enum_defn:
466         T_ENUM
467                 {
468                         field_symbol = NULL;
469                         enum_next_value = 0;
470                         enum_increment = 1;
471                 }
472         '{' enum_entry_list '}'
473 |       T_ENUM T_SYMBOL expression
474                 {
475                         process_field(ENUM, $2, $3.value);
476                         field_symbol = $2;
477                         enum_next_value = 0;
478                         enum_increment = 0x01 << (ffs($3.value) - 1);
479                 }
480         '{' enum_entry_list '}'
481 ;
482
483 enum_entry_list:
484         enum_entry
485 |       enum_entry_list ',' enum_entry
486 ;
487
488 enum_entry:
489         T_SYMBOL
490         {
491                 process_field(ENUM_ENTRY, $1, enum_next_value);
492                 enum_next_value += enum_increment;
493         }
494 |       T_SYMBOL expression
495         {
496                 process_field(ENUM_ENTRY, $1, $2.value);
497                 enum_next_value = $2.value + enum_increment;
498         }
499 ;
500
501 mask_defn:
502         T_MASK T_SYMBOL expression
503         {
504                 process_field(MASK, $2, $3.value);
505         }
506 ;
507
508 alias:
509         T_ALIAS T_SYMBOL
510         {
511                 if ($2->type != UNINITIALIZED) {
512                         stop("Re-definition of register alias",
513                              EX_DATAERR);
514                         /* NOTREACHED */
515                 }
516                 $2->type = ALIAS;
517                 initialize_symbol($2);
518                 $2->info.ainfo->parent = cur_symbol;
519         }
520 ;
521
522 accumulator:
523         T_ACCUM
524         {
525                 if (accumulator.symbol != NULL) {
526                         stop("Only one accumulator definition allowed",
527                              EX_DATAERR);
528                         /* NOTREACHED */
529                 }
530                 accumulator.symbol = cur_symbol;
531         }
532 ;
533
534 mode_pointer:
535         T_MODE_PTR
536         {
537                 if (mode_ptr.symbol != NULL) {
538                         stop("Only one mode pointer definition allowed",
539                              EX_DATAERR);
540                         /* NOTREACHED */
541                 }
542                 mode_ptr.symbol = cur_symbol;
543         }
544 ;
545
546 allones:
547         T_ALLONES
548         {
549                 if (allones.symbol != NULL) {
550                         stop("Only one definition of allones allowed",
551                              EX_DATAERR);
552                         /* NOTREACHED */
553                 }
554                 allones.symbol = cur_symbol;
555         }
556 ;
557
558 allzeros:
559         T_ALLZEROS
560         {
561                 if (allzeros.symbol != NULL) {
562                         stop("Only one definition of allzeros allowed",
563                              EX_DATAERR);
564                         /* NOTREACHED */
565                 }
566                 allzeros.symbol = cur_symbol;
567         }
568 ;
569
570 none:
571         T_NONE
572         {
573                 if (none.symbol != NULL) {
574                         stop("Only one definition of none allowed",
575                              EX_DATAERR);
576                         /* NOTREACHED */
577                 }
578                 none.symbol = cur_symbol;
579         }
580 ;
581
582 sindex:
583         T_SINDEX
584         {
585                 if (sindex.symbol != NULL) {
586                         stop("Only one definition of sindex allowed",
587                              EX_DATAERR);
588                         /* NOTREACHED */
589                 }
590                 sindex.symbol = cur_symbol;
591         }
592 ;
593
594 expression:
595         expression '|' expression
596         {
597                  $$.value = $1.value | $3.value;
598                  symlist_merge(&$$.referenced_syms,
599                                &$1.referenced_syms,
600                                &$3.referenced_syms);
601         }
602 |       expression '&' expression
603         {
604                 $$.value = $1.value & $3.value;
605                 symlist_merge(&$$.referenced_syms,
606                                &$1.referenced_syms,
607                                &$3.referenced_syms);
608         }
609 |       expression '+' expression
610         {
611                 $$.value = $1.value + $3.value;
612                 symlist_merge(&$$.referenced_syms,
613                                &$1.referenced_syms,
614                                &$3.referenced_syms);
615         }
616 |       expression '-' expression
617         {
618                 $$.value = $1.value - $3.value;
619                 symlist_merge(&($$.referenced_syms),
620                                &($1.referenced_syms),
621                                &($3.referenced_syms));
622         }
623 |       expression '*' expression
624         {
625                 $$.value = $1.value * $3.value;
626                 symlist_merge(&($$.referenced_syms),
627                                &($1.referenced_syms),
628                                &($3.referenced_syms));
629         }
630 |       expression '/' expression
631         {
632                 $$.value = $1.value / $3.value;
633                 symlist_merge(&($$.referenced_syms),
634                                &($1.referenced_syms),
635                                &($3.referenced_syms));
636         }
637 |       expression T_EXPR_LSHIFT expression
638         {
639                 $$.value = $1.value << $3.value;
640                 symlist_merge(&$$.referenced_syms,
641                                &$1.referenced_syms,
642                                &$3.referenced_syms);
643         }
644 |       expression T_EXPR_RSHIFT expression
645         {
646                 $$.value = $1.value >> $3.value;
647                 symlist_merge(&$$.referenced_syms,
648                                &$1.referenced_syms,
649                                &$3.referenced_syms);
650         }
651 |       '(' expression ')'
652         {
653                 $$ = $2;
654         }
655 |       '~' expression
656         {
657                 $$ = $2;
658                 $$.value = (~$$.value) & 0xFF;
659         }
660 |       '-' expression %prec UMINUS
661         {
662                 $$ = $2;
663                 $$.value = -$$.value;
664         }
665 |       T_NUMBER
666         {
667                 $$.value = $1;
668                 SLIST_INIT(&$$.referenced_syms);
669         }
670 |       T_SYMBOL
671         {
672                 symbol_t *symbol;
673
674                 symbol = $1;
675                 switch (symbol->type) {
676                 case ALIAS:
677                         symbol = $1->info.ainfo->parent;
678                 case REGISTER:
679                 case SCBLOC:
680                 case SRAMLOC:
681                         $$.value = symbol->info.rinfo->address;
682                         break;
683                 case MASK:
684                 case FIELD:
685                 case ENUM:
686                 case ENUM_ENTRY:
687                         $$.value = symbol->info.finfo->value;
688                         break;
689                 case DOWNLOAD_CONST:
690                 case CONST:
691                         $$.value = symbol->info.cinfo->value;
692                         break;
693                 case UNINITIALIZED:
694                 default:
695                 {
696                         snprintf(errbuf, sizeof(errbuf),
697                                  "Undefined symbol %s referenced",
698                                  symbol->name);
699                         stop(errbuf, EX_DATAERR);
700                         /* NOTREACHED */
701                         break;
702                 }
703                 }
704                 SLIST_INIT(&$$.referenced_syms);
705                 symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD);
706         }
707 ;
708
709 constant:
710         T_CONST T_SYMBOL expression 
711         {
712                 if ($2->type != UNINITIALIZED) {
713                         stop("Re-definition of symbol as a constant",
714                              EX_DATAERR);
715                         /* NOTREACHED */
716                 }
717                 $2->type = CONST;
718                 initialize_symbol($2);
719                 $2->info.cinfo->value = $3.value;
720         }
721 |       T_CONST T_SYMBOL T_DOWNLOAD
722         {
723                 if ($1) {
724                         stop("Invalid downloaded constant declaration",
725                              EX_DATAERR);
726                         /* NOTREACHED */
727                 }
728                 if ($2->type != UNINITIALIZED) {
729                         stop("Re-definition of symbol as a downloaded constant",
730                              EX_DATAERR);
731                         /* NOTREACHED */
732                 }
733                 $2->type = DOWNLOAD_CONST;
734                 initialize_symbol($2);
735                 $2->info.cinfo->value = download_constant_count++;
736         }
737 ;
738
739 macrodefn_prologue:
740         T_DEFINE T_SYMBOL
741         {
742                 if ($2->type != UNINITIALIZED) {
743                         stop("Re-definition of symbol as a macro",
744                              EX_DATAERR);
745                         /* NOTREACHED */
746                 }
747                 cur_symbol = $2;
748                 cur_symbol->type = MACRO;
749                 initialize_symbol(cur_symbol);
750         }
751 ;
752
753 macrodefn:
754         macrodefn_prologue T_MACROBODY
755         {
756                 add_macro_body($2);
757         }
758 |       macrodefn_prologue '(' macro_arglist ')' T_MACROBODY
759         {
760                 add_macro_body($5);
761                 cur_symbol->info.macroinfo->narg = $3;
762         }
763 ;
764
765 macro_arglist:
766         {
767                 /* Macros can take no arguments */
768                 $$ = 0;
769         }
770 |       T_ARG
771         {
772                 $$ = 1;
773                 add_macro_arg($1, 0);
774         }
775 |       macro_arglist ',' T_ARG
776         {
777                 if ($1 == 0) {
778                         stop("Comma without preceding argument in arg list",
779                              EX_DATAERR);
780                         /* NOTREACHED */
781                 }
782                 $$ = $1 + 1;
783                 add_macro_arg($3, $1);
784         }
785 ;
786
787 scratch_ram:
788         T_SRAM '{'
789                 {
790                         snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME,
791                                  num_srams);
792                         cur_symbol = symtable_get(SRAM_SYMNAME);
793                         cur_symtype = SRAMLOC;
794                         cur_symbol->type = SRAMLOC;
795                         initialize_symbol(cur_symbol);
796                 }
797                 reg_address
798                 {
799                         sram_or_scb_offset = cur_symbol->info.rinfo->address;
800                 }
801                 size
802                 {
803                         scb_or_sram_symbol = cur_symbol;
804                 }
805                 scb_or_sram_attributes
806         '}'
807                 {
808                         cur_symbol = NULL;
809                         scb_or_sram_symbol = NULL;
810                 }
811 ;
812
813 scb:
814         T_SCB '{'
815                 {
816                         cur_symbol = symtable_get(SCB_SYMNAME);
817                         cur_symtype = SCBLOC;
818                         if (cur_symbol->type != UNINITIALIZED) {
819                                 stop("Only one SRAM definition allowed",
820                                      EX_SOFTWARE);
821                                 /* NOTREACHED */
822                         }
823                         cur_symbol->type = SCBLOC;
824                         initialize_symbol(cur_symbol);
825                         /* 64 bytes of SCB space */
826                         cur_symbol->info.rinfo->size = 64;
827                 }
828                 reg_address
829                 {
830                         sram_or_scb_offset = cur_symbol->info.rinfo->address;
831                 }
832                 size
833                 {
834                         scb_or_sram_symbol = cur_symbol;
835                 }
836                 scb_or_sram_attributes
837         '}'
838                 {
839                         cur_symbol = NULL;
840                         scb_or_sram_symbol = NULL;
841                 }
842 ;
843
844 scb_or_sram_attributes:
845         /* NULL definition is okay */
846 |       modes
847 |       scb_or_sram_reg_list
848 |       modes scb_or_sram_reg_list
849 ;
850
851 scb_or_sram_reg_list:
852         reg_definition
853 |       scb_or_sram_reg_list reg_definition
854 ;
855
856 reg_symbol:
857         T_SYMBOL
858         {
859                 process_register(&$1);
860                 $$.symbol = $1;
861                 $$.offset = 0;
862         }
863 |       T_SYMBOL '[' T_SYMBOL ']'
864         {
865                 process_register(&$1);
866                 if ($3->type != CONST) {
867                         stop("register offset must be a constant", EX_DATAERR);
868                         /* NOTREACHED */
869                 }
870                 if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) {
871                         stop("Accessing offset beyond range of register",
872                              EX_DATAERR);
873                         /* NOTREACHED */
874                 }
875                 $$.symbol = $1;
876                 $$.offset = $3->info.cinfo->value;
877         }
878 |       T_SYMBOL '[' T_NUMBER ']'
879         {
880                 process_register(&$1);
881                 if (($3 + 1) > $1->info.rinfo->size) {
882                         stop("Accessing offset beyond range of register",
883                              EX_DATAERR);
884                         /* NOTREACHED */
885                 }
886                 $$.symbol = $1;
887                 $$.offset = $3;
888         }
889 |       T_A
890         {
891                 if (accumulator.symbol == NULL) {
892                         stop("No accumulator has been defined", EX_DATAERR);
893                         /* NOTREACHED */
894                 }
895                 $$.symbol = accumulator.symbol;
896                 $$.offset = 0;
897         }
898 ;
899
900 destination:
901         reg_symbol
902         {
903                 test_writable_symbol($1.symbol);
904                 $$ = $1;
905         }
906 ;
907
908 immediate:
909         expression
910         { $$ = $1; }
911 ;
912
913 immediate_or_a:
914         expression
915         {
916                 if ($1.value == 0 && is_download_const(&$1) == 0) {
917                         snprintf(errbuf, sizeof(errbuf),
918                                  "\nExpression evaluates to 0 and thus "
919                                  "references the accumulator.\n "
920                                  "If this is the desired effect, use 'A' "
921                                  "instead.\n");
922                         stop(errbuf, EX_DATAERR);
923                 }
924                 $$ = $1;
925         }
926 |       T_A
927         {
928                 SLIST_INIT(&$$.referenced_syms);
929                 symlist_add(&$$.referenced_syms, accumulator.symbol,
930                             SYMLIST_INSERT_HEAD);
931                 $$.value = 0;
932         }
933 ;
934
935 source:
936         reg_symbol
937         {
938                 test_readable_symbol($1.symbol);
939                 $$ = $1;
940         }
941 ;
942
943 opt_source:
944         {
945                 $$.symbol = NULL;
946                 $$.offset = 0;
947         }
948 |       ',' source
949         { $$ = $2; }
950 ;
951
952 ret:
953         { $$ = 0; }
954 |       T_RET
955         { $$ = 1; }
956 ;
957
958 set_src_mode:
959         T_SET_SRC_MODE T_NUMBER ';'
960         {
961                 src_mode = $2;
962         }
963 ;
964
965 set_dst_mode:
966         T_SET_DST_MODE T_NUMBER ';'
967         {
968                 dst_mode = $2;
969         }
970 ;
971
972 critical_section_start:
973         T_BEGIN_CS ';'
974         {
975                 critical_section_t *cs;
976
977                 if (in_critical_section != FALSE) {
978                         stop("Critical Section within Critical Section",
979                              EX_DATAERR);
980                         /* NOTREACHED */
981                 }
982                 cs = cs_alloc();
983                 cs->begin_addr = instruction_ptr;
984                 in_critical_section = TRUE;
985         }
986 ;
987
988 critical_section_end:
989         T_END_CS ';'
990         {
991                 critical_section_t *cs;
992
993                 if (in_critical_section == FALSE) {
994                         stop("Unballanced 'end_cs'", EX_DATAERR);
995                         /* NOTREACHED */
996                 }
997                 cs = TAILQ_LAST(&cs_tailq, cs_tailq);
998                 cs->end_addr = instruction_ptr;
999                 in_critical_section = FALSE;
1000         }
1001 ;
1002
1003 export:
1004         { $$ = 0; }
1005 |       T_EXPORT
1006         { $$ = 1; }
1007 ;
1008
1009 label:
1010         export T_SYMBOL ':'
1011         {
1012                 if ($2->type != UNINITIALIZED) {
1013                         stop("Program label multiply defined", EX_DATAERR);
1014                         /* NOTREACHED */
1015                 }
1016                 $2->type = LABEL;
1017                 initialize_symbol($2);
1018                 $2->info.linfo->address = instruction_ptr;
1019                 $2->info.linfo->exported = $1;
1020         }
1021 ;
1022
1023 address:
1024         T_SYMBOL
1025         {
1026                 $$.symbol = $1;
1027                 $$.offset = 0;
1028         }
1029 |       T_SYMBOL '+' T_NUMBER
1030         {
1031                 $$.symbol = $1;
1032                 $$.offset = $3;
1033         }
1034 |       T_SYMBOL '-' T_NUMBER
1035         {
1036                 $$.symbol = $1;
1037                 $$.offset = -$3;
1038         }
1039 |       '.'
1040         {
1041                 $$.symbol = NULL;
1042                 $$.offset = 0;
1043         }
1044 |       '.' '+' T_NUMBER
1045         {
1046                 $$.symbol = NULL;
1047                 $$.offset = $3;
1048         }
1049 |       '.' '-' T_NUMBER
1050         {
1051                 $$.symbol = NULL;
1052                 $$.offset = -$3;
1053         }
1054 ;
1055
1056 conditional:
1057         T_IF T_CEXPR '{'
1058         {
1059                 scope_t *new_scope;
1060
1061                 add_conditional($2);
1062                 new_scope = scope_alloc();
1063                 new_scope->type = SCOPE_IF;
1064                 new_scope->begin_addr = instruction_ptr;
1065                 new_scope->func_num = $2->info.condinfo->func_num;
1066         }
1067 |       T_ELSE T_IF T_CEXPR '{'
1068         {
1069                 scope_t *new_scope;
1070                 scope_t *scope_context;
1071                 scope_t *last_scope;
1072
1073                 /*
1074                  * Ensure that the previous scope is either an
1075                  * if or and else if.
1076                  */
1077                 scope_context = SLIST_FIRST(&scope_stack);
1078                 last_scope = TAILQ_LAST(&scope_context->inner_scope,
1079                                         scope_tailq);
1080                 if (last_scope == NULL
1081                  || last_scope->type == T_ELSE) {
1082
1083                         stop("'else if' without leading 'if'", EX_DATAERR);
1084                         /* NOTREACHED */
1085                 }
1086                 add_conditional($3);
1087                 new_scope = scope_alloc();
1088                 new_scope->type = SCOPE_ELSE_IF;
1089                 new_scope->begin_addr = instruction_ptr;
1090                 new_scope->func_num = $3->info.condinfo->func_num;
1091         }
1092 |       T_ELSE '{'
1093         {
1094                 scope_t *new_scope;
1095                 scope_t *scope_context;
1096                 scope_t *last_scope;
1097
1098                 /*
1099                  * Ensure that the previous scope is either an
1100                  * if or and else if.
1101                  */
1102                 scope_context = SLIST_FIRST(&scope_stack);
1103                 last_scope = TAILQ_LAST(&scope_context->inner_scope,
1104                                         scope_tailq);
1105                 if (last_scope == NULL
1106                  || last_scope->type == SCOPE_ELSE) {
1107
1108                         stop("'else' without leading 'if'", EX_DATAERR);
1109                         /* NOTREACHED */
1110                 }
1111                 new_scope = scope_alloc();
1112                 new_scope->type = SCOPE_ELSE;
1113                 new_scope->begin_addr = instruction_ptr;
1114         }
1115 ;
1116
1117 conditional:
1118         '}'
1119         {
1120                 scope_t *scope_context;
1121
1122                 scope_context = SLIST_FIRST(&scope_stack);
1123                 if (scope_context->type == SCOPE_ROOT) {
1124                         stop("Unexpected '}' encountered", EX_DATAERR);
1125                         /* NOTREACHED */
1126                 }
1127
1128                 scope_context->end_addr = instruction_ptr;
1129
1130                 /* Pop the scope */
1131                 SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
1132
1133                 process_scope(scope_context);
1134
1135                 if (SLIST_FIRST(&scope_stack) == NULL) {
1136                         stop("Unexpected '}' encountered", EX_DATAERR);
1137                         /* NOTREACHED */
1138                 }
1139         }
1140 ;
1141
1142 f1_opcode:
1143         T_AND { $$ = AIC_OP_AND; }
1144 |       T_XOR { $$ = AIC_OP_XOR; }
1145 |       T_ADD { $$ = AIC_OP_ADD; }
1146 |       T_ADC { $$ = AIC_OP_ADC; }
1147 ;
1148
1149 code:
1150         f1_opcode destination ',' immediate_or_a opt_source ret ';'
1151         {
1152                 format_1_instr($1, &$2, &$4, &$5, $6);
1153         }
1154 ;
1155
1156 code:
1157         T_OR reg_symbol ',' immediate_or_a opt_source ret ';'
1158         {
1159                 format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6);
1160         }
1161 ;
1162
1163 code:
1164         T_INC destination opt_source ret ';'
1165         {
1166                 expression_t immed;
1167
1168                 make_expression(&immed, 1);
1169                 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
1170         }
1171 ;
1172
1173 code:
1174         T_DEC destination opt_source ret ';'
1175         {
1176                 expression_t immed;
1177
1178                 make_expression(&immed, -1);
1179                 format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
1180         }
1181 ;
1182
1183 code:
1184         T_CLC ret ';'
1185         {
1186                 expression_t immed;
1187
1188                 make_expression(&immed, -1);
1189                 format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2);
1190         }
1191 |       T_CLC T_MVI destination ',' immediate_or_a ret ';'
1192         {
1193                 format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6);
1194         }
1195 ;
1196
1197 code:
1198         T_STC ret ';'
1199         {
1200                 expression_t immed;
1201
1202                 make_expression(&immed, 1);
1203                 format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2);
1204         }
1205 |       T_STC destination ret ';'
1206         {
1207                 expression_t immed;
1208
1209                 make_expression(&immed, 1);
1210                 format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3);
1211         }
1212 ;
1213
1214 code:
1215         T_BMOV destination ',' source ',' immediate ret ';'
1216         {
1217                 format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
1218         }
1219 ;
1220
1221 code:
1222         T_MOV destination ',' source ret ';'
1223         {
1224                 expression_t immed;
1225
1226                 make_expression(&immed, 1);
1227                 format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5);
1228         }
1229 ;
1230
1231 code:
1232         T_MVI destination ',' immediate ret ';'
1233         {
1234                 if ($4.value == 0
1235                  && is_download_const(&$4) == 0) {
1236                         expression_t immed;
1237
1238                         /*
1239                          * Allow move immediates of 0 so that macros,
1240                          * that can't know the immediate's value and
1241                          * otherwise compensate, still work.
1242                          */
1243                         make_expression(&immed, 1);
1244                         format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5);
1245                 } else {
1246                         format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
1247                 }
1248         }
1249 ;
1250
1251 code:
1252         T_NOT destination opt_source ret ';'
1253         {
1254                 expression_t immed;
1255
1256                 make_expression(&immed, 0xff);
1257                 format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4);
1258         }
1259 ;
1260
1261 code:
1262         T_CLR destination ret ';'
1263         {
1264                 expression_t immed;
1265
1266                 make_expression(&immed, 0xff);
1267                 format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3);
1268         }
1269 ;
1270
1271 code:
1272         T_NOP ret ';'
1273         {
1274                 expression_t immed;
1275
1276                 make_expression(&immed, 0xff);
1277                 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2);
1278         }
1279 ;
1280
1281 code:
1282         T_RET ';'
1283         {
1284                 expression_t immed;
1285
1286                 make_expression(&immed, 0xff);
1287                 format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE);
1288         }
1289 ;
1290
1291         /*
1292          * This grammer differs from the one in the aic7xxx
1293          * reference manual since the grammer listed there is
1294          * ambiguous and causes a shift/reduce conflict.
1295          * It also seems more logical as the "immediate"
1296          * argument is listed as the second arg like the
1297          * other formats.
1298          */
1299
1300 f2_opcode:
1301         T_SHL { $$ = AIC_OP_SHL; }
1302 |       T_SHR { $$ = AIC_OP_SHR; }
1303 |       T_ROL { $$ = AIC_OP_ROL; }
1304 |       T_ROR { $$ = AIC_OP_ROR; }
1305 ;
1306
1307 code:
1308         f2_opcode destination ',' expression opt_source ret ';'
1309         {
1310                 format_2_instr($1, &$2, &$4, &$5, $6);
1311         }
1312 ;
1313
1314 jmp_jc_jnc_call:
1315         T_JMP   { $$ = AIC_OP_JMP; }
1316 |       T_JC    { $$ = AIC_OP_JC; }
1317 |       T_JNC   { $$ = AIC_OP_JNC; }
1318 |       T_CALL  { $$ = AIC_OP_CALL; }
1319 ;
1320
1321 jz_jnz:
1322         T_JZ    { $$ = AIC_OP_JZ; }
1323 |       T_JNZ   { $$ = AIC_OP_JNZ; }
1324 ;
1325
1326 je_jne:
1327         T_JE    { $$ = AIC_OP_JE; }
1328 |       T_JNE   { $$ = AIC_OP_JNE; }
1329 ;
1330
1331 code:
1332         jmp_jc_jnc_call address ';'
1333         {
1334                 expression_t immed;
1335
1336                 make_expression(&immed, 0);
1337                 format_3_instr($1, &sindex, &immed, &$2);
1338         }
1339 ;
1340
1341 code:
1342         T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
1343         {
1344                 format_3_instr($5, &$2, &$4, &$6);
1345         }
1346 ;
1347
1348 code:
1349         T_TEST source ',' immediate_or_a jz_jnz address ';'
1350         {
1351                 format_3_instr($5, &$2, &$4, &$6);
1352         }
1353 ;
1354
1355 code:
1356         T_CMP source ',' immediate_or_a je_jne address ';'
1357         {
1358                 format_3_instr($5, &$2, &$4, &$6);
1359         }
1360 ;
1361
1362 code:
1363         T_MOV source jmp_jc_jnc_call address ';'
1364         {
1365                 expression_t immed;
1366
1367                 make_expression(&immed, 0);
1368                 format_3_instr($3, &$2, &immed, &$4);
1369         }
1370 ;
1371
1372 code:
1373         T_MVI immediate jmp_jc_jnc_call address ';'
1374         {
1375                 format_3_instr($3, &allzeros, &$2, &$4);
1376         }
1377 ;
1378
1379 %%
1380
1381 static void
1382 process_field(int field_type, symbol_t *sym, int value)
1383 {
1384         /*
1385          * Add the current register to its
1386          * symbol list, if it already exists,
1387          * warn if we are setting it to a
1388          * different value, or in the bit to
1389          * the "allowed bits" of this register.
1390          */
1391         if (sym->type == UNINITIALIZED) {
1392                 sym->type = field_type;
1393                 initialize_symbol(sym);
1394                 sym->info.finfo->value = value;
1395                 if (field_type != ENUM_ENTRY) {
1396                         if (field_type != MASK && value == 0) {
1397                                 stop("Empty Field, or Enum", EX_DATAERR);
1398                                 /* NOTREACHED */
1399                         }
1400                         sym->info.finfo->value = value;
1401                         sym->info.finfo->mask = value;
1402                 } else if (field_symbol != NULL) {
1403                         sym->info.finfo->mask = field_symbol->info.finfo->value;
1404                 } else {
1405                         sym->info.finfo->mask = 0xFF;
1406                 }
1407         } else if (sym->type != field_type) {
1408                 stop("Field definition mirrors a definition of the same "
1409                      " name, but a different type", EX_DATAERR);
1410                 /* NOTREACHED */
1411         } else if (value != sym->info.finfo->value) {
1412                 stop("Field redefined with a conflicting value", EX_DATAERR);
1413                 /* NOTREACHED */
1414         }
1415         /* Fail if this symbol is already listed */
1416         if (symlist_search(&(sym->info.finfo->symrefs),
1417                            cur_symbol->name) != NULL) {
1418                 stop("Field defined multiple times for register", EX_DATAERR);
1419                 /* NOTREACHED */
1420         }
1421         symlist_add(&(sym->info.finfo->symrefs), cur_symbol,
1422                     SYMLIST_INSERT_HEAD);
1423         cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask;
1424         cur_symbol->info.rinfo->typecheck_masks = TRUE;
1425         symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT);
1426 }
1427
1428 static void
1429 initialize_symbol(symbol_t *symbol)
1430 {
1431         switch (symbol->type) {
1432         case UNINITIALIZED:
1433                 stop("Call to initialize_symbol with type field unset",
1434                      EX_SOFTWARE);
1435                 /* NOTREACHED */
1436                 break;
1437         case REGISTER:
1438         case SRAMLOC:
1439         case SCBLOC:
1440                 symbol->info.rinfo =
1441                     (struct reg_info *)malloc(sizeof(struct reg_info));
1442                 if (symbol->info.rinfo == NULL) {
1443                         stop("Can't create register info", EX_SOFTWARE);
1444                         /* NOTREACHED */
1445                 }
1446                 memset(symbol->info.rinfo, 0,
1447                        sizeof(struct reg_info));
1448                 SLIST_INIT(&(symbol->info.rinfo->fields));
1449                 /*
1450                  * Default to allowing access in all register modes
1451                  * or to the mode specified by the SCB or SRAM space
1452                  * we are in.
1453                  */
1454                 if (scb_or_sram_symbol != NULL)
1455                         symbol->info.rinfo->modes =
1456                             scb_or_sram_symbol->info.rinfo->modes;
1457                 else
1458                         symbol->info.rinfo->modes = ~0;
1459                 break;
1460         case ALIAS:
1461                 symbol->info.ainfo =
1462                     (struct alias_info *)malloc(sizeof(struct alias_info));
1463                 if (symbol->info.ainfo == NULL) {
1464                         stop("Can't create alias info", EX_SOFTWARE);
1465                         /* NOTREACHED */
1466                 }
1467                 memset(symbol->info.ainfo, 0,
1468                        sizeof(struct alias_info));
1469                 break;
1470         case MASK:
1471         case FIELD:
1472         case ENUM:
1473         case ENUM_ENTRY:
1474                 symbol->info.finfo =
1475                     (struct field_info *)malloc(sizeof(struct field_info));
1476                 if (symbol->info.finfo == NULL) {
1477                         stop("Can't create field info", EX_SOFTWARE);
1478                         /* NOTREACHED */
1479                 }
1480                 memset(symbol->info.finfo, 0, sizeof(struct field_info));
1481                 SLIST_INIT(&(symbol->info.finfo->symrefs));
1482                 break;
1483         case CONST:
1484         case DOWNLOAD_CONST:
1485                 symbol->info.cinfo =
1486                     (struct const_info *)malloc(sizeof(struct const_info));
1487                 if (symbol->info.cinfo == NULL) {
1488                         stop("Can't create alias info", EX_SOFTWARE);
1489                         /* NOTREACHED */
1490                 }
1491                 memset(symbol->info.cinfo, 0,
1492                        sizeof(struct const_info));
1493                 break;
1494         case LABEL:
1495                 symbol->info.linfo =
1496                     (struct label_info *)malloc(sizeof(struct label_info));
1497                 if (symbol->info.linfo == NULL) {
1498                         stop("Can't create label info", EX_SOFTWARE);
1499                         /* NOTREACHED */
1500                 }
1501                 memset(symbol->info.linfo, 0,
1502                        sizeof(struct label_info));
1503                 break;
1504         case CONDITIONAL:
1505                 symbol->info.condinfo =
1506                     (struct cond_info *)malloc(sizeof(struct cond_info));
1507                 if (symbol->info.condinfo == NULL) {
1508                         stop("Can't create conditional info", EX_SOFTWARE);
1509                         /* NOTREACHED */
1510                 }
1511                 memset(symbol->info.condinfo, 0,
1512                        sizeof(struct cond_info));
1513                 break;
1514         case MACRO:
1515                 symbol->info.macroinfo = 
1516                     (struct macro_info *)malloc(sizeof(struct macro_info));
1517                 if (symbol->info.macroinfo == NULL) {
1518                         stop("Can't create macro info", EX_SOFTWARE);
1519                         /* NOTREACHED */
1520                 }
1521                 memset(symbol->info.macroinfo, 0,
1522                        sizeof(struct macro_info));
1523                 STAILQ_INIT(&symbol->info.macroinfo->args);
1524                 break;
1525         default:
1526                 stop("Call to initialize_symbol with invalid symbol type",
1527                      EX_SOFTWARE);
1528                 /* NOTREACHED */
1529                 break;
1530         }
1531 }
1532
1533 static void
1534 add_macro_arg(const char *argtext, int argnum)
1535 {
1536         struct macro_arg *marg;
1537         int i;
1538         int retval;
1539                 
1540
1541         if (cur_symbol == NULL || cur_symbol->type != MACRO) {
1542                 stop("Invalid current symbol for adding macro arg",
1543                      EX_SOFTWARE);
1544                 /* NOTREACHED */
1545         }
1546
1547         marg = (struct macro_arg *)malloc(sizeof(*marg));
1548         if (marg == NULL) {
1549                 stop("Can't create macro_arg structure", EX_SOFTWARE);
1550                 /* NOTREACHED */
1551         }
1552         marg->replacement_text = NULL;
1553         retval = snprintf(regex_pattern, sizeof(regex_pattern),
1554                           "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)",
1555                           argtext);
1556         if (retval >= sizeof(regex_pattern)) {
1557                 stop("Regex text buffer too small for arg",
1558                      EX_SOFTWARE);
1559                 /* NOTREACHED */
1560         }
1561         retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED);
1562         if (retval != 0) {
1563                 stop("Regex compilation failed", EX_SOFTWARE);
1564                 /* NOTREACHED */
1565         }
1566         STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links);
1567 }
1568
1569 static void
1570 add_macro_body(const char *bodytext)
1571 {
1572         if (cur_symbol == NULL || cur_symbol->type != MACRO) {
1573                 stop("Invalid current symbol for adding macro arg",
1574                      EX_SOFTWARE);
1575                 /* NOTREACHED */
1576         }
1577         cur_symbol->info.macroinfo->body = strdup(bodytext);
1578         if (cur_symbol->info.macroinfo->body == NULL) {
1579                 stop("Can't duplicate macro body text", EX_SOFTWARE);
1580                 /* NOTREACHED */
1581         }
1582 }
1583
1584 static void
1585 process_register(symbol_t **p_symbol)
1586 {
1587         symbol_t *symbol = *p_symbol;
1588
1589         if (symbol->type == UNINITIALIZED) {
1590                 snprintf(errbuf, sizeof(errbuf), "Undefined register %s",
1591                          symbol->name);
1592                 stop(errbuf, EX_DATAERR);
1593                 /* NOTREACHED */
1594         } else if (symbol->type == ALIAS) {
1595                 *p_symbol = symbol->info.ainfo->parent;
1596         } else if ((symbol->type != REGISTER)
1597                 && (symbol->type != SCBLOC)
1598                 && (symbol->type != SRAMLOC)) {
1599                 snprintf(errbuf, sizeof(errbuf),
1600                          "Specified symbol %s is not a register",
1601                          symbol->name);
1602                 stop(errbuf, EX_DATAERR);
1603         }
1604 }
1605
1606 static void
1607 format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
1608                symbol_ref_t *src, int ret)
1609 {
1610         struct instruction *instr;
1611         struct ins_format1 *f1_instr;
1612
1613         if (src->symbol == NULL)
1614                 src = dest;
1615
1616         /* Test register permissions */
1617         test_writable_symbol(dest->symbol);
1618         test_readable_symbol(src->symbol);
1619
1620         /* Ensure that immediate makes sense for this destination */
1621         type_check(dest->symbol, immed, opcode);
1622
1623         /* Allocate sequencer space for the instruction and fill it out */
1624         instr = seq_alloc();
1625         f1_instr = &instr->format.format1;
1626         f1_instr->ret = ret ? 1 : 0;
1627         f1_instr->opcode = opcode;
1628         f1_instr->destination = dest->symbol->info.rinfo->address
1629                               + dest->offset;
1630         f1_instr->source = src->symbol->info.rinfo->address
1631                          + src->offset;
1632         f1_instr->immediate = immed->value;
1633
1634         if (is_download_const(immed))
1635                 f1_instr->parity = 1;
1636         else if (dest->symbol == mode_ptr.symbol) {
1637                 u_int src_value;
1638                 u_int dst_value;
1639
1640                 /*
1641                  * Attempt to update mode information if
1642                  * we are operating on the mode register.
1643                  */
1644                 if (src->symbol == allones.symbol)
1645                         src_value = 0xFF;
1646                 else if (src->symbol == allzeros.symbol)
1647                         src_value = 0;
1648                 else if (src->symbol == mode_ptr.symbol)
1649                         src_value = (dst_mode << 4) | src_mode;
1650                 else
1651                         goto cant_update;
1652
1653                 switch (opcode) {
1654                 case AIC_OP_AND:
1655                         dst_value = src_value & immed->value;
1656                         break;
1657                 case AIC_OP_XOR:
1658                         dst_value = src_value ^ immed->value;
1659                         break;
1660                 case AIC_OP_ADD:
1661                         dst_value = (src_value + immed->value) & 0xFF;
1662                         break;
1663                 case AIC_OP_OR:
1664                         dst_value = src_value | immed->value;
1665                         break;
1666                 case AIC_OP_BMOV:
1667                         dst_value = src_value;
1668                         break;
1669                 default:
1670                         goto cant_update;
1671                 }
1672                 src_mode = dst_value & 0xF;
1673                 dst_mode = (dst_value >> 4) & 0xF;
1674         }
1675
1676 cant_update:
1677         symlist_free(&immed->referenced_syms);
1678         instruction_ptr++;
1679 }
1680
1681 static void
1682 format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places,
1683                symbol_ref_t *src, int ret)
1684 {
1685         struct instruction *instr;
1686         struct ins_format2 *f2_instr;
1687         uint8_t shift_control;
1688
1689         if (src->symbol == NULL)
1690                 src = dest;
1691
1692         /* Test register permissions */
1693         test_writable_symbol(dest->symbol);
1694         test_readable_symbol(src->symbol);
1695
1696         /* Allocate sequencer space for the instruction and fill it out */
1697         instr = seq_alloc();
1698         f2_instr = &instr->format.format2;
1699         f2_instr->ret = ret ? 1 : 0;
1700         f2_instr->opcode = AIC_OP_ROL;
1701         f2_instr->destination = dest->symbol->info.rinfo->address
1702                               + dest->offset;
1703         f2_instr->source = src->symbol->info.rinfo->address
1704                          + src->offset;
1705         if (places->value > 8 || places->value <= 0) {
1706                 stop("illegal shift value", EX_DATAERR);
1707                 /* NOTREACHED */
1708         }
1709         switch (opcode) {
1710         case AIC_OP_SHL:
1711                 if (places->value == 8)
1712                         shift_control = 0xf0;
1713                 else
1714                         shift_control = (places->value << 4) | places->value;
1715                 break;
1716         case AIC_OP_SHR:
1717                 if (places->value == 8) {
1718                         shift_control = 0xf8;
1719                 } else {
1720                         shift_control = (places->value << 4)
1721                                       | (8 - places->value)
1722                                       | 0x08;
1723                 }
1724                 break;
1725         case AIC_OP_ROL:
1726                 shift_control = places->value & 0x7;
1727                 break;
1728         case AIC_OP_ROR:
1729                 shift_control = (8 - places->value) | 0x08;
1730                 break;
1731         default:
1732                 shift_control = 0; /* Quiet Compiler */
1733                 stop("Invalid shift operation specified", EX_SOFTWARE);
1734                 /* NOTREACHED */
1735                 break;
1736         };
1737         f2_instr->shift_control = shift_control;
1738         symlist_free(&places->referenced_syms);
1739         instruction_ptr++;
1740 }
1741
1742 static void
1743 format_3_instr(int opcode, symbol_ref_t *src,
1744                expression_t *immed, symbol_ref_t *address)
1745 {
1746         struct instruction *instr;
1747         struct ins_format3 *f3_instr;
1748         int addr;
1749
1750         /* Test register permissions */
1751         test_readable_symbol(src->symbol);
1752
1753         /* Ensure that immediate makes sense for this source */
1754         type_check(src->symbol, immed, opcode);
1755
1756         /* Allocate sequencer space for the instruction and fill it out */
1757         instr = seq_alloc();
1758         f3_instr = &instr->format.format3;
1759         if (address->symbol == NULL) {
1760                 /* 'dot' referrence.  Use the current instruction pointer */
1761                 addr = instruction_ptr + address->offset;
1762         } else if (address->symbol->type == UNINITIALIZED) {
1763                 /* forward reference */
1764                 addr = address->offset;
1765                 instr->patch_label = address->symbol;
1766         } else
1767                 addr = address->symbol->info.linfo->address + address->offset;
1768         f3_instr->opcode = opcode;
1769         f3_instr->address = addr;
1770         f3_instr->source = src->symbol->info.rinfo->address
1771                          + src->offset;
1772         f3_instr->immediate = immed->value;
1773
1774         if (is_download_const(immed))
1775                 f3_instr->parity = 1;
1776
1777         symlist_free(&immed->referenced_syms);
1778         instruction_ptr++;
1779 }
1780
1781 static void
1782 test_readable_symbol(symbol_t *symbol)
1783 {
1784         
1785         if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
1786                 snprintf(errbuf, sizeof(errbuf),
1787                         "Register %s unavailable in source reg mode %d",
1788                         symbol->name, src_mode);
1789                 stop(errbuf, EX_DATAERR);
1790         }
1791
1792         if (symbol->info.rinfo->mode == WO) {
1793                 stop("Write Only register specified as source",
1794                      EX_DATAERR);
1795                 /* NOTREACHED */
1796         }
1797 }
1798
1799 static void
1800 test_writable_symbol(symbol_t *symbol)
1801 {
1802         
1803         if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
1804                 snprintf(errbuf, sizeof(errbuf),
1805                         "Register %s unavailable in destination reg mode %d",
1806                         symbol->name, dst_mode);
1807                 stop(errbuf, EX_DATAERR);
1808         }
1809
1810         if (symbol->info.rinfo->mode == RO) {
1811                 stop("Read Only register specified as destination",
1812                      EX_DATAERR);
1813                 /* NOTREACHED */
1814         }
1815 }
1816
1817 static void
1818 type_check(symbol_t *symbol, expression_t *expression, int opcode)
1819 {
1820         symbol_node_t *node;
1821         int and_op;
1822
1823         and_op = FALSE;
1824         if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
1825                 and_op = TRUE;
1826
1827         /*
1828          * Make sure that we aren't attempting to write something
1829          * that hasn't been defined.  If this is an and operation,
1830          * this is a mask, so "undefined" bits are okay.
1831          */
1832         if (and_op == FALSE
1833          && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
1834                 snprintf(errbuf, sizeof(errbuf),
1835                          "Invalid bit(s) 0x%x in immediate written to %s",
1836                          expression->value & ~symbol->info.rinfo->valid_bitmask,
1837                          symbol->name);
1838                 stop(errbuf, EX_DATAERR);
1839                 /* NOTREACHED */
1840         }
1841
1842         /*
1843          * Now make sure that all of the symbols referenced by the
1844          * expression are defined for this register.
1845          */
1846         if (symbol->info.rinfo->typecheck_masks != FALSE) {
1847                 for(node = expression->referenced_syms.slh_first;
1848                     node != NULL;
1849                     node = node->links.sle_next) {
1850                         if ((node->symbol->type == MASK
1851                           || node->symbol->type == FIELD
1852                           || node->symbol->type == ENUM
1853                           || node->symbol->type == ENUM_ENTRY)
1854                          && symlist_search(&node->symbol->info.finfo->symrefs,
1855                                            symbol->name) == NULL) {
1856                                 snprintf(errbuf, sizeof(errbuf),
1857                                          "Invalid field or mask %s "
1858                                          "for register %s",
1859                                          node->symbol->name, symbol->name);
1860                                 stop(errbuf, EX_DATAERR);
1861                                 /* NOTREACHED */
1862                         }
1863                 }
1864         }
1865 }
1866
1867 static void
1868 make_expression(expression_t *immed, int value)
1869 {
1870         SLIST_INIT(&immed->referenced_syms);
1871         immed->value = value & 0xff;
1872 }
1873
1874 static void
1875 add_conditional(symbol_t *symbol)
1876 {
1877         static int numfuncs;
1878
1879         if (numfuncs == 0) {
1880                 /* add a special conditional, "0" */
1881                 symbol_t *false_func;
1882
1883                 false_func = symtable_get("0");
1884                 if (false_func->type != UNINITIALIZED) {
1885                         stop("Conditional expression '0' "
1886                              "conflicts with a symbol", EX_DATAERR);
1887                         /* NOTREACHED */
1888                 }
1889                 false_func->type = CONDITIONAL;
1890                 initialize_symbol(false_func);
1891                 false_func->info.condinfo->func_num = numfuncs++;
1892                 symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
1893         }
1894
1895         /* This condition has occurred before */
1896         if (symbol->type == CONDITIONAL)
1897                 return;
1898
1899         if (symbol->type != UNINITIALIZED) {
1900                 stop("Conditional expression conflicts with a symbol",
1901                      EX_DATAERR);
1902                 /* NOTREACHED */
1903         }
1904
1905         symbol->type = CONDITIONAL;
1906         initialize_symbol(symbol);
1907         symbol->info.condinfo->func_num = numfuncs++;
1908         symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
1909 }
1910
1911 static void
1912 add_version(const char *verstring)
1913 {
1914         const char prefix[] = " * ";
1915         int newlen;
1916         int oldlen;
1917
1918         newlen = strlen(verstring) + strlen(prefix);
1919         oldlen = 0;
1920         if (versions != NULL)
1921                 oldlen = strlen(versions);
1922         versions = realloc(versions, newlen + oldlen + 2);
1923         if (versions == NULL)
1924                 stop("Can't allocate version string", EX_SOFTWARE);
1925         strcpy(&versions[oldlen], prefix);
1926         strcpy(&versions[oldlen + strlen(prefix)], verstring);
1927         versions[newlen + oldlen] = '\n';
1928         versions[newlen + oldlen + 1] = '\0';
1929 }
1930
1931 void
1932 yyerror(const char *string)
1933 {
1934         stop(string, EX_DATAERR);
1935 }
1936
1937 static int
1938 is_download_const(expression_t *immed)
1939 {
1940         if ((immed->referenced_syms.slh_first != NULL)
1941          && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST))
1942                 return (TRUE);
1943
1944         return (FALSE);
1945 }