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