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