Import Upstream version 1.3+dfsg
Thorsten Alteholz
6 years ago
0 | ####################################################### | |
1 | # | |
2 | # a56 - a DSP56001 assembler | |
3 | # | |
4 | # Written by Quinn C. Jensen | |
5 | # July 1990 | |
6 | # | |
7 | ####################################################### | |
8 | ||
9 | # environment definitions | |
10 | # uncomment the ones you like | |
11 | ||
12 | # generic unix | |
13 | CC = cc | |
14 | HOSTCC = cc | |
15 | YACC = yacc | |
16 | CCDEFS = -DLDEBUG | |
17 | MV = mv | |
18 | YTABC = y.tab.c | |
19 | YTABH = y.tab.h | |
20 | POSTPROCESS = echo | |
21 | ||
22 | # gcc & bison | |
23 | #CC = gcc | |
24 | #HOSTCC = gcc | |
25 | #YACC = bison -y | |
26 | #CCDEFS = | |
27 | #MV = mv | |
28 | #YTABC = y.tab.c | |
29 | #YTABH = y.tab.h | |
30 | #POSTPROCESS = echo | |
31 | ||
32 | # Delorie's DOS gcc (from ftp://omnigate.clarkson.edu/pub/msdos/djgpp) | |
33 | #CC = gcc | |
34 | #HOSTCC = gcc | |
35 | #YACC = bison -y | |
36 | #CCDEFS = | |
37 | #MV = ren | |
38 | #YTABC = y_tab.c | |
39 | #YTABH = y_tab.h | |
40 | #POSTPROCESS = coff2exe | |
41 | ||
42 | # gcc cross-compile to go32 environment | |
43 | #CC = i386-go32-gcc | |
44 | #HOSTCC = cc | |
45 | #YACC = yacc | |
46 | #CCDEFS = | |
47 | #MV = mv | |
48 | #YTABC = y.tab.c | |
49 | #YTABH = y.tab.h | |
50 | #POSTPROCESS = echo | |
51 | ||
52 | ####################################################### | |
53 | ||
54 | # -O or -g | |
55 | #DEBUG = -O -Olimit 3000 | |
56 | DEBUG = -O | |
57 | ||
58 | SRCS = main.c a56.y lex.c subs.c getopt.c kparse.key | |
59 | OBJS = main.o gram.o lex.o toktab.o subs.o getopt.o kparse.o | |
60 | ||
61 | DEFINES = $(CCDEFS) | |
62 | #DEFINES = -DYYDEBUG -DLDEBUG $(CCDEFS) | |
63 | ||
64 | CFLAGS = $(DEBUG) $(DEFINES) | |
65 | ||
66 | all: keybld a56 toomf | |
67 | ||
68 | a56: $(OBJS) | |
69 | $(CC) $(CFLAGS) -o a56 $(OBJS) -lm | |
70 | @$(POSTPROCESS) a56 | |
71 | ||
72 | keybld: keybld.o ksubs.o | |
73 | $(HOSTCC) $(CFLAGS) -o keybld keybld.o ksubs.o | |
74 | @$(POSTPROCESS) keybld | |
75 | ||
76 | keybld.o: keybld.c | |
77 | $(HOSTCC) $(CFLAGS) -c keybld.c | |
78 | ||
79 | ksubs.o: subs.c | |
80 | $(HOSTCC) $(CFLAGS) -c subs.c | |
81 | $(MV) subs.o ksubs.o | |
82 | ||
83 | lex.o: lex.c gram.h | |
84 | ||
85 | kparse.c: a56.key keybld | |
86 | keybld < a56.key > kparse.c | |
87 | ||
88 | gram.c gram.h: a56.y | |
89 | @echo "[expect 2 shift/reduce conflicts here]" | |
90 | $(YACC) -d a56.y | |
91 | $(MV) $(YTABC) gram.c | |
92 | $(MV) $(YTABH) gram.h | |
93 | ||
94 | toktab.c: gram.h | |
95 | awk -f tok.awk < gram.h > toktab.c | |
96 | ||
97 | y.output: a56.y | |
98 | $(YACC) -v a56.y | |
99 | ||
100 | toomf: toomf.o | |
101 | $(CC) -o toomf $(CFLAGS) toomf.o | |
102 | @$(POSTPROCESS) toomf | |
103 | ||
104 | torom: torom.o subs.o | |
105 | $(CC) -o torom $(CFLAGS) torom.o subs.o | |
106 | ||
107 | tape: toktab.c | |
108 | csh -c 'tar cvbf 1 - `cat files` | gzip > a56.tar.gz' | |
109 | ||
110 | main.o gram.o lex.o: a56.h | |
111 | ||
112 | clean: ; rm -f a56 toomf y.output *.o *.out tmp *.bak a56.tar.gz keybld | |
113 | ||
114 | spotless: clean | |
115 | rm -f gram.c lexyy.c gram.h toktab.c kparse.c |
0 | ||
1 | a56 - a DSP56001 assembler - version 1.1 | |
2 | ||
3 | /* | |
4 | * Copyright (C) 1990-1992 Quinn C. Jensen | |
5 | * | |
6 | * Permission to use, copy, modify, distribute, and sell this software | |
7 | * and its documentation for any purpose is hereby granted without fee, | |
8 | * provided that the above copyright notice appear in all copies and | |
9 | * that both that copyright notice and this permission notice appear | |
10 | * in supporting documentation. The author makes no representations | |
11 | * about the suitability of this software for any purpose. It is | |
12 | * provided "as is" without express or implied warranty. | |
13 | * | |
14 | */ | |
15 | ||
16 | V1.1 CHANGES | |
17 | ||
18 | Many thanks to Tom Cunningham at Motorola who noted several bugs, fixing | |
19 | most of them. Thanks also to Stephen Edwards at CalTech for his fixes as well. | |
20 | Both he and Tom fixed up the XY parallel move code; I believe all the | |
21 | fixes are integrated. | |
22 | ||
23 | Summary of changes since v1.0: | |
24 | ||
25 | - Jcc, JScc, Tcc recognizes "CC" synonym for "HS" (Tom) | |
26 | - LUA syntax fixed (Tom, Stephen) | |
27 | - DIV syntax fixed (Tom) | |
28 | - XY move fixed (Tom, Stephen) | |
29 | - a56 now detects phase errors (changes in symbol values | |
30 | between pass 1 and 2) | |
31 | - several causes of phase errors fixed | |
32 | - immediate value handling improved for both integer and | |
33 | fixed-point values | |
34 | - symbols have type (INT or FLOAT) | |
35 | - cpp droppings are properly handled | |
36 | - ALIGN pseudo-op added | |
37 | ||
38 | Known bugs/deficiencies: | |
39 | ||
40 | - MOVE to a control reg generates bogus code (always use MOVEC, | |
41 | MOVEM, and MOVEP) | |
42 | ||
43 | The example code has been cleaned up a bit and I've included my | |
44 | 56K board's envelope code - tdsg.basic.a56. This code is specific to | |
45 | my implimentation. | |
46 | ||
47 | A note on the reverb code - I have since found since posting version 1.0 | |
48 | that the reverb code has a great-big almost-DC bumb in its impulse | |
49 | response. I found this after doing some simulations. I suspected something | |
50 | was wrong because I had to scale the output of the comb filters by .046 | |
51 | or something before going into the two all-pass stages. Overall I think it | |
52 | works better without the 1.7 ms all-pass. There's another reverb example | |
53 | on Dr. Bubb that fits Moorer's 1979 model better. I've included this in | |
54 | the examples but I have not yet assembled or tried it. | |
55 | ||
56 | OVERVIEW | |
57 | ||
58 | This program was written as a vehicle to learn the intricacies | |
59 | of the DSP56001 instruction set, and to provide a tool for Unix-based | |
60 | DSP code development (for those of us without a NeXT machine.) | |
61 | ||
62 | The intent was to provide compatibility with Motorola assembler's syntax. | |
63 | But since the author did not have Motorola's assembler or its documentation, | |
64 | it is no doubt far from compatible. Only a few pseudo-ops are implemented-- | |
65 | probably only partially. | |
66 | ||
67 | Macros are not supported, except through the use of an external macro | |
68 | preprocessor, such as /lib/cpp. To facilitate cpp macro expansion, multiple | |
69 | assembler statements on a single input line are delimited with an '@', e.g.: | |
70 | ||
71 | #define JCHEQ(c,label) move #c,x0 @cmp x0,a @jeq label | |
72 | ||
73 | #define JCHNE(c,label) move #c,x0 @cmp x0,a @jne label | |
74 | ||
75 | ||
76 | SUPPORTED PSEUDO-OPS | |
77 | ||
78 | The following is a list of the pseudo-ops that are recognized: | |
79 | ||
80 | <symbol> = <expression> ;assign a symbol | |
81 | ||
82 | ALIGN <number> ;set location pointer | |
83 | ;to next integral | |
84 | ;multiple of <number> | |
85 | ||
86 | ORG <space:> <expression> ;new location pointer | |
87 | ORG <space:> <expression>, <space:> <expression> | |
88 | ||
89 | DC <dc_list> ;declare constants | |
90 | ||
91 | PAGE <number>, <number>, <number>, <number> ;ignored | |
92 | ||
93 | INCLUDE <file> ;file inclusion | |
94 | ||
95 | END ;end | |
96 | ||
97 | In addition, a "PSECT" pseudo-op was implemented. It allows program sections | |
98 | to be defined and bopped in and out of, each with its own location counter and | |
99 | space. The Motorola assembler probably does not have this pseudo-op, but no | |
100 | doubt supports the concept in some way. | |
101 | ||
102 | PSECT <name> <space:><begin_addr>:<end_addr> ;define | |
103 | ||
104 | PSECT <name> ;switch to psect <name> | |
105 | ||
106 | ||
107 | FUTURE DIRECTION | |
108 | ||
109 | The assembler probably generates bogus code here and there, and no doubt | |
110 | does not handle all of the syntax. I welcome all comments, fixes and | |
111 | enhancements. | |
112 | ||
113 | TO MAKE AND USE | |
114 | ||
115 | Type "make". gram.c and lex.yy.c are provided for those without yacc | |
116 | (or bison) and/or lex. | |
117 | ||
118 | The resulting program, a56, is used as follows: | |
119 | ||
120 | a56 [-b] [-l] [-o output-file] file [...] | |
121 | ||
122 | An assembler listing is sent to the standard-output and an ascii-formatted | |
123 | object file (a56.out) is produced. The "-b" option adds binary to the listing. | |
124 | "-l" causes included files to be listed. "-o" directs the output to the | |
125 | specified file rather than the default, a56.out. | |
126 | ||
127 | A separate program, toomf, converts a56.out into "OMF" format suitable for | |
128 | downloading to the 56001 via the sloader.a56 program. | |
129 | ||
130 | toomf < a56.out > file.omf | |
131 | ||
132 | AUTHOR | |
133 | ||
134 | 11/28/91 | |
135 | v1.1 8/6/92 | |
136 | ||
137 | Quinn C. Jensen | |
138 | 1374 N 40 E | |
139 | Orem, UT 84057 | |
140 | ||
141 | home: jensenq@zdomain.com (preferred address for a56 correspondence) | |
142 | work: jensenq@novell.com |
0 | ||
1 | a56 - a DSP56001 assembler - version 1.2 | |
2 | ||
3 | /* | |
4 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
5 | * | |
6 | * Permission to use, copy, modify, distribute, and sell this software | |
7 | * and its documentation for any purpose is hereby granted without fee, | |
8 | * provided that the above copyright notice appear in all copies and | |
9 | * that both that copyright notice and this permission notice appear | |
10 | * in supporting documentation. The author makes no representations | |
11 | * about the suitability of this software for any purpose. It is | |
12 | * provided "as is" without express or implied warranty. | |
13 | * | |
14 | */ | |
15 | ||
16 | V1.2 CHANGES | |
17 | ||
18 | Contributors to V1.2 - | |
19 | ||
20 | Andreas Gustafsson <gson@joker.cs.hut.fi> | |
21 | - Added DS and DSM directives | |
22 | - Generalization of the use of "*" allowing current program counter | |
23 | to be used in any expression (including "org l:*" which is useful | |
24 | for changing spaces without changing the PC) | |
25 | - Noted a bug with MOVEP to a non-symbolic I/O address. I believe | |
26 | this is now fixed. | |
27 | - Noted that mispelled argumentless operators will be treated as | |
28 | labels. For example, N0P (N-zero-P) will be treated as a label. | |
29 | Unfortunately, my own use of a56 (i.e. using cpp as the macro | |
30 | pre-processor) complicates this. However, the grammar might | |
31 | have been simpler if the lexical analyzer was able to distinguish | |
32 | between label declarations and references instead of leaving that | |
33 | up to the YACC parser. | |
34 | ||
35 | Tim Channon <tchannon@black.demon.co.uk> and Peter Breuer | |
36 | <ptb@comlab.ox.ac.uk> | |
37 | - Missing ";" in grammar! | |
38 | ||
39 | Rober Ganter <ganter@ifi.unibas.ch> | |
40 | - Fixed bad comment on line 10 of a56.y | |
41 | ||
42 | Me <jensenq@zdomain.com> | |
43 | - Listing now includes psect usage summary | |
44 | - Better checking of movec arguments | |
45 | - Added int(value) function to convert floating point constant expression | |
46 | to integer (by truncation) | |
47 | - Correctly convert a floating -1.0 to 0x800000 | |
48 | - Wrote a new lexical analyzer and lexical parser generator | |
49 | - Many other minor enhancements and fixes. | |
50 | - Ported to DOS using DJ Delories' GCC port. (Tools available at | |
51 | ftp://omnigate.clarkson.edu/pub/msdos/djgpp) | |
52 | ||
53 | Known bugs/deficiencies: | |
54 | ||
55 | - MOVE to a control reg generates bogus code (always use MOVEC, | |
56 | MOVEM, and MOVEP) | |
57 | ||
58 | The example code this time around includes a full six-comb stereo reverb | |
59 | (based on Moorer). This one sounds a lot better than the four-comb algorithm. | |
60 | Each comb uses a one-pole low-pass filter in the loop. It lacks the | |
61 | early-reflection FIR (although Motorola's rvb2.asm has it) but has | |
62 | true stereo decorrelation by using a twin allpass stage. My old reverb | |
63 | just used inversion to simulate stereo (the whole reverb effect would | |
64 | disappear if you mixed the outputs). I've included only actual reverb | |
65 | code itself. It lacks the hardware-implementation-specific shell. | |
66 | ||
67 | ||
68 | --------------------------------------------------------------------------- | |
69 | ||
70 | OVERVIEW | |
71 | ||
72 | This program was written as a vehicle to learn the intricacies | |
73 | of the DSP56001 instruction set, and to provide a tool for Unix-based | |
74 | DSP code development (for those of us without a NeXT machine.) | |
75 | ||
76 | The intent was to provide compatibility with Motorola assembler's syntax. | |
77 | But since the author did not have Motorola's assembler or its documentation, | |
78 | it is no doubt far from compatible. Only a few pseudo-ops are implemented-- | |
79 | probably only partially. | |
80 | ||
81 | Macros are not supported, except through the use of an external macro | |
82 | preprocessor, such as /lib/cpp. To facilitate cpp macro expansion, multiple | |
83 | assembler statements on a single input line are delimited with an '@', e.g.: | |
84 | ||
85 | #define JCHEQ(c,label) move #c,x0 @cmp x0,a @jeq label | |
86 | ||
87 | #define JCHNE(c,label) move #c,x0 @cmp x0,a @jne label | |
88 | ||
89 | ||
90 | SUPPORTED PSEUDO-OPS | |
91 | ||
92 | The following is a list of the pseudo-ops that are recognized: | |
93 | ||
94 | <symbol> = <expression> ;assign a symbol | |
95 | <label> EQU <expression> ;ditto | |
96 | ||
97 | ALIGN <number> ;set location pointer | |
98 | ;to next integral | |
99 | ;multiple of <number> | |
100 | ||
101 | ORG <space:> <expression> ;new location pointer | |
102 | ORG <space:> <expression>, <space:> <expression> | |
103 | ||
104 | DC <dc_list> ;declare constants | |
105 | ||
106 | DS <number> ;reserve <number> | |
107 | ;words of space | |
108 | ||
109 | <label> DSM <number> ;reserve space for | |
110 | ;properly aligned | |
111 | ;modulo-addressed | |
112 | ;buffer of size | |
113 | ;<number>, assigning | |
114 | ;the aligned starting | |
115 | ;address to <label> | |
116 | ||
117 | PAGE <number>, <number>, <number>, <number> ;ignored | |
118 | ||
119 | INCLUDE <file> ;file inclusion | |
120 | ||
121 | END ;end | |
122 | ||
123 | In addition, a "PSECT" pseudo-op was implemented. It allows program sections | |
124 | to be defined and bopped in and out of, each with its own location counter and | |
125 | space. The Motorola assembler probably does not have this pseudo-op, but no | |
126 | doubt supports the concept in some way. | |
127 | ||
128 | PSECT <name> <space:><begin_addr>:<end_addr> ;define | |
129 | ||
130 | PSECT <name> ;switch to psect <name> | |
131 | ||
132 | ||
133 | FUTURE DIRECTION | |
134 | ||
135 | The assembler probably generates bogus code here and there, and no doubt | |
136 | does not handle all of the syntax. I welcome all comments, fixes and | |
137 | enhancements. | |
138 | ||
139 | TO MAKE AND USE | |
140 | ||
141 | Type "make". | |
142 | ||
143 | The resulting program, a56, is used as follows: | |
144 | ||
145 | a56 [-b] [-l] [-o output-file] file [...] | |
146 | ||
147 | An assembler listing is sent to the standard-output and an ascii-formatted | |
148 | object file (a56.out) is produced. The "-b" option adds binary to the listing. | |
149 | "-l" causes included files to be listed. "-o" directs the output to the | |
150 | specified file rather than the default, a56.out. | |
151 | ||
152 | A separate program, toomf, converts a56.out into "OMF" format suitable for | |
153 | downloading to the 56001 via the sloader.a56 program. | |
154 | ||
155 | toomf < a56.out > file.omf | |
156 | ||
157 | AUTHOR | |
158 | ||
159 | 11/28/91 | |
160 | v1.1 8/6/92 | |
161 | v1.2 5/2/94 | |
162 | ||
163 | Quinn C. Jensen | |
164 | 1374 N 40 E | |
165 | Orem, UT 84057 | |
166 | ||
167 | home: jensenq@zdomain.com (preferred address for a56 correspondence) | |
168 | work: jensenq@novell.com |
0 | ||
1 | a56 - a DSP5600X assembler - version 1.3 | |
2 | ||
3 | /* | |
4 | * Copyright (C) 1990-1998 Quinn C. Jensen | |
5 | * | |
6 | * Permission to use, copy, modify, distribute, and sell this software | |
7 | * and its documentation for any purpose is hereby granted without fee, | |
8 | * provided that the above copyright notice appear in all copies and | |
9 | * that both that copyright notice and this permission notice appear | |
10 | * in supporting documentation. The author makes no representations | |
11 | * about the suitability of this software for any purpose. It is | |
12 | * provided "as is" without express or implied warranty. | |
13 | * | |
14 | */ | |
15 | ||
16 | V1.3 CHANGES | |
17 | ||
18 | - Added intrinsic transcendental functions for constant literal | |
19 | expressions (pi, sin, cos, tan atan, asin, acos, exp, ln, log, | |
20 | pow) | |
21 | ||
22 | - Added warnings for control register load/use hazards | |
23 | ||
24 | - More sophisticated constant expression evaluation including | |
25 | implicit float/integer conversion. Results of expressions | |
26 | are typed and so formatted in the listing and symbol table. | |
27 | ||
28 | - Various fixes including stray pointers, etc. (Thanks to | |
29 | Dirk Farin farindk@trick.informatik.uni-stuttgart.de) | |
30 | ||
31 | Known bugs/deficiencies: | |
32 | ||
33 | - MOVE to a control reg generates bogus code (always use MOVEC, | |
34 | MOVEM, and MOVEP) | |
35 | ||
36 | Wish list | |
37 | ||
38 | - Add support for new instructions and modes | |
39 | ||
40 | ||
41 | --------------------------------------------------------------------------- | |
42 | ||
43 | OVERVIEW | |
44 | ||
45 | This program was written as a vehicle to learn the intricacies | |
46 | of the DSP56001 instruction set, and to provide a tool for Unix-based | |
47 | DSP code development (for those of us without a NeXT machine.) | |
48 | ||
49 | The intent was to provide compatibility with Motorola assembler's syntax. | |
50 | But since the author did not have Motorola's assembler or its documentation, | |
51 | it is no doubt far from compatible. Only a few pseudo-ops are implemented-- | |
52 | probably only partially. | |
53 | ||
54 | Macros are not supported, except through the use of an external macro | |
55 | preprocessor, such as /lib/cpp. To facilitate cpp macro expansion, multiple | |
56 | assembler statements on a single input line are delimited with an '@', e.g.: | |
57 | ||
58 | #define JCHEQ(c,label) move #c,x0 @cmp x0,a @jeq label | |
59 | ||
60 | #define JCHNE(c,label) move #c,x0 @cmp x0,a @jne label | |
61 | ||
62 | ||
63 | SUPPORTED PSEUDO-OPS | |
64 | ||
65 | The following is a list of the pseudo-ops that are recognized: | |
66 | ||
67 | <symbol> = <expression> ;assign a symbol | |
68 | <label> EQU <expression> ;ditto | |
69 | ||
70 | ALIGN <number> ;set location pointer | |
71 | ;to next integral | |
72 | ;multiple of <number> | |
73 | ||
74 | ORG <space:> <expression> ;new location pointer | |
75 | ORG <space:> <expression>, <space:> <expression> | |
76 | ||
77 | DC <dc_list> ;declare constants | |
78 | ||
79 | DS <number> ;reserve <number> | |
80 | ;words of space | |
81 | ||
82 | <label> DSM <number> ;reserve space for | |
83 | ;properly aligned | |
84 | ;modulo-addressed | |
85 | ;buffer of size | |
86 | ;<number>, assigning | |
87 | ;the aligned starting | |
88 | ;address to <label> | |
89 | ||
90 | PAGE <number>, <number>, <number>, <number> ;ignored | |
91 | ||
92 | INCLUDE <file> ;file inclusion | |
93 | ||
94 | END ;end | |
95 | ||
96 | In addition, a "PSECT" pseudo-op was implemented. It allows program sections | |
97 | to be defined and bopped in and out of, each with its own location counter and | |
98 | space. The Motorola assembler probably does not have this pseudo-op, but no | |
99 | doubt supports the concept in some way. | |
100 | ||
101 | PSECT <name> <space:><begin_addr>:<end_addr> ;define | |
102 | ||
103 | PSECT <name> ;switch to psect <name> | |
104 | ||
105 | ||
106 | FUTURE DIRECTION | |
107 | ||
108 | The assembler probably generates bogus code here and there, and no doubt | |
109 | does not handle all of the syntax. I welcome all comments, fixes and | |
110 | enhancements. | |
111 | ||
112 | TO MAKE AND USE | |
113 | ||
114 | Type "make". | |
115 | ||
116 | The resulting program, a56, is used as follows: | |
117 | ||
118 | a56 [-b] [-l] [-o output-file] file [...] | |
119 | ||
120 | An assembler listing is sent to the standard-output and an ascii-formatted | |
121 | object file (a56.out) is produced. The "-b" option adds binary to the listing. | |
122 | "-l" causes included files to be listed. "-o" directs the output to the | |
123 | specified file rather than the default, a56.out. | |
124 | ||
125 | A separate program, toomf, converts a56.out into "OMF" format suitable for | |
126 | downloading to the 56001 via the sloader.a56 program. | |
127 | ||
128 | toomf < a56.out > file.omf | |
129 | ||
130 | AUTHOR | |
131 | ||
132 | 11/28/91 | |
133 | v1.1 8/6/92 | |
134 | v1.2 5/2/94 | |
135 | v1.3 3/18/98 | |
136 | ||
137 | Quinn C. Jensen | |
138 | 1374 N 40 E | |
139 | Orem, UT 84057 | |
140 | ||
141 | http://www.zdomain.com/~jensenq/ | |
142 | ||
143 | home: jensenq@zdomain.com (preferred address for a56 correspondence) | |
144 | work: jensenq@novell.com |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
11 | * | |
12 | * Permission to use, copy, modify, distribute, and sell this software | |
13 | * and its documentation for any purpose is hereby granted without fee, | |
14 | * provided that the above copyright notice appear in all copies and | |
15 | * that both that copyright notice and this permission notice appear | |
16 | * in supporting documentation. The author makes no representations | |
17 | * about the suitability of this software for any purpose. It is | |
18 | * provided "as is" without express or implied warranty. | |
19 | * | |
20 | */ | |
21 | ||
22 | /* | |
23 | * a56.h - general definitions | |
24 | * | |
25 | */ | |
26 | ||
27 | #include <stdio.h> | |
28 | ||
29 | #ifndef TRUE | |
30 | #define TRUE 1 | |
31 | #define FALSE 0 | |
32 | #define NOT ! | |
33 | typedef int BOOL; | |
34 | #endif | |
35 | ||
36 | struct sym { | |
37 | char *name; | |
38 | struct n { | |
39 | short type; | |
40 | #define UNDEF -1 | |
41 | #define INT 0 | |
42 | #define FLT 1 | |
43 | short seg; | |
44 | #define NONE 0 | |
45 | #define PROG 1 | |
46 | #define XDATA 2 | |
47 | #define YDATA 3 | |
48 | #define LDATA 4 | |
49 | #define ANY 5 | |
50 | union val { | |
51 | int i; | |
52 | double f; | |
53 | } val; | |
54 | } n; | |
55 | struct sym *next; | |
56 | } *find_sym(); | |
57 | ||
58 | extern int pass; | |
59 | ||
60 | #define NEW(object) ((object *)alloc(sizeof(object))) | |
61 | ||
62 | #define MAX_NEST 20 /* maximum include file nesting */ | |
63 | ||
64 | struct inc { | |
65 | char *file; | |
66 | FILE *fp; | |
67 | int line; | |
68 | }; | |
69 | extern struct inc inc[]; | |
70 | extern int inc_p; | |
71 | #define curfile inc[inc_p].file | |
72 | #define curline inc[inc_p].line | |
73 | ||
74 | extern int ldebug; | |
75 | ||
76 | struct psect { | |
77 | char *name; | |
78 | int seg; | |
79 | unsigned int pc, bottom, top; | |
80 | struct psect *next; | |
81 | } *find_psect(), *new_psect(); | |
82 | ||
83 | FILE *open_read(), *open_write(), *open_append(); | |
84 | ||
85 | /* save string s somewhere */ | |
86 | #define strsave(s) ((s) != NULL ? \ | |
87 | (char *)strcpy((char *)malloc(strlen(s)+1),(s)) : NULL) | |
88 | ||
89 | /* after a call to fgets(), remove the newline character */ | |
90 | #define rmcr(s) {if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0';}; | |
91 | ||
92 | #define ASSERT(expr, str) \ | |
93 | if(expr) fprintf(stderr, "ASSERT: %s: line %d: %s\n", __FILE__, __LINE__, str); |
0 | .code #include "a56.h" | |
1 | .code #include "gram.h" | |
2 | X: {return XMEM;} | |
3 | Y: {return YMEM;} | |
4 | L: {return LMEM;} | |
5 | P: {return PMEM;} | |
6 | A10 {return A10;} | |
7 | A {return AAAA;} | |
8 | B10 {return B10;} | |
9 | B {return BBBB;} | |
10 | AB {return AABB;} | |
11 | BA {return BBAA;} | |
12 | X {return XXXX;} | |
13 | Y {return YYYY;} | |
14 | SR {return SR;} | |
15 | MR {return MR;} | |
16 | CCR {return CCR;} | |
17 | OMR {return OMR;} | |
18 | SP {return SP;} | |
19 | SSH {return SSH;} | |
20 | SSL {return SSL;} | |
21 | LA {return LA;} | |
22 | LC {return LC;} | |
23 | A0 {yylval.ival = 0; return AREG;} | |
24 | A1 {yylval.ival = 1; return AREG;} | |
25 | A2 {yylval.ival = 2; return AREG;} | |
26 | B0 {yylval.ival = 0; return BREG;} | |
27 | B1 {yylval.ival = 1; return BREG;} | |
28 | B2 {yylval.ival = 2; return BREG;} | |
29 | M0 {yylval.ival = 0; return MREG;} | |
30 | M1 {yylval.ival = 1; return MREG;} | |
31 | M2 {yylval.ival = 2; return MREG;} | |
32 | M3 {yylval.ival = 3; return MREG;} | |
33 | M4 {yylval.ival = 4; return MREG;} | |
34 | M5 {yylval.ival = 5; return MREG;} | |
35 | M6 {yylval.ival = 6; return MREG;} | |
36 | M7 {yylval.ival = 7; return MREG;} | |
37 | N0 {yylval.ival = 0; return NREG;} | |
38 | N1 {yylval.ival = 1; return NREG;} | |
39 | N2 {yylval.ival = 2; return NREG;} | |
40 | N3 {yylval.ival = 3; return NREG;} | |
41 | N4 {yylval.ival = 4; return NREG;} | |
42 | N5 {yylval.ival = 5; return NREG;} | |
43 | N6 {yylval.ival = 6; return NREG;} | |
44 | N7 {yylval.ival = 7; return NREG;} | |
45 | R0 {yylval.ival = 0; return RREG;} | |
46 | R1 {yylval.ival = 1; return RREG;} | |
47 | R2 {yylval.ival = 2; return RREG;} | |
48 | R3 {yylval.ival = 3; return RREG;} | |
49 | R4 {yylval.ival = 4; return RREG;} | |
50 | R5 {yylval.ival = 5; return RREG;} | |
51 | R6 {yylval.ival = 6; return RREG;} | |
52 | R7 {yylval.ival = 7; return RREG;} | |
53 | X0 {yylval.ival = 0; return XREG;} | |
54 | X1 {yylval.ival = 1; return XREG;} | |
55 | Y0 {yylval.ival = 0; return YREG;} | |
56 | Y1 {yylval.ival = 1; return YREG;} | |
57 | ABS {return OP_ABS;} | |
58 | ADC {return OP_ADC;} | |
59 | ADD {return OP_ADD;} | |
60 | ADDL {return OP_ADDL;} | |
61 | ADDR {return OP_ADDR;} | |
62 | ASL {return OP_ASL;} | |
63 | ASR {return OP_ASR;} | |
64 | CLR {return OP_CLR;} | |
65 | CMP {return OP_CMP;} | |
66 | CMPM {return OP_CMPM;} | |
67 | DIV {return OP_DIV;} | |
68 | MAC {return OP_MAC;} | |
69 | MACR {return OP_MACR;} | |
70 | MPY {return OP_MPY;} | |
71 | MPYR {return OP_MPYR;} | |
72 | NEG {return OP_NEG;} | |
73 | NORM {return OP_NORM;} | |
74 | RND {return OP_RND;} | |
75 | SBC {return OP_SBC;} | |
76 | SUB {return OP_SUB;} | |
77 | SUBL {return OP_SUBL;} | |
78 | SUBR {return OP_SUBR;} | |
79 | TCC {yylval.cond = 0x0; return OP_TCC;} | |
80 | THS {yylval.cond = 0x0; return OP_TCC;} | |
81 | TGE {yylval.cond = 0x1; return OP_TCC;} | |
82 | TNE {yylval.cond = 0x2; return OP_TCC;} | |
83 | TPL {yylval.cond = 0x3; return OP_TCC;} | |
84 | TNN {yylval.cond = 0x4; return OP_TCC;} | |
85 | TEC {yylval.cond = 0x5; return OP_TCC;} | |
86 | TLC {yylval.cond = 0x6; return OP_TCC;} | |
87 | TGT {yylval.cond = 0x7; return OP_TCC;} | |
88 | TCS {yylval.cond = 0x8; return OP_TCC;} | |
89 | TLO {yylval.cond = 0x8; return OP_TCC;} | |
90 | TLT {yylval.cond = 0x9; return OP_TCC;} | |
91 | TEQ {yylval.cond = 0xA; return OP_TCC;} | |
92 | TMI {yylval.cond = 0xB; return OP_TCC;} | |
93 | TNR {yylval.cond = 0xC; return OP_TCC;} | |
94 | TES {yylval.cond = 0xD; return OP_TCC;} | |
95 | TLS {yylval.cond = 0xE; return OP_TCC;} | |
96 | TLE {yylval.cond = 0xF; return OP_TCC;} | |
97 | TFR {return OP_TFR;} | |
98 | TST {return OP_TST;} | |
99 | AND {return OP_AND;} | |
100 | ANDI {return OP_ANDI;} | |
101 | EOR {return OP_EOR;} | |
102 | LSL {return OP_LSL;} | |
103 | LSR {return OP_LSR;} | |
104 | NOT {return OP_NOT;} | |
105 | OR {return OP_OR;} | |
106 | ORI {return OP_ORI;} | |
107 | ROL {return OP_ROL;} | |
108 | ROR {return OP_ROR;} | |
109 | BCLR {return OP_BCLR;} | |
110 | BSET {return OP_BSET;} | |
111 | BCHG {return OP_BCHG;} | |
112 | BTST {return OP_BTST;} | |
113 | DO {return OP_DO;} | |
114 | ENDDO {return OP_ENDDO;} | |
115 | LUA {return OP_LUA;} | |
116 | MOVE {return OP_MOVE;} | |
117 | MOVEC {return OP_MOVEC;} | |
118 | MOVEM {return OP_MOVEM;} | |
119 | MOVEP {return OP_MOVEP;} | |
120 | INCLUDE {return OP_INCLUDE;} | |
121 | ILLEGAL {return OP_ILLEGAL;} | |
122 | JCC {yylval.cond = 0x0; return OP_JCC;} | |
123 | JHS {yylval.cond = 0x0; return OP_JCC;} | |
124 | JGE {yylval.cond = 0x1; return OP_JCC;} | |
125 | JNE {yylval.cond = 0x2; return OP_JCC;} | |
126 | JPL {yylval.cond = 0x3; return OP_JCC;} | |
127 | JNN {yylval.cond = 0x4; return OP_JCC;} | |
128 | JEC {yylval.cond = 0x5; return OP_JCC;} | |
129 | JLC {yylval.cond = 0x6; return OP_JCC;} | |
130 | JGT {yylval.cond = 0x7; return OP_JCC;} | |
131 | JCS {yylval.cond = 0x8; return OP_JCC;} | |
132 | JLO {yylval.cond = 0x8; return OP_JCC;} | |
133 | JLT {yylval.cond = 0x9; return OP_JCC;} | |
134 | JEQ {yylval.cond = 0xA; return OP_JCC;} | |
135 | JMI {yylval.cond = 0xB; return OP_JCC;} | |
136 | JNR {yylval.cond = 0xC; return OP_JCC;} | |
137 | JES {yylval.cond = 0xD; return OP_JCC;} | |
138 | JLS {yylval.cond = 0xE; return OP_JCC;} | |
139 | JLE {yylval.cond = 0xF; return OP_JCC;} | |
140 | JMP {return OP_JMP;} | |
141 | JCLR {return OP_JCLR;} | |
142 | JSET {return OP_JSET;} | |
143 | JSCC {yylval.cond = 0x0; return OP_JSCC;} | |
144 | JSHS {yylval.cond = 0x0; return OP_JSCC;} | |
145 | JSGE {yylval.cond = 0x1; return OP_JSCC;} | |
146 | JSNE {yylval.cond = 0x2; return OP_JSCC;} | |
147 | JSPL {yylval.cond = 0x3; return OP_JSCC;} | |
148 | JSNN {yylval.cond = 0x4; return OP_JSCC;} | |
149 | JSEC {yylval.cond = 0x5; return OP_JSCC;} | |
150 | JSLC {yylval.cond = 0x6; return OP_JSCC;} | |
151 | JSGT {yylval.cond = 0x7; return OP_JSCC;} | |
152 | JSCS {yylval.cond = 0x8; return OP_JSCC;} | |
153 | JSLO {yylval.cond = 0x8; return OP_JSCC;} | |
154 | JSLT {yylval.cond = 0x9; return OP_JSCC;} | |
155 | JSEQ {yylval.cond = 0xA; return OP_JSCC;} | |
156 | JSMI {yylval.cond = 0xB; return OP_JSCC;} | |
157 | JSNR {yylval.cond = 0xC; return OP_JSCC;} | |
158 | JSES {yylval.cond = 0xD; return OP_JSCC;} | |
159 | JSLS {yylval.cond = 0xE; return OP_JSCC;} | |
160 | JSLE {yylval.cond = 0xF; return OP_JSCC;} | |
161 | JSR {return OP_JSR;} | |
162 | JSCLR {return OP_JSCLR;} | |
163 | JSSET {return OP_JSSET;} | |
164 | NOP {return OP_NOP;} | |
165 | REP {return OP_REP;} | |
166 | RESET {return OP_RESET;} | |
167 | RTI {return OP_RTI;} | |
168 | RTS {return OP_RTS;} | |
169 | STOP {return OP_STOP;} | |
170 | SWI {return OP_SWI;} | |
171 | WAIT {return OP_WAIT;} | |
172 | EQU {return OP_EQU;} | |
173 | ORG {return OP_ORG;} | |
174 | DC {return OP_DC;} | |
175 | DS {return OP_DS;} | |
176 | DSM {return OP_DSM;} | |
177 | INT {return OP_INT;} | |
178 | END {return OP_END;} | |
179 | PAGE {return OP_PAGE;} | |
180 | PSECT {return OP_PSECT;} | |
181 | ALIGN {return OP_ALIGN;} | |
182 | PI {return OP_PI;} | |
183 | SIN {return OP_SIN;} | |
184 | COS {return OP_COS;} | |
185 | TAN {return OP_TAN;} | |
186 | ATAN {return OP_ATAN;} | |
187 | ASIN {return OP_ASIN;} | |
188 | ACOS {return OP_ACOS;} | |
189 | EXP {return OP_EXP;} | |
190 | LN {return OP_LN;} | |
191 | LOG {return OP_LOG;} | |
192 | POW {return OP_POW;} |
0 | %{ | |
1 | /******************************************************* | |
2 | * | |
3 | * a56 - a DSP56001 assembler | |
4 | * | |
5 | * Written by Quinn C. Jensen | |
6 | * July 1990 | |
7 | * | |
8 | *******************************************************/ | |
9 | ||
10 | /* | |
11 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
12 | * | |
13 | * Permission to use, copy, modify, distribute, and sell this software | |
14 | * and its documentation for any purpose is hereby granted without fee, | |
15 | * provided that the above copyright notice appear in all copies and | |
16 | * that both that copyright notice and this permission notice appear | |
17 | * in supporting documentation. The author makes no representations | |
18 | * about the suitability of this software for any purpose. It is | |
19 | * provided "as is" without express or implied warranty. | |
20 | * | |
21 | */ | |
22 | ||
23 | /* | |
24 | * a56.y - The YACC grammar for the assembler. | |
25 | * | |
26 | * Note: This module requires a "BIG" version of YACC. I had to | |
27 | * recompile YACC in the largest mode available. | |
28 | * | |
29 | * Other notes: | |
30 | * | |
31 | * MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure | |
32 | * out which form to use. | |
33 | * | |
34 | */ | |
35 | ||
36 | #include "a56.h" | |
37 | #include <math.h> | |
38 | ||
39 | unsigned int w0, w1; /* workspace for the actual generated code */ | |
40 | BOOL uses_w1; /* says whether w1 is alive */ | |
41 | unsigned int pc; /* current program counter */ | |
42 | int seg; /* current segment P: X: Y: or L: */ | |
43 | int expr_seg; /* segment of current expression */ | |
44 | ||
45 | int just_rep = 0; /* keeps track of REP instruction */ | |
46 | int hot_rreg = -1; /* rreg loaded by prev inst. or -1 */ | |
47 | int hot_nreg = -1; /* nreg loaded by prev inst. or -1 */ | |
48 | int hot_mreg = -1; /* mreg loaded by prev inst. or -1 */ | |
49 | int prev_hot_rreg = -1; /* rreg loaded by prev inst. or -1 */ | |
50 | int prev_hot_nreg = -1; /* nreg loaded by prev inst. or -1 */ | |
51 | int prev_hot_mreg = -1; /* mreg loaded by prev inst. or -1 */ | |
52 | ||
53 | int substatement = 0; /* in a substatement */ | |
54 | BOOL long_symbolic_expr = FALSE; /* a parser flag */ | |
55 | char *new_include = NULL; /* file to be included */ | |
56 | ||
57 | /* listing stuff */ | |
58 | ||
59 | char segs[] = "uPXYL*"; | |
60 | extern BOOL list_on_next; /* listing to turn on or off */ | |
61 | BOOL list_on; /* listing on at the moment */ | |
62 | extern char *cur_line; /* points to line being lex'd */ | |
63 | char list_buf[1024 + 80]; /* listing buffer */ | |
64 | char list_buf2[1024 + 80]; /* listing buffer for two-line code */ | |
65 | BOOL uses_buf2 = FALSE; /* list_buf2 is alive */ | |
66 | BOOL list_print_line = FALSE; /* whether or not to print line in listing */ | |
67 | char *spaces(), *luntab(); | |
68 | ||
69 | struct n binary_op(); | |
70 | struct n unary_op(); | |
71 | struct n sym_ref(); | |
72 | ||
73 | #define R_R6 0x0001 | |
74 | #define R_R5 0x0002 | |
75 | #define R_R4 0x0004 | |
76 | #define R_DATA_ALU_ACCUM 0x0008 | |
77 | #define R_CTL_REG 0x0010 | |
78 | #define R_FUNKY_CTL_REG 0x0020 | |
79 | #define R_SDX 0x0040 | |
80 | #define R_SDY 0x0080 | |
81 | #define R_LSD 0x0100 | |
82 | #define R_AB 0x0200 | |
83 | #define R_XREG 0x0400 | |
84 | #define R_YREG 0x0800 | |
85 | /* registers to which short immediate move is an unsigned int */ | |
86 | #define R_UINT 0x1000 | |
87 | /* registers to which short immediate move is an signed frac */ | |
88 | #define R_SFRAC 0x2000 | |
89 | %} | |
90 | ||
91 | %union { | |
92 | int ival; /* integer value */ | |
93 | struct n n; /* just like in struct sym */ | |
94 | double dval; /* floating point value */ | |
95 | char *sval; /* string */ | |
96 | int cval; /* character */ | |
97 | char cond; /* condition */ | |
98 | struct regs { | |
99 | int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg; | |
100 | int sdx, sdy, lsd, ab, xreg, yreg; | |
101 | int flags; | |
102 | } regs; | |
103 | struct ea { | |
104 | int mode; | |
105 | int ext; | |
106 | int pp; | |
107 | } ea; | |
108 | } | |
109 | ||
110 | %token <n> CHEX CDEC FRAC | |
111 | %token <ival> AREG BREG MREG NREG RREG XREG YREG | |
112 | %token <ival> OP OPA OPP | |
113 | %token <cond> OP_JCC OP_JSCC OP_TCC | |
114 | %token <sval> SYM | |
115 | %token <sval> STRING | |
116 | %token <cval> CHAR | |
117 | %token XMEM | |
118 | %token YMEM | |
119 | %token LMEM | |
120 | %token PMEM | |
121 | %token AAAA | |
122 | %token A10 | |
123 | %token BBBB | |
124 | %token B10 | |
125 | %token AABB | |
126 | %token BBAA | |
127 | %token XXXX | |
128 | %token YYYY | |
129 | %token SR | |
130 | %token MR | |
131 | %token CCR | |
132 | %token OMR | |
133 | %token SP | |
134 | %token SSH | |
135 | %token SSL | |
136 | %token LA | |
137 | %token LC | |
138 | %token EOL | |
139 | %token EOS | |
140 | %token LEXBAD | |
141 | ||
142 | %token OP_ABS | |
143 | %token OP_ADC | |
144 | %token OP_ADD | |
145 | %token OP_ADDL | |
146 | %token OP_ADDR | |
147 | %token OP_ASL | |
148 | %token OP_ASR | |
149 | %token OP_CLR | |
150 | %token OP_CMP | |
151 | %token OP_CMPM | |
152 | %token OP_DIV | |
153 | %token OP_MAC | |
154 | %token OP_MACR | |
155 | %token OP_MPY | |
156 | %token OP_MPYR | |
157 | %token OP_NEG | |
158 | %token OP_NORM | |
159 | %token OP_RND | |
160 | %token OP_SBC | |
161 | %token OP_SUB | |
162 | %token OP_SUBL | |
163 | %token OP_SUBR | |
164 | %token OP_TFR | |
165 | %token OP_TST | |
166 | %token OP_AND | |
167 | %token OP_ANDI | |
168 | %token OP_EOR | |
169 | %token OP_LSL | |
170 | %token OP_LSR | |
171 | %token OP_NOT | |
172 | %token OP_OR | |
173 | %token OP_ORI | |
174 | %token OP_ROL | |
175 | %token OP_ROR | |
176 | %token OP_BCLR | |
177 | %token OP_BSET | |
178 | %token OP_BCHG | |
179 | %token OP_BTST | |
180 | %token OP_DO | |
181 | %token OP_ENDDO | |
182 | %token OP_LUA | |
183 | %token OP_MOVE | |
184 | %token OP_MOVEC | |
185 | %token OP_MOVEM | |
186 | %token OP_MOVEP | |
187 | %token OP_ILLEGAL | |
188 | %token OP_INCLUDE | |
189 | %token OP_JMP | |
190 | %token OP_JCLR | |
191 | %token OP_JSET | |
192 | %token OP_JSR | |
193 | %token OP_JSCLR | |
194 | %token OP_JSSET | |
195 | %token OP_NOP | |
196 | %token OP_REP | |
197 | %token OP_RESET | |
198 | %token OP_RTI | |
199 | %token OP_RTS | |
200 | %token OP_STOP | |
201 | %token OP_SWI | |
202 | %token OP_WAIT | |
203 | %token OP_EQU | |
204 | %token OP_ORG | |
205 | %token OP_DC | |
206 | %token OP_DS | |
207 | %token OP_DSM | |
208 | %token OP_END | |
209 | %token OP_PAGE | |
210 | %token OP_PSECT | |
211 | %token OP_ALIGN | |
212 | %token OP_INT | |
213 | %token SHL | |
214 | %token SHR | |
215 | %token OP_PI | |
216 | %token OP_SIN | |
217 | %token OP_COS | |
218 | %token OP_TAN | |
219 | %token OP_ATAN | |
220 | %token OP_ASIN | |
221 | %token OP_ACOS | |
222 | %token OP_EXP | |
223 | %token OP_LN | |
224 | %token OP_LOG | |
225 | %token OP_POW | |
226 | ||
227 | %type <n> num num_or_sym | |
228 | %type <n> num_or_sym_expr | |
229 | %type <n> expr | |
230 | %type <n> ix | |
231 | %type <n> ix_long | |
232 | ||
233 | %type <ival> abs_addr abs_short_addr io_short_addr | |
234 | %type <ival> a_b x_or_y ea b5_10111_max | |
235 | %type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12 | |
236 | %type <ival> ea_short | |
237 | %type <ival> prog_ctl_reg | |
238 | %type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8 | |
239 | %type <ival> mpy_arg mpy_srcs plus_minus | |
240 | %type <ival> sd3 | |
241 | %type <ival> funky_ctl_reg tcc_sd space | |
242 | %type <sval> opt_label | |
243 | ||
244 | %type <regs> regs | |
245 | %type <ea> movep_ea_pp | |
246 | ||
247 | %left '|' | |
248 | %left '^' | |
249 | %left SHL SHR | |
250 | %left '&' | |
251 | %left '+' '-' | |
252 | %left '*' '/' '%' | |
253 | %right '~' | |
254 | ||
255 | %start input | |
256 | ||
257 | %% | |
258 | ||
259 | /*%%%********************* top syntax ***********************/ | |
260 | ||
261 | input : /* empty */ | |
262 | | input statement | |
263 | ; | |
264 | ||
265 | statement | |
266 | : good_stuff EOL | |
267 | { | |
268 | if(pass == 2 && list_on && list_print_line) { | |
269 | printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n", | |
270 | list_buf, substatement == 0 ? luntab(cur_line) : ""); | |
271 | if(uses_buf2) | |
272 | printf(ldebug ? "\n(%s|)\n" : "%s\n", | |
273 | list_buf2); | |
274 | list_buf[0] = list_buf2[0] = '\0'; | |
275 | } | |
276 | curline++; | |
277 | uses_buf2 = FALSE; | |
278 | list_print_line = TRUE; | |
279 | list_on = list_on_next; | |
280 | substatement = 0; | |
281 | if(NOT check_psect(seg, pc) && pass == 2) | |
282 | yyerror("%04X: psect violation", pc); | |
283 | } | |
284 | | good_stuff EOS | |
285 | { | |
286 | if(pass == 2 && list_on && list_print_line) { | |
287 | printf(ldebug ? "\n(%s" : "%s", list_buf); | |
288 | if(substatement == 0) | |
289 | printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line)); | |
290 | else | |
291 | printf(ldebug ? ")\n" : "\n"); | |
292 | if(uses_buf2) | |
293 | printf(ldebug ? "\n(%s|)\n" : "%s\n", | |
294 | list_buf2); | |
295 | list_buf[0] = list_buf2[0] = '\0'; | |
296 | } | |
297 | substatement++; | |
298 | uses_buf2 = FALSE; | |
299 | list_print_line = TRUE; | |
300 | list_on = list_on_next; | |
301 | if(NOT check_psect(seg, pc) && pass == 2) | |
302 | yyerror("%04X: psect violation", pc); | |
303 | } | |
304 | | error EOL | |
305 | {curline++; substatement = 0;} | |
306 | ; | |
307 | ||
308 | good_stuff | |
309 | : /* empty */ | |
310 | {sprintf(list_buf, "%s", spaces(0));} | |
311 | | cpp_droppings | |
312 | {list_print_line = FALSE;} | |
313 | | assembler_ops | |
314 | {long_symbolic_expr = FALSE;} | |
315 | | label_field operation_field | |
316 | {char *printcode(); | |
317 | if(pass == 2) { | |
318 | gencode(seg, pc, w0); | |
319 | sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0)); | |
320 | pc++; | |
321 | if(uses_w1) { | |
322 | gencode(seg, pc, w1); | |
323 | sprintf(list_buf2, "%c:%04X %s", segs[seg], pc, | |
324 | printcode(w1 & 0xFFFFFF)); | |
325 | uses_buf2++; | |
326 | pc++; | |
327 | } | |
328 | } else { | |
329 | pc++; | |
330 | if(uses_w1) | |
331 | pc++; | |
332 | } | |
333 | w0 = w1 = 0; uses_w1 = FALSE; | |
334 | long_symbolic_expr = FALSE;} | |
335 | | SYM | |
336 | {sym_def($1, INT, seg, pc); | |
337 | free($1); | |
338 | if(pass == 2 && list_on) { | |
339 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8)); | |
340 | long_symbolic_expr = FALSE; | |
341 | }} | |
342 | ; | |
343 | ||
344 | cpp_droppings | |
345 | : '#' num STRING | |
346 | {if(strlen($3) > 0) | |
347 | curfile = $3; | |
348 | else | |
349 | curfile = "<stdin>"; | |
350 | curline = $2.val.i - 1;} | |
351 | ; | |
352 | ||
353 | assembler_ops | |
354 | : SYM OP_EQU expr | |
355 | {sym_def($1, $3.type, ANY, $3.val.i, $3.val.f); | |
356 | free($1); | |
357 | if(pass == 2 && list_on) { | |
358 | if($3.type == INT) | |
359 | sprintf(list_buf, "%06X%s", | |
360 | $3.val.i & 0xFFFFFF, | |
361 | spaces(14-8)); | |
362 | else | |
363 | sprintf(list_buf, "%10g%s", $3.val.f, | |
364 | spaces(14-4)); | |
365 | }} | |
366 | | OP_ALIGN expr | |
367 | {int ival = n2int($2); | |
368 | if($2.type == UNDEF) { | |
369 | yyerror("illegal forward reference"); | |
370 | } else if (ival <= 1) { | |
371 | yyerror("%d: illegal alignment", ival); | |
372 | } else { | |
373 | if(pc % ival != 0) | |
374 | pc += ival - pc % ival; | |
375 | } | |
376 | if(pass == 2 && list_on) | |
377 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, | |
378 | spaces(14-8)); | |
379 | } | |
380 | | OP_PSECT SYM | |
381 | {struct psect *pp = find_psect($2); | |
382 | if(NOT pp) { | |
383 | if(pass == 2) | |
384 | yyerror("%s: undefined psect", $2); | |
385 | } else { | |
386 | seg = pp->seg; | |
387 | pc = pp->pc; | |
388 | set_psect(pp); | |
389 | if(pass == 2 && list_on) | |
390 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, | |
391 | spaces(14-8)); | |
392 | } | |
393 | free($2);} | |
394 | | OP_PSECT SYM space expr ':' expr | |
395 | {new_psect($2, $3, n2int($4), n2int($6)); | |
396 | if(pass == 2 && list_on) | |
397 | sprintf(list_buf, "%c:%04X %04X%s", | |
398 | segs[$3], n2int($4), n2int($6), spaces(14-8+4+1)); | |
399 | } | |
400 | | OP_ORG space expr | |
401 | {pc = n2int($3); | |
402 | seg = $2; | |
403 | if(pass == 2 && list_on) | |
404 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, | |
405 | spaces(14-8)); | |
406 | } | |
407 | | OP_ORG space expr ',' space expr | |
408 | {pc = n2int($3); | |
409 | seg = $2; | |
410 | if(pass == 2 && list_on) | |
411 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, | |
412 | spaces(14-8)); | |
413 | } | |
414 | | label_field OP_DC dc_list | |
415 | | label_field OP_DS expr | |
416 | {pc += n2int($3); | |
417 | if(pass == 2 && list_on) | |
418 | sprintf(list_buf, "%c:%04X%s", segs[seg], pc, | |
419 | spaces(14-8)); | |
420 | } | |
421 | | opt_label OP_DSM expr | |
422 | {int size = n2int($3); | |
423 | if(size) | |
424 | { int align = 1; | |
425 | while(align < size) | |
426 | align <<= 1; | |
427 | pc += (align - (pc % align)); | |
428 | } | |
429 | if($1) | |
430 | { sym_def($1, INT, seg, pc); | |
431 | free($1); | |
432 | } | |
433 | pc += size; | |
434 | } | |
435 | | OP_PAGE num ',' num ',' num ',' num | |
436 | {if(pass == 2 && list_on) { | |
437 | sprintf(list_buf, "%s", spaces(0)); | |
438 | }} | |
439 | | OP_INCLUDE STRING | |
440 | {if(pass == 2 && list_on) { | |
441 | printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n", | |
442 | spaces(0), luntab(cur_line)); | |
443 | list_print_line = FALSE; | |
444 | } | |
445 | include($2); /* free($2); */ | |
446 | } | |
447 | | OP_END | |
448 | {if(pass == 2 && list_on) { | |
449 | sprintf(list_buf, "%s", spaces(0)); | |
450 | }} | |
451 | ; | |
452 | ||
453 | dc_list | |
454 | : dc_list ',' dc_stuff | |
455 | | dc_stuff | |
456 | ; | |
457 | ||
458 | dc_stuff | |
459 | : STRING | |
460 | {int len = strlen($1), i; char *cp; w0 = 0; | |
461 | if(len % 3 == 2) | |
462 | len++; /* force empty word */ | |
463 | for(i = 0, cp = $1; i < len; i++, cp++) { | |
464 | w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8; | |
465 | if(i % 3 == 2 || i == len - 1) { | |
466 | if(pass == 2) { | |
467 | if(list_on) sprintf(list_buf, "%c:%04X %06X%s", | |
468 | segs[seg], pc, w0, | |
469 | spaces(14-6+5)); | |
470 | gencode(seg, pc, w0); | |
471 | } | |
472 | pc++; w0 = 0; | |
473 | } | |
474 | } | |
475 | free($1);} | |
476 | | expr | |
477 | {int frac = n2frac($1); | |
478 | if(pass == 2) { | |
479 | if(list_on) { | |
480 | sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc, | |
481 | frac & 0xFFFFFF, spaces(14-6+5)); | |
482 | } | |
483 | gencode(seg, pc, frac); | |
484 | } | |
485 | pc++;} | |
486 | ||
487 | space | |
488 | : PMEM | |
489 | {$$ = PROG;} | |
490 | | XMEM | |
491 | {$$ = XDATA;} | |
492 | | YMEM | |
493 | {$$ = YDATA;} | |
494 | | LMEM | |
495 | {$$ = LDATA;} | |
496 | ; | |
497 | ||
498 | label_field | |
499 | : SYM | |
500 | {sym_def($1, INT, seg, pc); | |
501 | free($1);} | |
502 | | /* empty */ | |
503 | ; | |
504 | ||
505 | opt_label | |
506 | : SYM {$$ = $1;} | |
507 | | /* empty */ {$$ = NULL;} | |
508 | ; | |
509 | ||
510 | operation_field | |
511 | : operation | |
512 | {prev_hot_rreg = hot_rreg; | |
513 | prev_hot_nreg = hot_nreg; | |
514 | prev_hot_mreg = hot_mreg; | |
515 | hot_rreg = hot_nreg = hot_mreg = -1; | |
516 | if(just_rep) | |
517 | just_rep--;} | |
518 | ; | |
519 | ||
520 | operation | |
521 | : no_parallel | |
522 | | parallel_ok | |
523 | {w0 |= 0x200000;} | |
524 | | parallel_ok parallel_move | |
525 | ; | |
526 | ||
527 | /*%%%************* instructions that allow parallel moves ****************/ | |
528 | ||
529 | parallel_ok | |
530 | : | |
531 | OP_MPY mpy_arg | |
532 | {w0 |= 0x80 | $2 << 2;} | |
533 | | OP_MPYR mpy_arg | |
534 | {w0 |= 0x81 | $2 << 2;} | |
535 | | OP_MAC mpy_arg | |
536 | {w0 |= 0x82 | $2 << 2;} | |
537 | | OP_MACR mpy_arg | |
538 | {w0 |= 0x83 | $2 << 2;} | |
539 | ||
540 | | OP_SUB op8_1 | |
541 | {w0 |= 0x04 | $2 << 3;} | |
542 | | OP_ADD op8_1 | |
543 | {w0 |= 0x00 | $2 << 3;} | |
544 | | OP_MOVE | |
545 | {w0 |= 0x00;} | |
546 | ||
547 | | OP_TFR op8_2 | |
548 | {w0 |= 0x01 | $2 << 3;} | |
549 | | OP_CMP op8_2 | |
550 | {w0 |= 0x05 | $2 << 3;} | |
551 | | OP_CMPM op8_2 | |
552 | {w0 |= 0x07 | $2 << 3;} | |
553 | ||
554 | | OP_RND op8_3 | |
555 | {w0 |= 0x11 | $2 << 3;} | |
556 | | OP_ADDL op8_3 | |
557 | {w0 |= 0x12 | $2 << 3;} | |
558 | | OP_CLR op8_3 | |
559 | {w0 |= 0x13 | $2 << 3;} | |
560 | | OP_SUBL op8_3 | |
561 | {w0 |= 0x16 | $2 << 3;} | |
562 | | OP_NOT op8_3 | |
563 | {w0 |= 0x17 | $2 << 3;} | |
564 | ||
565 | | OP_ADDR op8_4 | |
566 | {w0 |= 0x02 | $2 << 3;} | |
567 | | OP_TST op8_4 | |
568 | {w0 |= 0x03 | $2 << 3;} | |
569 | | OP_SUBR op8_4 | |
570 | {w0 |= 0x06 | $2 << 3;} | |
571 | ||
572 | | OP_AND op8_5 | |
573 | {w0 |= 0x46 | $2 << 3;} | |
574 | | OP_OR op8_5 | |
575 | {w0 |= 0x42 | $2 << 3;} | |
576 | | OP_EOR op8_5 | |
577 | {w0 |= 0x43 | $2 << 3;} | |
578 | ||
579 | | OP_ASR op8_6 | |
580 | {w0 |= 0x22 | $2 << 3;} | |
581 | | OP_LSR op8_6 | |
582 | {w0 |= 0x23 | $2 << 3;} | |
583 | | OP_ABS op8_6 | |
584 | {w0 |= 0x26 | $2 << 3;} | |
585 | | OP_ROR op8_6 | |
586 | {w0 |= 0x27 | $2 << 3;} | |
587 | ||
588 | | OP_ASL op8_7 | |
589 | {w0 |= 0x32 | $2 << 3;} | |
590 | | OP_LSL op8_7 | |
591 | {w0 |= 0x33 | $2 << 3;} | |
592 | | OP_NEG op8_7 | |
593 | {w0 |= 0x36 | $2 << 3;} | |
594 | | OP_ROL op8_7 | |
595 | {w0 |= 0x37 | $2 << 3;} | |
596 | ||
597 | | OP_ADC op8_8 | |
598 | {w0 |= 0x21 | $2 << 3;} | |
599 | | OP_SBC op8_8 | |
600 | {w0 |= 0x25 | $2 << 3;} | |
601 | ; | |
602 | ||
603 | mpy_arg : plus_minus mpy_srcs ',' a_b | |
604 | {$$ = $1 | $4 << 1 | $2 << 2;} | |
605 | ; | |
606 | ||
607 | plus_minus | |
608 | : '+' | |
609 | {$$ = 0;} | |
610 | | '-' | |
611 | {$$ = 1;} | |
612 | | | |
613 | {$$ = 0;} | |
614 | ; | |
615 | ||
616 | mpy_srcs | |
617 | : XREG ',' XREG | |
618 | {switch ($1 << 4 | $3) { | |
619 | case 0x00: $$ = 0x0; break; | |
620 | case 0x01: | |
621 | case 0x10: $$ = 0x2; break; | |
622 | case 0x11: | |
623 | yyerror("illegal source operands"); | |
624 | break; | |
625 | }} | |
626 | | YREG ',' YREG | |
627 | {switch ($1 << 4 | $3) { | |
628 | case 0x00: $$ = 0x1; break; | |
629 | case 0x01: | |
630 | case 0x10: $$ = 0x3; break; | |
631 | case 0x11: | |
632 | yyerror("illegal source operands"); | |
633 | break; | |
634 | }} | |
635 | | XREG ',' YREG | |
636 | {switch ($1 << 4 | $3) { | |
637 | case 0x00: $$ = 0x5; break; | |
638 | case 0x01: $$ = 0x4; break; | |
639 | case 0x10: $$ = 0x6; break; | |
640 | case 0x11: $$ = 0x7; break; | |
641 | }} | |
642 | | YREG ',' XREG | |
643 | {switch ($1 << 4 | $3) { | |
644 | case 0x00: $$ = 0x5; break; | |
645 | case 0x01: $$ = 0x6; break; | |
646 | case 0x10: $$ = 0x4; break; | |
647 | case 0x11: $$ = 0x7; break; | |
648 | }} | |
649 | ; | |
650 | ||
651 | op8_1 : BBBB ',' AAAA | |
652 | {$$ = 0x2;} | |
653 | | AAAA ',' BBBB | |
654 | {$$ = 0x3;} | |
655 | | XXXX ',' a_b | |
656 | {$$ = 0x4 | $3;} | |
657 | | YYYY ',' a_b | |
658 | {$$ = 0x6 | $3;} | |
659 | | XREG ',' a_b | |
660 | {$$ = 0x8 | $1 << 2 | $3;} | |
661 | | YREG ',' a_b | |
662 | {$$ = 0xA | $1 << 2 | $3;} | |
663 | ; | |
664 | ||
665 | op8_2 : BBBB ',' AAAA | |
666 | {$$ = 0x0;} | |
667 | | AAAA ',' BBBB | |
668 | {$$ = 0x1;} | |
669 | | XREG ',' a_b | |
670 | {$$ = 0x8 | $1 << 2 | $3;} | |
671 | | YREG ',' a_b | |
672 | {$$ = 0xA | $1 << 2 | $3;} | |
673 | ; | |
674 | ||
675 | op8_3 : AAAA | |
676 | {$$ = 0x0;} | |
677 | | BBBB | |
678 | {$$ = 0x1;} | |
679 | | BBBB ',' AAAA | |
680 | {$$ = 0x0;} | |
681 | | AAAA ',' BBBB | |
682 | {$$ = 0x1;} | |
683 | ; | |
684 | ||
685 | op8_4 : op8_3 | |
686 | {$$ = $1;} | |
687 | ; | |
688 | ||
689 | op8_5 : XREG ',' a_b | |
690 | {$$ = 0x0 | $1 << 2 | $3;} | |
691 | | YREG ',' a_b | |
692 | {$$ = 0x2 | $1 << 2 | $3;} | |
693 | ; | |
694 | ||
695 | op8_6 : a_b | |
696 | {$$ = $1;} | |
697 | ; | |
698 | ||
699 | op8_7 : a_b | |
700 | {$$ = $1;} | |
701 | ; | |
702 | ||
703 | op8_8 : XXXX ',' a_b | |
704 | {$$ = 0x0 | $3;} | |
705 | | YYYY ',' a_b | |
706 | {$$ = 0x2 | $3;} | |
707 | ; | |
708 | ||
709 | a_b : AAAA | |
710 | {$$ = 0;} | |
711 | | BBBB | |
712 | {$$ = 1;} | |
713 | ; | |
714 | ||
715 | no_parallel | |
716 | : control_inst | |
717 | {if(just_rep == 1) | |
718 | yyerror("instruction not allowed after REP");} | |
719 | | bit_inst | |
720 | | move_inst | |
721 | | arith_inst | |
722 | ; | |
723 | ||
724 | /*%%%************** non-parallel arithmetic and logical ********************/ | |
725 | ||
726 | arith_inst | |
727 | : OP_NORM RREG ',' a_b | |
728 | {w0 |= 0x01D815 | $2 << 8 | $4 << 3;} | |
729 | | OP_DIV sd3 | |
730 | {w0 |= 0x018040 | $2 << 3;} | |
731 | | or_op ix ',' funky_ctl_reg | |
732 | {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;} | |
733 | | and_op ix ',' funky_ctl_reg | |
734 | {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;} | |
735 | ; | |
736 | ||
737 | or_op : OP_OR | |
738 | | OP_ORI | |
739 | ; | |
740 | ||
741 | and_op : OP_AND | |
742 | | OP_ANDI | |
743 | ; | |
744 | ||
745 | /*%%%******************************* control instructions **********************/ | |
746 | ||
747 | control_inst | |
748 | : OP_JSCC ea_a12 | |
749 | {if($2) { | |
750 | w0 |= 0x0BC0A0 | $1 << 0; | |
751 | } else { | |
752 | w0 |= 0x0F0000 | $1 << 12; | |
753 | }} | |
754 | | OP_JCC ea_a12 | |
755 | {if($2) { | |
756 | w0 |= 0x0AC0A0 | $1 << 0; | |
757 | } else { | |
758 | w0 |= 0x0E0000 | $1 << 12; | |
759 | }} | |
760 | | OP_JSR ea_a12 | |
761 | {if($2) { | |
762 | w0 |= 0x0BC080; | |
763 | } else { | |
764 | w0 |= 0x0D0000; | |
765 | }} | |
766 | | OP_JMP ea_a12 | |
767 | {if($2) { | |
768 | w0 |= 0x0AC080; | |
769 | } else { | |
770 | w0 |= 0x0C0000; | |
771 | }} | |
772 | ||
773 | | OP_JSSET control_args | |
774 | {w0 |= 0x0B0020;} | |
775 | | OP_JSCLR control_args | |
776 | {w0 |= 0x0B0000;} | |
777 | | OP_JSET control_args | |
778 | {w0 |= 0x0A0020;} | |
779 | | OP_JCLR control_args | |
780 | {w0 |= 0x0A0000;} | |
781 | ||
782 | | OP_REP rep_args | |
783 | {just_rep = 2;} | |
784 | | OP_DO do_args | |
785 | {uses_w1++;} | |
786 | | OP_ENDDO | |
787 | {w0 |= 0x00008C;} | |
788 | | OP_STOP | |
789 | {w0 |= 0x000087;} | |
790 | | OP_WAIT | |
791 | {w0 |= 0x000086;} | |
792 | | OP_RESET | |
793 | {w0 |= 0x000084;} | |
794 | | OP_RTS | |
795 | {w0 |= 0x00000C;} | |
796 | | OP_SWI | |
797 | {w0 |= 0x000006;} | |
798 | | OP_ILLEGAL | |
799 | {w0 |= 0x000005;} | |
800 | | OP_RTI | |
801 | {w0 |= 0x000004;} | |
802 | | OP_NOP | |
803 | {w0 |= 0x000000; | |
804 | just_rep = 0;} | |
805 | ; | |
806 | ||
807 | do_args | |
808 | : ix ',' abs_addr | |
809 | {int ival = n2int($1); | |
810 | w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8; | |
811 | if(ival > 0xFFF && pass == 2) { | |
812 | yywarning("warning: immediate operand truncated"); | |
813 | } | |
814 | w1 |= $3-1;} | |
815 | | regs ',' abs_addr | |
816 | {w0 |= 0x06C000 | $1.r6 << 8; | |
817 | hot_rreg = hot_nreg = hot_mreg = -1; | |
818 | w1 |= $3-1;} | |
819 | | x_or_y ea_no_ext ',' abs_addr | |
820 | {w0 |= 0x064000 | $2 << 8 | $1 << 6; | |
821 | w1 |= $4-1;} | |
822 | | x_or_y abs_short_addr ',' abs_addr /* allow forced */ | |
823 | {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6; | |
824 | /* | |
825 | * $$$ oops, can't check expr_seg because both abs_short_addr and | |
826 | * abs_addr touch it | |
827 | */ | |
828 | if($2 > 0x003F && pass == 2) | |
829 | yywarning("warning: address operand truncated"); | |
830 | w1 |= $4-1;} | |
831 | | x_or_y abs_addr ',' abs_addr | |
832 | {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6; | |
833 | /* | |
834 | * $$$ oops, can't check expr_seg because both abs_short_addr and | |
835 | * abs_addr touch it | |
836 | */ | |
837 | if($2 > 0x003F && pass == 2) | |
838 | yywarning("warning: address operand truncated"); | |
839 | w1 |= $4-1;} | |
840 | ; | |
841 | ||
842 | rep_args | |
843 | : ix | |
844 | {int ival = n2int($1); | |
845 | w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8; | |
846 | if(ival > 0xFFF && pass == 2) { | |
847 | yywarning("warning: immediate operand truncated"); | |
848 | }} | |
849 | | regs | |
850 | {w0 |= 0x06C020 | $1.r6 << 8; | |
851 | hot_rreg = hot_nreg = hot_mreg = -1;} | |
852 | | x_or_y ea_no_ext | |
853 | {w0 |= 0x064020 | $1 << 6 | $2 << 8;} | |
854 | | x_or_y abs_addr | |
855 | {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8; | |
856 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
857 | $1 == 1 && expr_seg != YDATA)) | |
858 | yywarning("warning: space mismatch"); | |
859 | if($2 > 0x003F && pass == 2) | |
860 | yywarning("warning: address operand truncated"); | |
861 | } | |
862 | | x_or_y abs_short_addr /* forced */ | |
863 | {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8; | |
864 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
865 | $1 == 1 && expr_seg != YDATA)) | |
866 | yywarning("warning: space mismatch"); | |
867 | if($2 > 0x003F && pass == 2) | |
868 | yywarning("warning: address operand truncated"); | |
869 | } | |
870 | ; | |
871 | ||
872 | control_args | |
873 | : b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr | |
874 | {w0 |= $1 << 0 | $3 << 6; | |
875 | uses_w1++; | |
876 | w1 = $6;} | |
877 | | b5_10111_max ',' regs ',' abs_addr | |
878 | {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8; | |
879 | hot_rreg = hot_nreg = hot_mreg = -1; | |
880 | uses_w1++; | |
881 | w1 = $5;} | |
882 | ; | |
883 | ||
884 | p6_ean_a6 | |
885 | : abs_addr /* in pass 2 can always discern size. */ | |
886 | /* Sometimes in pass one, too. But since */ | |
887 | /* address extension is always used for the */ | |
888 | /* branch target, pass 1 can assume the */ | |
889 | /* symbol value will fit; warning in pass 2 */ | |
890 | /* if it doesn't */ | |
891 | {if($1 != -1) { /* symbol defined */ | |
892 | w0 |= ($1 & 0x3F) << 8; | |
893 | if($1 >= 0xFFC0) { | |
894 | w0 |= 0x008080; | |
895 | } else { | |
896 | w0 |= 0x000080; | |
897 | if($1 > 0x003F && pass == 2) | |
898 | yywarning("warning: address operand truncated"); | |
899 | } | |
900 | }} | |
901 | | abs_short_addr | |
902 | {if($1 != -1) { | |
903 | if($1 > 0x3F && pass == 2) | |
904 | yywarning("warning: address operand truncated"); | |
905 | w0 |= 0x000080 | ($1 & 0x3F) << 8; | |
906 | }} | |
907 | | io_short_addr | |
908 | {if($1 != -1) { | |
909 | if($1 < 0xFFC0 && pass == 2) | |
910 | yywarning("warning: address operand truncated"); | |
911 | w0 |= 0x008080 | ($1 & 0x3F) << 8; | |
912 | }} | |
913 | | ea_no_ext | |
914 | {w0 |= 0x004080 | $1 << 8;} | |
915 | ; | |
916 | ||
917 | /*%%%**************************** bit instructions ***************************/ | |
918 | ||
919 | bit_inst | |
920 | : OP_BTST bit_args | |
921 | {w0 |= 0x0B0020;} | |
922 | | OP_BCHG bit_args | |
923 | {w0 |= 0x0B0000;} | |
924 | | OP_BSET bit_args | |
925 | {w0 |= 0x0A0020;} | |
926 | | OP_BCLR bit_args | |
927 | {w0 |= 0x0A0000;} | |
928 | ; | |
929 | ||
930 | bit_args | |
931 | : b5_10111_max ',' x_or_y p6_ea_a6 | |
932 | {w0 |= $1 << 0 | $3 << 6; | |
933 | } | |
934 | | b5_10111_max ',' regs | |
935 | {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;} | |
936 | ; | |
937 | ||
938 | p6_ea_a6 | |
939 | : io_short_addr /* must be forced to tell from abs_addr */ | |
940 | {if($1 != -1) { | |
941 | w0 |= ($1 & 0x3F) << 8 | 0x008000; | |
942 | if($1 < 0xFFC0 && pass == 2) | |
943 | yywarning("warning: address operand truncated"); | |
944 | }} | |
945 | | abs_short_addr /* must be forced to tell from abs_addr */ | |
946 | {if($1 != -1) { | |
947 | w0 |= ($1 & 0x3F) << 8 | 0x000000; | |
948 | if($1 > 0x003F && pass == 2) | |
949 | yywarning("warning: address operand truncated"); | |
950 | }} | |
951 | | ea /* can use abs_addr */ | |
952 | {w0 |= 0x004000;} | |
953 | ; | |
954 | ||
955 | /*%%%************************** move instructions **********************/ | |
956 | ||
957 | move_inst | |
958 | : OP_MOVEP movep_args | |
959 | | OP_MOVEM movem_args | |
960 | | OP_MOVEC movec_args | |
961 | | OP_LUA ea_short ',' regs | |
962 | {w0 |= 0x044010 | $2 << 8 | $4.r4;} | |
963 | | OP_TCC tcc_args | |
964 | {w0 |= $1 << 12;} | |
965 | ; | |
966 | ||
967 | tcc_args | |
968 | : tcc_sd | |
969 | {w0 |= 0x020000 | $1 << 3;} | |
970 | | tcc_sd RREG ',' RREG | |
971 | {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;} | |
972 | ; | |
973 | ||
974 | tcc_sd | |
975 | : regs /* a_b */ ',' regs /* a_b */ | |
976 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
977 | if($1.flags & R_AB && $3.flags & R_AB) { | |
978 | if($1.ab == $3.ab) | |
979 | yyerror("source and dest must be different"); | |
980 | $$ = $3.ab; | |
981 | } else if($1.flags & R_XREG && $3.flags & R_AB) { | |
982 | $$ = 0x8 | $1.xreg << 2 | $3.ab; | |
983 | } else if($1.flags & R_YREG && $3.flags & R_AB) { | |
984 | $$ = 0xA | $1.yreg << 2 | $3.ab; | |
985 | } else | |
986 | yyerror("illegal TCC operands"); | |
987 | } | |
988 | ; | |
989 | ||
990 | sd3 : regs /* XREG */ ',' regs /* a_b */ | |
991 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
992 | if($1.flags & R_XREG && $3.flags & R_AB) { | |
993 | $$ = $1.xreg << 2 | $3.ab; | |
994 | } else if($1.flags & R_YREG && $3.flags & R_AB) { | |
995 | $$ = $1.yreg << 2 | 2 | $3.ab; | |
996 | }} | |
997 | ; | |
998 | ||
999 | movec_args | |
1000 | : x_or_y ea ',' regs /* ctl_reg */ | |
1001 | {if(NOT ($4.flags & R_CTL_REG)) | |
1002 | yyerror("bad MOVEC target register"); | |
1003 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
1004 | $1 == 1 && expr_seg != YDATA)) | |
1005 | yywarning("warning: space mismatch"); | |
1006 | if($1 == 0) { | |
1007 | w0 |= 0x05C020 | $4.ctl_reg; | |
1008 | } else { | |
1009 | w0 |= 0x05C060 | $4.ctl_reg; | |
1010 | }} | |
1011 | | regs /* ctl_reg */ ',' x_or_y ea | |
1012 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1013 | if(NOT ($1.flags & R_CTL_REG)) | |
1014 | yyerror("bad MOVEC source register"); | |
1015 | if($3 == 0) { | |
1016 | w0 |= 0x054020 | $1.ctl_reg; | |
1017 | } else { | |
1018 | w0 |= 0x054060 | $1.ctl_reg; | |
1019 | }} | |
1020 | | ix ',' regs /* ctl_reg */ | |
1021 | {int ival = n2int($1); | |
1022 | if(NOT ($3.flags & R_CTL_REG)) | |
1023 | yyerror("bad MOVEC target register"); | |
1024 | if(ival < 256 && NOT long_symbolic_expr) { | |
1025 | w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; | |
1026 | } else { | |
1027 | w0 |= 0x05C020 | 0x003400 | $3.ctl_reg; | |
1028 | uses_w1++; w1 = ival & 0xFFFF; | |
1029 | }} | |
1030 | | x_or_y abs_short_addr ',' regs /* ctl_reg */ | |
1031 | {if($1 == 0) { | |
1032 | w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg; | |
1033 | } else { | |
1034 | w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg; | |
1035 | } | |
1036 | if(NOT ($4.flags & R_CTL_REG)) | |
1037 | yyerror("bad MOVEC target register"); | |
1038 | if($2 > 0x003F && pass == 2) | |
1039 | yywarning("warning: address operand truncated"); | |
1040 | } | |
1041 | | regs /* ctl_reg */ ',' x_or_y abs_short_addr | |
1042 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1043 | if($3 == 0) { | |
1044 | w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg; | |
1045 | } else { | |
1046 | w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg; | |
1047 | } | |
1048 | if(NOT ($1.flags & R_CTL_REG)) | |
1049 | yyerror("bad MOVEC source register"); | |
1050 | if($4 > 0x003F && pass == 2) | |
1051 | yywarning("warning: address operand truncated"); | |
1052 | } | |
1053 | | regs /* ctl_reg */ ',' regs | |
1054 | {if($1.flags & R_CTL_REG) { | |
1055 | w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg; | |
1056 | } else if($3.flags & R_CTL_REG) { | |
1057 | w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg; | |
1058 | } else if($1.flags & $3.flags & R_CTL_REG) { | |
1059 | /* bogus? $$$ */ | |
1060 | w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | | |
1061 | $3.ctl_reg; | |
1062 | } else { | |
1063 | yyerror("MOVEC must reference a control reg"); | |
1064 | }} | |
1065 | ; | |
1066 | ||
1067 | movep_args | |
1068 | : x_or_y movep_ea_pp ',' x_or_y movep_ea_pp | |
1069 | {w0 |= 0x084080; | |
1070 | switch($2.pp << 1 | $5.pp) { | |
1071 | case 0: case 3: | |
1072 | yyerror("illegal MOVEP; can't move EA to EA or IO to IO"); | |
1073 | break; | |
1074 | case 1: /* ea, pp */ | |
1075 | w0 |= $4 << 16 | 1 << 15 | $1 << 6 | | |
1076 | ($5.ext & 0x3F); | |
1077 | if($2.mode == 0x003000) { | |
1078 | w0 |= 0x003000; | |
1079 | uses_w1++; | |
1080 | w1 = $2.ext; | |
1081 | } else { | |
1082 | w0 |= $2.mode; | |
1083 | } | |
1084 | break; | |
1085 | case 2: /* pp, ea */ | |
1086 | w0 |= $1 << 16 | 0 << 15 | $4 << 6 | | |
1087 | ($2.ext & 0x3F); | |
1088 | if($5.mode == 0x003000) { | |
1089 | w0 |= 0x003000; | |
1090 | uses_w1++; | |
1091 | w1 = $5.ext; | |
1092 | } else { | |
1093 | w0 |= $5.mode; | |
1094 | } | |
1095 | break; | |
1096 | }} | |
1097 | | ix ',' x_or_y num_or_sym | |
1098 | {w0 |= 0x084080; | |
1099 | w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | | |
1100 | (n2int($4) & 0x3F); | |
1101 | uses_w1++; | |
1102 | w1 = n2int($1);} | |
1103 | | PMEM ea ',' x_or_y num_or_sym | |
1104 | {w0 |= 0x084040; | |
1105 | w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);} | |
1106 | | x_or_y movep_ea_pp ',' PMEM ea | |
1107 | {w0 |= 0x084040; | |
1108 | if($2.mode != 0x003000 && $2.mode != 0) | |
1109 | yyerror("illegal MOVEP"); | |
1110 | w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);} | |
1111 | | regs ',' x_or_y num_or_sym | |
1112 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1113 | w0 |= 0x084000; | |
1114 | w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | | |
1115 | (n2int($4) & 0x3F);} | |
1116 | | x_or_y movep_ea_pp ',' regs | |
1117 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1118 | w0 |= 0x084000; | |
1119 | if(!$2.pp) | |
1120 | yyerror("illegal MOVEP"); | |
1121 | w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);} | |
1122 | ; | |
1123 | ||
1124 | movep_ea_pp | |
1125 | : abs_addr | |
1126 | {if($1 != UNDEF && $1 >= 0xFFC0) { | |
1127 | /* defined symbol or constant, in i/o range */ | |
1128 | $$.pp = 1; | |
1129 | $$.mode = 0; | |
1130 | } else { | |
1131 | /* either out of i/o range or symbol not */ | |
1132 | /* yet defined: assume ea extension */ | |
1133 | $$.pp = 0; | |
1134 | $$.mode = 0x003000; | |
1135 | } | |
1136 | $$.ext = $1;} | |
1137 | | io_short_addr /* forced i/o short */ | |
1138 | {$$.pp = 1; | |
1139 | $$.mode = 0; | |
1140 | if($1 < 0xFFC0 && pass == 2) | |
1141 | yywarning("warning: address operand truncated"); | |
1142 | $$.ext = $1;} | |
1143 | | ea_no_ext | |
1144 | {$$.pp = 0; | |
1145 | $$.mode = $1 << 8; | |
1146 | $$.ext = $1;} | |
1147 | ; | |
1148 | ||
1149 | movem_args | |
1150 | : regs ',' PMEM ea_a6 | |
1151 | {w0 |= 0x070000 | 0 << 15 | $1.r6;} | |
1152 | | PMEM ea_a6 ',' regs | |
1153 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1154 | w0 |= 0x070000 | 1 << 15 | $4.r6;} | |
1155 | ; | |
1156 | ||
1157 | /*%%%**************** memory reference fields ************************/ | |
1158 | ||
1159 | b5_10111_max | |
1160 | : ix | |
1161 | {int ival = n2int($1); | |
1162 | $$ = ival; if(ival > 0x17) | |
1163 | yyerror("%d: illegal bit number", ival);} | |
1164 | ; | |
1165 | ||
1166 | x_or_y | |
1167 | : XMEM | |
1168 | {$$ = 0;} | |
1169 | | YMEM | |
1170 | {$$ = 1;} | |
1171 | ; | |
1172 | ||
1173 | /*%%%**************** effective address fields ************************/ | |
1174 | ||
1175 | ea_a6 | |
1176 | : ea | |
1177 | {w0 |= 0x004080;} | |
1178 | | abs_short_addr | |
1179 | {w0 |= ($1 & 0x3F) << 8; | |
1180 | if($1 > 0x003F && pass == 2) | |
1181 | yywarning("warning: address operand truncated"); | |
1182 | } | |
1183 | ; | |
1184 | ||
1185 | ea_a12 | |
1186 | : ea | |
1187 | {$$ = 1;} | |
1188 | | abs_short_addr | |
1189 | {w0 |= $1 & 0xFFF; $$ = 0; | |
1190 | if($1 > 0x0FFF && pass == 2) | |
1191 | yywarning("warning: address operand truncated"); | |
1192 | } | |
1193 | ; | |
1194 | ||
1195 | ea : abs_addr | |
1196 | {w0 |= 0x003000; | |
1197 | uses_w1++; | |
1198 | w1 |= $1; | |
1199 | $$ = 0x003000;} | |
1200 | | ea_no_ext | |
1201 | {w0 |= $1 << 8; | |
1202 | $$ = $1 << 8; | |
1203 | expr_seg = ANY;} | |
1204 | ; | |
1205 | ||
1206 | ea_no_ext | |
1207 | : ea_short | |
1208 | {$$ = $1;} | |
1209 | | '(' RREG ')' | |
1210 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1211 | $$ = 4 << 3 | $2;} | |
1212 | | '(' RREG '+' NREG ')' | |
1213 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1214 | if($4 == prev_hot_nreg) yywarning("warning: n%d just loaded", $4); | |
1215 | if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); | |
1216 | $$ = 5 << 3 | $2; | |
1217 | if($2 != $4) yyerror("Rn and Nn must be same number");} | |
1218 | | '-' '(' RREG ')' | |
1219 | {if($3 == prev_hot_rreg) yywarning("warning: r%d just loaded", $3); | |
1220 | if($3 == prev_hot_mreg) yywarning("warning: m%d just loaded", $3); | |
1221 | $$ = 7 << 3 | $3;} | |
1222 | ; | |
1223 | ||
1224 | ea_short | |
1225 | : '(' RREG ')' '-' NREG | |
1226 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1227 | if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5); | |
1228 | if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); | |
1229 | $$ = 0 << 3 | $2; | |
1230 | expr_seg = ANY; | |
1231 | if($2 != $5) yyerror("Rn and Nn must be same number");} | |
1232 | | '(' RREG ')' '+' NREG | |
1233 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1234 | if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5); | |
1235 | if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); | |
1236 | $$ = 1 << 3 | $2; | |
1237 | expr_seg = ANY; | |
1238 | if($2 != $5) yyerror("Rn and Nn must be same number");} | |
1239 | | '(' RREG ')' '-' | |
1240 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1241 | if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); | |
1242 | expr_seg = ANY; | |
1243 | $$ = 2 << 3 | $2;} | |
1244 | | '(' RREG ')' '+' | |
1245 | {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); | |
1246 | if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); | |
1247 | expr_seg = ANY; | |
1248 | $$ = 3 << 3 | $2;} | |
1249 | ; | |
1250 | ||
1251 | /*%%%******************* register fields ******************************/ | |
1252 | ||
1253 | regs | |
1254 | : XREG | |
1255 | {$$.r6 = $$.r5 = 0x04 | $1; | |
1256 | $$.sdx = $1; | |
1257 | $$.xreg = $1; | |
1258 | $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;} | |
1259 | | YREG | |
1260 | {$$.r6 = $$.r5 = 0x06 | $1; | |
1261 | $$.sdy = $1; | |
1262 | $$.yreg = $1; | |
1263 | $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;} | |
1264 | | AREG | |
1265 | {switch($1) { | |
1266 | case 0: | |
1267 | $$.r6 = $$.r5 = 0x08 | 0; | |
1268 | break; | |
1269 | case 1: | |
1270 | $$.r6 = $$.r5 = 0x08 | 4; | |
1271 | break; | |
1272 | case 2: | |
1273 | $$.r6 = $$.r5 = 0x08 | 2; | |
1274 | break; | |
1275 | } | |
1276 | $$.flags = R_R6|R_R5|R_UINT;} | |
1277 | | BREG | |
1278 | {switch($1) { | |
1279 | case 0: | |
1280 | $$.r6 = $$.r5 = 0x08 | 1; break; | |
1281 | case 1: | |
1282 | $$.r6 = $$.r5 = 0x08 | 5; break; | |
1283 | case 2: | |
1284 | $$.r6 = $$.r5 = 0x08 | 3; break; | |
1285 | } | |
1286 | $$.flags = R_R6|R_R5|R_UINT;} | |
1287 | | AAAA | |
1288 | {$$.r6 = $$.r5 = 0x0E; | |
1289 | $$.sdx = $$.sdy = 0x2; | |
1290 | $$.ab = 0; | |
1291 | $$.lsd = 4; | |
1292 | $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;} | |
1293 | | BBBB | |
1294 | {$$.r6 = $$.r5 = 0x0F; | |
1295 | $$.sdx = $$.sdy = 0x3; | |
1296 | $$.ab = 1; | |
1297 | $$.lsd = 5; | |
1298 | $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;} | |
1299 | | RREG | |
1300 | {$$.r6 = $$.r5 = 0x10 | $1; | |
1301 | $$.r4 = 0x00 | $1; | |
1302 | $$.flags = R_R6|R_R5|R_R4|R_UINT; | |
1303 | hot_rreg = $1;} | |
1304 | | NREG | |
1305 | {$$.r6 = $$.r5 = 0x18 | $1; | |
1306 | $$.r4 = 0x08 | $1; | |
1307 | $$.flags = R_R6|R_R5|R_R4|R_UINT; | |
1308 | hot_nreg = $1;} | |
1309 | | MREG | |
1310 | {$$.r6 = 0x20 | $1; | |
1311 | $$.r5 = -1; | |
1312 | $$.ctl_reg = $1; | |
1313 | $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT; | |
1314 | hot_mreg = $1;} | |
1315 | | prog_ctl_reg | |
1316 | {$$.r6 = 0x38 | $1; | |
1317 | $$.r5 = -1; | |
1318 | $$.ctl_reg = 0x18 | $1; | |
1319 | $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;} | |
1320 | | A10 | |
1321 | {$$.lsd = 0; | |
1322 | $$.flags = R_LSD;} | |
1323 | | B10 | |
1324 | {$$.lsd = 1; | |
1325 | $$.flags = R_LSD;} | |
1326 | | XXXX | |
1327 | {$$.lsd = 2; | |
1328 | $$.flags = R_LSD;} | |
1329 | | YYYY | |
1330 | {$$.lsd = 3; | |
1331 | $$.flags = R_LSD;} | |
1332 | | AABB | |
1333 | {$$.lsd = 6; | |
1334 | $$.flags = R_LSD;} | |
1335 | | BBAA | |
1336 | {$$.lsd = 7; | |
1337 | $$.flags = R_LSD;} | |
1338 | ; | |
1339 | ||
1340 | prog_ctl_reg | |
1341 | : SR | |
1342 | {$$ = 1;} | |
1343 | | OMR | |
1344 | {$$ = 2;} | |
1345 | | SP | |
1346 | {$$ = 3;} | |
1347 | | SSH | |
1348 | {$$ = 4;} | |
1349 | | SSL | |
1350 | {$$ = 5;} | |
1351 | | LA | |
1352 | {$$ = 6;} | |
1353 | | LC | |
1354 | {$$ = 7;} | |
1355 | ; | |
1356 | ||
1357 | funky_ctl_reg | |
1358 | : MR | |
1359 | {$$ = 0;} | |
1360 | | CCR | |
1361 | {$$ = 1;} | |
1362 | | OMR | |
1363 | {$$ = 2;} | |
1364 | ; | |
1365 | ||
1366 | /*%%%************************* parallel moves *************/ | |
1367 | ||
1368 | parallel_move | |
1369 | : i_move | |
1370 | | u_move | |
1371 | | x_or_y_move | |
1372 | | xr_move | |
1373 | | ry_move | |
1374 | | r_move | |
1375 | | xy_move | |
1376 | | l_move | |
1377 | ; | |
1378 | ||
1379 | i_move : ix ',' regs | |
1380 | {int ival = n2int($1); | |
1381 | int frac = n2frac($1); | |
1382 | int value; | |
1383 | BOOL shortform = FALSE; | |
1384 | if($3.flags & R_CTL_REG) { | |
1385 | yyerror("please use MOVEC for control register moves"); | |
1386 | break; | |
1387 | } | |
1388 | if(($3.flags & R_SFRAC) && $1.type == FLT) { | |
1389 | if((frac & 0xFFFF) == 0 && | |
1390 | NOT long_symbolic_expr) { | |
1391 | value = frac >> 16; | |
1392 | shortform++; | |
1393 | } else { | |
1394 | value = frac; | |
1395 | } | |
1396 | } else { | |
1397 | if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) { | |
1398 | value = ival; | |
1399 | shortform++; | |
1400 | } else { | |
1401 | value = ival; | |
1402 | } | |
1403 | } | |
1404 | ||
1405 | if(shortform) { | |
1406 | w0 |= 0x200000 | (value & 0xFF) << 8 | | |
1407 | $3.r5 << 16; | |
1408 | } else { | |
1409 | w0 |= 0x400000 | 0x00F400 | | |
1410 | ($3.r5 >> 3 & 3) << 20 | | |
1411 | ($3.r5 & 7) << 16; | |
1412 | uses_w1++; w1 = value; | |
1413 | }} | |
1414 | ; | |
1415 | ||
1416 | r_move : regs ',' regs | |
1417 | { | |
1418 | if($3.flags & R_CTL_REG) { | |
1419 | yyerror("please use MOVEC for control register moves"); | |
1420 | break; | |
1421 | } | |
1422 | if($1.flags & R_R5 & $3.flags) | |
1423 | w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13; | |
1424 | else | |
1425 | yyerror("illegal R move"); | |
1426 | } | |
1427 | ; | |
1428 | ||
1429 | u_move : ea_short | |
1430 | {w0 |= 0x204000 | $1 << 8;} | |
1431 | ; | |
1432 | ||
1433 | x_or_y_move | |
1434 | : x_or_y ea ',' regs | |
1435 | {w0 |= 0x40C000 | $1 << 19; | |
1436 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
1437 | $1 == 1 && expr_seg != YDATA)) | |
1438 | yywarning("warning: space mismatch"); | |
1439 | if($4.flags & R_CTL_REG) { | |
1440 | yyerror("please use MOVEC for control register moves"); | |
1441 | break; | |
1442 | } | |
1443 | w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;} | |
1444 | | x_or_y abs_short_addr ',' regs | |
1445 | {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8; | |
1446 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
1447 | $1 == 1 && expr_seg != YDATA)) | |
1448 | yywarning("warning: space mismatch"); | |
1449 | if($4.flags & R_CTL_REG) { | |
1450 | yyerror("please use MOVEC for control register moves"); | |
1451 | break; | |
1452 | } | |
1453 | if($2 > 0x003F && pass == 2) | |
1454 | yywarning("warning: address operand truncated"); | |
1455 | w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;} | |
1456 | | regs ',' x_or_y ea | |
1457 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1458 | w0 |= 0x404000 | $3 << 19; | |
1459 | if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || | |
1460 | $3 == 1 && expr_seg != YDATA)) | |
1461 | yywarning("warning: space mismatch"); | |
1462 | if($1.flags & R_CTL_REG) { | |
1463 | yyerror("please use MOVEC for control register moves"); | |
1464 | break; | |
1465 | } | |
1466 | w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;} | |
1467 | | regs ',' x_or_y abs_short_addr | |
1468 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1469 | w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8; | |
1470 | if($1.flags & R_CTL_REG) { | |
1471 | yyerror("please use MOVEC for control register moves"); | |
1472 | break; | |
1473 | } | |
1474 | if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || | |
1475 | $3 == 1 && expr_seg != YDATA)) | |
1476 | yywarning("warning: space mismatch"); | |
1477 | if($4 > 0x003F && pass == 2) | |
1478 | yywarning("warning: address operand truncated"); | |
1479 | w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;} | |
1480 | | ix_long ',' regs | |
1481 | {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 | | |
1482 | ($3.r5 & 7) << 16; | |
1483 | if($3.flags & R_CTL_REG) { | |
1484 | yyerror("please use MOVEC for control register moves"); | |
1485 | break; | |
1486 | } | |
1487 | uses_w1++; w1 = n2frac($1); | |
1488 | } | |
1489 | ; | |
1490 | ||
1491 | xr_move | |
1492 | : x_or_y /* XMEM */ ea ',' regs regs /* a_b */ ',' YREG | |
1493 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1494 | if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || | |
1495 | $1 == 1 && expr_seg != YDATA)) | |
1496 | yywarning("warning: space mismatch"); | |
1497 | if($1 == 0 && $5.flags & R_AB) { | |
1498 | w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 | | |
1499 | $7 << 16; | |
1500 | } else { | |
1501 | yyerror("illegal X:R move"); | |
1502 | }} | |
1503 | | ix ',' regs regs /* a_b */ ',' YREG | |
1504 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1505 | if($4.flags & R_AB) { | |
1506 | w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 | | |
1507 | $6 << 16; | |
1508 | uses_w1++; | |
1509 | w1 |= n2frac($1) & 0xFFFFFF; | |
1510 | } else { | |
1511 | yyerror("illegal X:R move"); | |
1512 | }} | |
1513 | | regs ',' x_or_y /* XMEM */ ea regs /* a_b */ ',' regs/*YREG*/ | |
1514 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1515 | if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || | |
1516 | $3 == 1 && expr_seg != YDATA)) | |
1517 | yywarning("warning: space mismatch"); | |
1518 | if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB && | |
1519 | $7.flags & R_YREG) { | |
1520 | w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 | | |
1521 | $7.yreg << 16; | |
1522 | } else if($1.flags & R_AB && $3 == 0 && | |
1523 | $5.flags & R_XREG && $7.flags & R_AB) { | |
1524 | if($5.xreg != 0) yyerror("must use X0"); | |
1525 | if($1.ab == 0 && $7.ab == 0) | |
1526 | w0 |= 0x080000; | |
1527 | else if($1.ab == 1 && $7.ab == 1) | |
1528 | w0 |= 0x090000; | |
1529 | else | |
1530 | yyerror("illegal X:R move"); | |
1531 | } else { | |
1532 | yyerror("illegal X:R move"); | |
1533 | }} | |
1534 | ; | |
1535 | ||
1536 | ry_move : regs /* a_b */ ',' regs /* XREG */ YMEM ea ',' regs | |
1537 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1538 | if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) { | |
1539 | w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 | | |
1540 | $7.sdy << 16; | |
1541 | } else { | |
1542 | yyerror("illegal R:Y move"); | |
1543 | }} | |
1544 | | regs /* a_b */ ',' regs /* XREG */ ix ',' regs | |
1545 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1546 | if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) { | |
1547 | w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 | | |
1548 | $6.sdy << 16; | |
1549 | uses_w1++; | |
1550 | w1 |= n2frac($4) & 0xFFFFFF; | |
1551 | } else { | |
1552 | yyerror("illegal R:Y move"); | |
1553 | }} | |
1554 | | regs /* a_b */ ',' regs /* XREG */ regs ',' YMEM ea | |
1555 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1556 | if($1.flags & R_AB && $3.flags & R_XREG) { | |
1557 | w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 | | |
1558 | $4.sdy << 16; | |
1559 | } else if ($1.flags & R_YREG && $3.flags & R_AB && | |
1560 | $4.flags & R_AB) { | |
1561 | if($1.yreg != 0) yyerror("must use Y0"); | |
1562 | if($3.ab == 0 && $4.ab == 0) | |
1563 | w0 |= 0x088000; | |
1564 | else if($3.ab == 1 && $4.ab == 1) | |
1565 | w0 |= 0x098000; | |
1566 | else | |
1567 | yyerror("illegal R:Y move"); | |
1568 | } else { | |
1569 | yyerror("illegal R:Y move"); | |
1570 | }} | |
1571 | ; | |
1572 | ||
1573 | l_move | |
1574 | : LMEM ea ',' regs /* lsd */ | |
1575 | {if($4.flags & R_CTL_REG) { | |
1576 | yyerror("please use MOVEC for control register moves"); | |
1577 | break; | |
1578 | } | |
1579 | w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;} | |
1580 | | regs /* lsd */ ',' LMEM ea | |
1581 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1582 | if($1.flags & R_CTL_REG) { | |
1583 | yyerror("please use MOVEC for control register moves"); | |
1584 | break; | |
1585 | } | |
1586 | w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;} | |
1587 | | LMEM abs_short_addr ',' regs /* lsd */ | |
1588 | {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19; | |
1589 | if($4.flags & R_CTL_REG) { | |
1590 | yyerror("please use MOVEC for control register moves"); | |
1591 | break; | |
1592 | } | |
1593 | if($2 > 0x003F && pass == 2) | |
1594 | yywarning("warning: address operand truncated"); | |
1595 | w0 |= ($2 & 0x3F) << 8;} | |
1596 | | regs /* lsd */ ',' LMEM abs_short_addr | |
1597 | {hot_rreg = hot_nreg = hot_mreg = -1; | |
1598 | w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19; | |
1599 | if($1.flags & R_CTL_REG) { | |
1600 | yyerror("please use MOVEC for control register moves"); | |
1601 | break; | |
1602 | } | |
1603 | if($4 > 0x003F && pass == 2) | |
1604 | yywarning("warning: address operand truncated"); | |
1605 | w0 |= ($4 & 0x3F) << 8;} | |
1606 | ; | |
1607 | ||
1608 | xy_move | |
1609 | : x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs YMEM ea /*ea_strange*/ ',' regs | |
1610 | {int eax = $2, eay = $6, | |
1611 | regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg, | |
1612 | regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg; | |
1613 | hot_rreg = hot_nreg = hot_mreg = -1; | |
1614 | if((eax & 0x400) == (eay & 0x400)) | |
1615 | yyerror("registers must be in opposite halves"); | |
1616 | if(!($4.flags & (R_AB | R_XREG))) | |
1617 | yyerror("invalid X move register"); | |
1618 | if(!($8.flags & (R_AB | R_YREG))) | |
1619 | yyerror("invalid Y move register"); | |
1620 | if($4.flags & R_AB && | |
1621 | $8.flags & R_AB && | |
1622 | $4.ab == $8.ab) | |
1623 | yyerror("duplicate destination register"); | |
1624 | w0 = w0 & 0xFF | 0xC08000; /* both write */ | |
1625 | w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} | |
1626 | | x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs regs ',' YMEM ea /*ea_strange*/ | |
1627 | {int eax = $2, eay = $8, | |
1628 | regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg, | |
1629 | regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg; | |
1630 | hot_rreg = hot_nreg = hot_mreg = -1; | |
1631 | if((eax & 0x400) == (eay & 0x400)) | |
1632 | yyerror("registers must be in opposite halves"); | |
1633 | if(!($4.flags & (R_AB | R_XREG))) | |
1634 | yyerror("invalid X move register"); | |
1635 | if(!($5.flags & (R_AB | R_YREG))) | |
1636 | yyerror("invalid Y move register"); | |
1637 | w0 = w0 & 0xFF | 0x808000; /* X:write, Y:read */ | |
1638 | w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} | |
1639 | | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ YMEM ea /*ea_strange*/ ',' regs | |
1640 | {int eax = $4, eay = $6, | |
1641 | regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg, | |
1642 | regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg; | |
1643 | hot_rreg = hot_nreg = hot_mreg = -1; | |
1644 | if((eax & 0x400) == (eay & 0x400)) | |
1645 | yyerror("registers must be in opposite halves"); | |
1646 | if(!($1.flags & (R_AB | R_XREG))) | |
1647 | yyerror("invalid X move register"); | |
1648 | if(!($8.flags & (R_AB | R_YREG))) | |
1649 | yyerror("invalid Y move register"); | |
1650 | w0 = w0 & 0xFF | 0xC00000; /* X:read, Y:write */ | |
1651 | w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} | |
1652 | | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ regs ',' YMEM ea /*ea_strange*/ | |
1653 | {int eax = $4, eay = $8, | |
1654 | regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg, | |
1655 | regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg; | |
1656 | hot_rreg = hot_nreg = hot_mreg = -1; | |
1657 | if((eax & 0x400) == (eay & 0x400)) | |
1658 | yyerror("registers must be in opposite halves"); | |
1659 | if(!($1.flags & (R_AB | R_XREG))) | |
1660 | yyerror("invalid X move register"); | |
1661 | if(!($5.flags & (R_AB | R_YREG))) | |
1662 | yyerror("invalid Y move register"); | |
1663 | w0 = w0 & 0xFF | 0x800000; /* both read */ | |
1664 | w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} | |
1665 | ; | |
1666 | ||
1667 | /*%%%******* absolute address and immediate data fields ************/ | |
1668 | ||
1669 | num : CHEX | |
1670 | {$$ = $1;} | |
1671 | | CDEC | |
1672 | {$$ = $1;} | |
1673 | | FRAC | |
1674 | {$$ = $1;} | |
1675 | ; | |
1676 | ||
1677 | ix : '#' expr | |
1678 | {$$ = $2; expr_seg = ANY;} | |
1679 | | '#' '<' expr | |
1680 | {$$.val.i = n2int($3) & 0xFF; | |
1681 | $$.type = INT; | |
1682 | expr_seg = ANY; | |
1683 | long_symbolic_expr = FALSE;} | |
1684 | ; | |
1685 | ||
1686 | ix_long : '#' '>' expr | |
1687 | {$$ = $3; expr_seg = ANY;} | |
1688 | ; | |
1689 | ||
1690 | abs_addr | |
1691 | : expr | |
1692 | {$$ = n2int($1); | |
1693 | expr_seg = $1.seg;} | |
1694 | ; | |
1695 | ||
1696 | abs_short_addr | |
1697 | : '<' expr | |
1698 | {$$ = n2int($2); | |
1699 | expr_seg = $2.seg;} | |
1700 | ; | |
1701 | ||
1702 | io_short_addr | |
1703 | : SHL expr | |
1704 | {$$ = n2int($2); | |
1705 | expr_seg = $2.seg;} | |
1706 | ; | |
1707 | ||
1708 | num_or_sym | |
1709 | : num | |
1710 | {$$ = $1;} | |
1711 | | SYM | |
1712 | {$$ = sym_ref($1); free($1);} | |
1713 | | io_short_addr | |
1714 | {$$.type = INT; $$.val.i = $1; $$.seg = expr_seg;} | |
1715 | ; | |
1716 | ||
1717 | num_or_sym_expr | |
1718 | : num | |
1719 | {$$ = $1; expr_seg = $1.seg;} | |
1720 | | SYM | |
1721 | {$$ = sym_ref($1); | |
1722 | free($1); | |
1723 | long_symbolic_expr++; | |
1724 | expr_seg = $$.seg; | |
1725 | } | |
1726 | | CHAR | |
1727 | {$$.type = INT; $$.val.i = $1 & 0xFFFFFF; expr_seg = $$.seg = ANY;} | |
1728 | | '*' | |
1729 | {$$.type = INT; $$.val.i = pc; expr_seg = $$.seg = ANY;} | |
1730 | | OP_PI | |
1731 | {$$.type = FLT; $$.val.f = acos(-1.0); expr_seg = $$.seg = ANY;} | |
1732 | ; | |
1733 | ||
1734 | expr | |
1735 | : OP_INT '(' expr ')' | |
1736 | {$$.type = INT; | |
1737 | if($3.type == INT) | |
1738 | $$.val.i = $3.val.i; | |
1739 | else | |
1740 | $$.val.i = $3.val.f; | |
1741 | $$.seg = $3.seg; | |
1742 | } | |
1743 | | expr '|' expr | |
1744 | {$$ = binary_op($1, '|', $3);} | |
1745 | | expr '^' expr | |
1746 | {$$ = binary_op($1, '^', $3);} | |
1747 | | expr '&' expr | |
1748 | {$$ = binary_op($1, '&', $3);} | |
1749 | | expr SHR expr | |
1750 | {$$ = binary_op($1, SHR, $3);} | |
1751 | | expr SHL expr | |
1752 | {$$ = binary_op($1, SHL, $3);} | |
1753 | | expr '-' expr | |
1754 | {$$ = binary_op($1, '-', $3);} | |
1755 | | expr '+' expr | |
1756 | {$$ = binary_op($1, '+', $3);} | |
1757 | | expr '%' expr | |
1758 | {$$ = binary_op($1, '%', $3);} | |
1759 | | expr '/' expr | |
1760 | {$$ = binary_op($1, '/', $3);} | |
1761 | | expr '*' expr | |
1762 | {$$ = binary_op($1, '*', $3);} | |
1763 | | '-' expr %prec '~' | |
1764 | {$$ = unary_op('-', $2);} | |
1765 | | '~' expr | |
1766 | {$$ = unary_op('~', $2);} | |
1767 | | OP_SIN '(' expr ')' | |
1768 | {$$ = unary_op('s', $3);} | |
1769 | | OP_COS '(' expr ')' | |
1770 | {$$ = unary_op('c', $3);} | |
1771 | | OP_TAN '(' expr ')' | |
1772 | {$$ = unary_op('t', $3);} | |
1773 | | OP_ASIN '(' expr ')' | |
1774 | {$$ = unary_op('S', $3);} | |
1775 | | OP_ACOS '(' expr ')' | |
1776 | {$$ = unary_op('C', $3);} | |
1777 | | OP_ATAN '(' expr ')' | |
1778 | {$$ = unary_op('T', $3);} | |
1779 | | OP_EXP '(' expr ')' | |
1780 | {$$ = unary_op('e', $3);} | |
1781 | | OP_LN '(' expr ')' | |
1782 | {$$ = unary_op('l', $3);} | |
1783 | | OP_LOG '(' expr ')' | |
1784 | {$$ = unary_op('L', $3);} | |
1785 | | OP_ABS '(' expr ')' | |
1786 | {$$ = unary_op('a', $3);} | |
1787 | | OP_POW '(' expr ',' expr ')' | |
1788 | {$$ = binary_op($3, 'p', $5);} | |
1789 | | '(' expr ')' | |
1790 | {$$ = $2;} | |
1791 | | num_or_sym_expr | |
1792 | {$$ = $1;} | |
1793 | ; | |
1794 | ||
1795 | /*%%%****************** end ******************************/ | |
1796 | ||
1797 | %% | |
1798 | ||
1799 | #include <stdio.h> | |
1800 | #include <setjmp.h> | |
1801 | #include <sys/signal.h> | |
1802 | ||
1803 | int yydebug; | |
1804 | ||
1805 | struct n binary_op(a1, op, a2) | |
1806 | struct n a1, a2; | |
1807 | int op; | |
1808 | { | |
1809 | struct n result; | |
1810 | int iarg1, iarg2; | |
1811 | double farg1, farg2; | |
1812 | ||
1813 | if(a1.type == UNDEF || a2.type == UNDEF) { | |
1814 | result.type = UNDEF; | |
1815 | return result; | |
1816 | } | |
1817 | ||
1818 | iarg1 = a1.type == INT ? a1.val.i : a1.val.f; | |
1819 | iarg2 = a2.type == INT ? a2.val.i : a2.val.f; | |
1820 | ||
1821 | farg1 = a1.type == INT ? a1.val.i : a1.val.f; | |
1822 | farg2 = a2.type == INT ? a2.val.i : a2.val.f; | |
1823 | ||
1824 | /* figure out target segment */ | |
1825 | ||
1826 | if(a1.seg == a2.seg) | |
1827 | result.seg = a1.seg; | |
1828 | else if(a1.seg == ANY) | |
1829 | result.seg = a2.seg; | |
1830 | else if(a2.seg == ANY) | |
1831 | result.seg = a1.seg; | |
1832 | else | |
1833 | result.seg = NONE; | |
1834 | ||
1835 | /* promote to float automatically */ | |
1836 | ||
1837 | if(a1.type != a2.type) { | |
1838 | if(a1.type == INT) { | |
1839 | a1.val.f = a1.val.i; /* truncate */ | |
1840 | a1.type = FLT; | |
1841 | } else { | |
1842 | a2.val.f = a2.val.i; /* truncate */ | |
1843 | } | |
1844 | } | |
1845 | result.type = a1.type; | |
1846 | ||
1847 | /* do the op */ | |
1848 | ||
1849 | switch(op) { | |
1850 | case '+': | |
1851 | if(result.type == INT) result.val.i = a1.val.i + a2.val.i; | |
1852 | else result.val.f = a1.val.f + a2.val.f; | |
1853 | break; | |
1854 | case '-': | |
1855 | if(result.type == INT) result.val.i = a1.val.i - a2.val.i; | |
1856 | else result.val.f = a1.val.f - a2.val.f; | |
1857 | break; | |
1858 | case '*': | |
1859 | if(result.type == INT) result.val.i = a1.val.i * a2.val.i; | |
1860 | else result.val.f = a1.val.f * a2.val.f; | |
1861 | break; | |
1862 | case '/': | |
1863 | if(result.type == INT) result.val.i = a1.val.i / a2.val.i; | |
1864 | else result.val.f = a1.val.f / a2.val.f; | |
1865 | break; | |
1866 | case '%': | |
1867 | result.val.i = iarg1 % iarg2; | |
1868 | result.type = INT; | |
1869 | break; | |
1870 | case SHL: | |
1871 | result.val.i = iarg1 << iarg2; | |
1872 | result.type = INT; | |
1873 | break; | |
1874 | case SHR: | |
1875 | result.val.i = iarg1 >> iarg2; | |
1876 | result.type = INT; | |
1877 | break; | |
1878 | case '|': | |
1879 | result.val.i = iarg1 | iarg2; | |
1880 | result.type = INT; | |
1881 | break; | |
1882 | case '&': | |
1883 | result.val.i = iarg1 & iarg2; | |
1884 | result.type = INT; | |
1885 | break; | |
1886 | case '^': | |
1887 | result.val.i = iarg1 ^ iarg2; | |
1888 | result.type = INT; | |
1889 | break; | |
1890 | case 'p': | |
1891 | result.val.f = pow(farg1, farg2); | |
1892 | result.type = FLT; | |
1893 | } | |
1894 | ||
1895 | return result; | |
1896 | } | |
1897 | ||
1898 | jmp_buf unary_env; | |
1899 | ||
1900 | void | |
1901 | sigfpu() | |
1902 | { | |
1903 | longjmp(unary_env, 1); | |
1904 | } | |
1905 | ||
1906 | char *unary_name(op) | |
1907 | { | |
1908 | switch(op) { | |
1909 | case 's': return "sin"; | |
1910 | case 'c': return "cos"; | |
1911 | case 't': return "tan"; | |
1912 | case 'S': return "asin"; | |
1913 | case 'C': return "acos"; | |
1914 | case 'T': return "atan"; | |
1915 | case 'e': return "exp"; | |
1916 | case 'l': return "ln"; | |
1917 | case 'L': return "log"; | |
1918 | case 'a': return "abs"; | |
1919 | } | |
1920 | } | |
1921 | ||
1922 | struct n unary_op(op, a1) | |
1923 | int op; | |
1924 | struct n a1; | |
1925 | { | |
1926 | struct n result; | |
1927 | void (*orig)(); | |
1928 | double farg; | |
1929 | ||
1930 | if(a1.type == UNDEF) { | |
1931 | result.type = UNDEF; | |
1932 | return result; | |
1933 | } | |
1934 | ||
1935 | result.seg = a1.seg; | |
1936 | ||
1937 | /* do the op */ | |
1938 | ||
1939 | orig = signal(SIGFPE, sigfpu); | |
1940 | if(setjmp(unary_env)) { | |
1941 | yyerror("floating point exception in function %s", unary_name(op)); | |
1942 | result.val.i = result.val.f = 0; | |
1943 | } else { | |
1944 | farg = a1.type == INT ? (double)a1.val.i : a1.val.f; | |
1945 | switch(op) { | |
1946 | case '-': | |
1947 | result.type = a1.type; | |
1948 | if(a1.type == INT) result.val.i = -a1.val.i; | |
1949 | else result.val.f = -a1.val.f; | |
1950 | break; | |
1951 | case '~': | |
1952 | result.type = a1.type; | |
1953 | if(a1.type == INT) result.val.i = ~a1.val.i; | |
1954 | else result.val.f = ~(int)a1.val.f; | |
1955 | break; | |
1956 | case 'a': | |
1957 | result.type = a1.type; | |
1958 | if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i; | |
1959 | else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f; | |
1960 | break; | |
1961 | case 's': | |
1962 | result.type = FLT; | |
1963 | result.val.f = sin(farg); | |
1964 | break; | |
1965 | case 'c': | |
1966 | result.type = FLT; | |
1967 | result.val.f = cos(farg); | |
1968 | break; | |
1969 | case 't': | |
1970 | result.type = FLT; | |
1971 | result.val.f = tan(farg); | |
1972 | break; | |
1973 | case 'S': | |
1974 | result.type = FLT; | |
1975 | result.val.f = asin(farg); | |
1976 | break; | |
1977 | case 'C': | |
1978 | result.type = FLT; | |
1979 | result.val.f = acos(farg); | |
1980 | break; | |
1981 | case 'T': | |
1982 | result.type = FLT; | |
1983 | result.val.f = atan(farg); | |
1984 | break; | |
1985 | case 'e': | |
1986 | result.type = FLT; | |
1987 | result.val.f = exp(farg); | |
1988 | break; | |
1989 | case 'l': | |
1990 | result.type = FLT; | |
1991 | result.val.f = log(farg); | |
1992 | break; | |
1993 | case 'L': | |
1994 | result.type = FLT; | |
1995 | result.val.f = log10(farg); | |
1996 | break; | |
1997 | } | |
1998 | } | |
1999 | signal(SIGFPE, orig); | |
2000 | ||
2001 | return result; | |
2002 | } | |
2003 | ||
2004 | n2int(n) | |
2005 | struct n n; | |
2006 | { | |
2007 | if(n.type == UNDEF) | |
2008 | return UNDEF; | |
2009 | else if(n.type == INT) | |
2010 | return n.val.i; | |
2011 | else | |
2012 | return n.val.f; | |
2013 | } | |
2014 | ||
2015 | n2frac(n) | |
2016 | struct n n; | |
2017 | { | |
2018 | double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f; | |
2019 | ||
2020 | if(n.type == UNDEF) | |
2021 | return UNDEF; | |
2022 | else if(n.type == INT) | |
2023 | return n.val.i; | |
2024 | else if(n.val.f == -1.0) | |
2025 | return 0x800000; | |
2026 | ||
2027 | adval -= (double)(int)adval; | |
2028 | adval *= (double)0x800000; | |
2029 | adval += 0.5; | |
2030 | ||
2031 | if(n.val.f >= 0.0) | |
2032 | return adval; | |
2033 | else | |
2034 | return -adval; | |
2035 | } | |
2036 | ||
2037 | extern struct {int n; char *name;} tok_tab[]; | |
2038 | extern int n_tok; | |
2039 | ||
2040 | char *tok_print(tok) | |
2041 | int tok; | |
2042 | { | |
2043 | int i; | |
2044 | static char buf[32]; | |
2045 | ||
2046 | if(tok == '1') { | |
2047 | i = 1; | |
2048 | } | |
2049 | ||
2050 | if(tok < 256) { | |
2051 | sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF); | |
2052 | return buf; | |
2053 | } else { | |
2054 | for(i = 0; i < n_tok; i++) { | |
2055 | if(tok == tok_tab[i].n) | |
2056 | return tok_tab[i].name; | |
2057 | } | |
2058 | } | |
2059 | return "*bogus*"; | |
2060 | } | |
2061 | ||
2062 | yyerror(s, a0, a1, a2, a3) | |
2063 | char *s, *a0, *a1, *a2, *a3; | |
2064 | { | |
2065 | extern int error; | |
2066 | char buf[1024]; | |
2067 | ||
2068 | error++; | |
2069 | sprintf(buf, s, a0, a1, a2, a3); | |
2070 | ||
2071 | if(pass == 2) { | |
2072 | fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, | |
2073 | buf, tok_print(yychar)); | |
2074 | fprintf(stderr, "%s\n", cur_line); | |
2075 | printf("%s: line %d: %s (tok=%s)\n", curfile, curline, | |
2076 | buf, tok_print(yychar)); | |
2077 | } | |
2078 | } | |
2079 | ||
2080 | yywarning(s, a0, a1, a2, a3) | |
2081 | char *s, *a0, *a1, *a2, *a3; | |
2082 | { | |
2083 | extern int warning; | |
2084 | char buf[1024]; | |
2085 | ||
2086 | warning++; | |
2087 | sprintf(buf, s, a0, a1, a2, a3); | |
2088 | ||
2089 | if(pass == 2) { | |
2090 | fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, | |
2091 | buf, tok_print(yychar)); | |
2092 | fprintf(stderr, "%s\n", cur_line); | |
2093 | printf("%s: line %d: %s (tok=%s)\n", curfile, curline, | |
2094 | buf, tok_print(yychar)); | |
2095 | } | |
2096 | } | |
2097 | ||
2098 | char *luntab(s) | |
2099 | char *s; | |
2100 | { | |
2101 | static char buf[1024]; | |
2102 | int p; | |
2103 | ||
2104 | strcpy(buf, s); | |
2105 | ||
2106 | untab(buf); | |
2107 | p = strlen(buf); | |
2108 | ||
2109 | if(buf[p - 1] == '\n') | |
2110 | buf[p - 1] = '\0'; | |
2111 | ||
2112 | return buf; | |
2113 | } |
0 | #if 0 | |
1 | +----------------------------------------------------------------------+ | |
2 | | Question: My filter design package gives me decimal fractional | | |
3 | | numbers as output for my FIR filter coefficients. | | |
4 | | How do I convert these decimal fractions into the | | |
5 | | DSP56200's format? | | |
6 | +----------------------------------------------------------------------+ | |
7 | ||
8 | Answer: | |
9 | It's fairly easy to convert decimal fractions into the | |
10 | data format required by the DSP56200. The DSP56200 coeffi- | |
11 | cients are represented as 24-bit signed, fractional, 2's | |
12 | complement numbers as shown in Table 1. | |
13 | ||
14 | TABLE 1 - Representations for FIR Filter Coefficients | |
15 | ----------------------------------------------------- | |
16 | ||
17 | Decimal Hexadecimal | |
18 | Fraction 24-Bit Binary Value Coefficient | |
19 | -------- ------------------- ---------- | |
20 | ||
21 | 0.75 0.1100000 00000000 00000000 60 00 00 | |
22 | 0.5 0.1000000 00000000 00000000 40 00 00 | |
23 | 0.25 0.0100000 00000000 00000000 20 00 00 | |
24 | 0.125 0.0010000 00000000 00000000 10 00 00 | |
25 | -0.125 1.1110000 00000000 00000000 F0 00 00 | |
26 | -0.75 1.0100000 00000000 00000000 A0 00 00 | |
27 | ||
28 | Each 24-bit coefficient is separated into three bytes | |
29 | corresponding to the high, middle, and low bytes. The high | |
30 | byte is written to the DSP56200 at address 0A (hex), the | |
31 | middle byte to address 0B (hex), and the low byte to address | |
32 | 0C (hex). | |
33 | ||
34 | Conversion Procedure: | |
35 | ||
36 | Step 1: Multiply the decimal fraction by 8388608.0 (decimal). | |
37 | Note that 8388608 = 2 raised to the 23rd power. | |
38 | Step 2: Truncate or round the result into an integer. | |
39 | Step 3: Logically AND this integer with 00FFFFFF (hex). | |
40 | Step 4: Write the result to an output file as a hex integer. | |
41 | ||
42 | It is easy to write a program to perform this conversion on | |
43 | a set of coefficients. If done by computer program, make | |
44 | sure that all integer variables are represented with at | |
45 | least 24-bits. An example of a short "C" program is | |
46 | included at the end of this answer. | |
47 | ||
48 | Things to watch for: | |
49 | ||
50 | (1) Avoid letting a coefficient value be exactly 800000 | |
51 | (-1.0 in a fractional system). If this coefficient | |
52 | is multiplied by a data sample with value -1.0, the | |
53 | result is -1.0 instead of +1.0 as expected. This is | |
54 | because +1.0 cannot be represented in a signed, 2's | |
55 | complement, fractional system. | |
56 | ||
57 | (2) The filter coefficients must be carefully selected | |
58 | to prevent overflow. If there is a possibility of | |
59 | overflow with a set of filter coefficients, then all | |
60 | coefficients must be scaled by a constant value. The | |
61 | DSP56200's 24-bit coefficients allow plenty of room | |
62 | for scaling. If 12-bit input data samples are used | |
63 | in a system, the potential for overflow is greatly | |
64 | reduced if the samples are right justified and sign- | |
65 | extended four bits before they are sent to the | |
66 | DSP56200. | |
67 | ||
68 | "C" Program: | |
69 | #endif | |
70 | /****************************************\ | |
71 | ** DECIMAL FRACTION TO HEX CONVERSION ** | |
72 | \****************************************/ | |
73 | ||
74 | /******************************************************************\ | |
75 | * This program converts one decimal, fractional number to a hex * | |
76 | * number which can be written to the DSP56200's Coefficient RAM * | |
77 | * Access registers. It prompts the user for a decimal fraction * | |
78 | * and returns the corresponding hex number. * | |
79 | * * | |
80 | * Examples of Program Results (useful for checking programs) * | |
81 | * Inputs Outputs * | |
82 | * ------ ------- * | |
83 | * 0.750 => 600000 * | |
84 | * 0.500 => 400000 * | |
85 | * 0.250 => 200000 * | |
86 | * 0.125 => 100000 * | |
87 | * -0.125 => f00000 * | |
88 | * -0.750 => a00000 * | |
89 | * 0.00784313678741455 => 010101 * | |
90 | * -0.00784313678741455 => fefeff * | |
91 | * * | |
92 | * Note: The program assumes that the variable type "long" is an * | |
93 | * integer which is at least 24-bits wide. * | |
94 | * * | |
95 | * Also: The DSP56200 cannot use any coefficient value with a * | |
96 | * magnitude of 1.0 or larger. All coefficients must be * | |
97 | * signed, fractional quantities. * | |
98 | \******************************************************************/ | |
99 | ||
100 | main() | |
101 | { | |
102 | double fractnum; /* double precision floating pt */ | |
103 | long hexval; /* long integer */ | |
104 | ||
105 | for(;;) { | |
106 | /* Read 1 Decimal Floating Point Number from the Keyboard */ | |
107 | printf("Enter the decimal fraction: "); | |
108 | scanf("%lf", &fractnum); | |
109 | ||
110 | /* Convert to a Hex Integer which can be used by the DSP56200 */ | |
111 | hexval = (long) (8388608.0 * fractnum); | |
112 | hexval = 0x00ffffffL & hexval; | |
113 | ||
114 | /* Write the Hex number out to the Terminal */ | |
115 | printf("DSP56200 Coefficient = %06lx\n", hexval); | |
116 | } | |
117 | } |
0 | /* | |
1 | I got this off net.sources from Henry Spencer. | |
2 | It is a public domain getopt(3) like in System V. | |
3 | I have made the following modifications: | |
4 | ||
5 | index(s,c) was added because too many people could | |
6 | not compile getopt without it. | |
7 | ||
8 | A test main program was added, ifdeffed by GETOPT. | |
9 | This main program is a public domain implementation | |
10 | of the getopt(1) program like in System V. The getopt | |
11 | program can be used to standardize shell option handling. | |
12 | e.g. cc -DGETOPT getopt.c -o getopt | |
13 | */ | |
14 | #include <stdio.h> | |
15 | ||
16 | #ifndef lint | |
17 | static char sccsfid[] = "@(#) getopt.c 5.0 (UTZoo) 1985"; | |
18 | #endif | |
19 | ||
20 | #define ARGCH (int)':' | |
21 | #define BADCH (int)'?' | |
22 | #define EMSG "" | |
23 | #define ENDARGS "--" | |
24 | ||
25 | /* this is included because index is not on some UNIX systems */ | |
26 | static | |
27 | char * | |
28 | index (s, c) | |
29 | register char *s; | |
30 | register int c; | |
31 | { | |
32 | while (*s) | |
33 | if (c == *s) return (s); | |
34 | else s++; | |
35 | return (NULL); | |
36 | } | |
37 | ||
38 | /* | |
39 | * get option letter from argument vector | |
40 | */ | |
41 | int opterr = 1, /* useless, never set or used */ | |
42 | optind = 1, /* index into parent argv vector */ | |
43 | optopt; /* character checked for validity */ | |
44 | char *optarg; /* argument associated with option */ | |
45 | ||
46 | #define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \ | |
47 | fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); | |
48 | ||
49 | ||
50 | getopt(nargc,nargv,ostr) | |
51 | int nargc; | |
52 | char **nargv, | |
53 | *ostr; | |
54 | { | |
55 | static char *place = EMSG; /* option letter processing */ | |
56 | register char *oli; /* option letter list index */ | |
57 | char *index(); | |
58 | ||
59 | if(!*place) { /* update scanning pointer */ | |
60 | if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF); | |
61 | if (*place == '-') { /* found "--" */ | |
62 | ++optind; | |
63 | return(EOF); | |
64 | } | |
65 | } /* option letter okay? */ | |
66 | if ((optopt = (int)*place++) == ARGCH || !(oli = index(ostr,optopt))) { | |
67 | if(!*place) ++optind; | |
68 | tell(": illegal option -- "); | |
69 | } | |
70 | if (*++oli != ARGCH) { /* don't need argument */ | |
71 | optarg = NULL; | |
72 | if (!*place) ++optind; | |
73 | } | |
74 | else { /* need an argument */ | |
75 | if (*place) optarg = place; /* no white space */ | |
76 | else if (nargc <= ++optind) { /* no arg */ | |
77 | place = EMSG; | |
78 | tell(": option requires an argument -- "); | |
79 | } | |
80 | else optarg = nargv[optind]; /* white space */ | |
81 | place = EMSG; | |
82 | ++optind; | |
83 | } | |
84 | return(optopt); /* dump back option letter */ | |
85 | } | |
86 | ||
87 | ||
88 | #ifdef GETOPT | |
89 | ||
90 | #ifndef lint | |
91 | static char sccspid[] = "@(#) getopt.c 5.1 (WangInst) 6/15/85"; | |
92 | #endif | |
93 | ||
94 | main (argc, argv) char **argv; | |
95 | { | |
96 | char *optstring = argv[1]; | |
97 | char *argv0 = argv[0]; | |
98 | extern int optind; | |
99 | extern char *optarg; | |
100 | int opterr = 0; | |
101 | int C; | |
102 | char *opi; | |
103 | if (argc == 1) | |
104 | { | |
105 | fprintf (stderr, "Usage: %s optstring args\n", argv0); | |
106 | exit (1); | |
107 | } | |
108 | argv++; | |
109 | argc--; | |
110 | argv[0] = argv0; | |
111 | while ((C = getopt (argc, argv, optstring)) != EOF) | |
112 | { | |
113 | if (C == BADCH) opterr++; | |
114 | printf ("-%c ", C); | |
115 | opi = index (optstring, C); | |
116 | if (opi && opi[1] == ARGCH) | |
117 | if (optarg) | |
118 | printf ("\"%s\" ", optarg); | |
119 | else opterr++; | |
120 | } | |
121 | printf ("%s", ENDARGS); | |
122 | while (optind < argc) | |
123 | printf (" \"%s\"", argv[optind++]); | |
124 | putchar ('\n'); | |
125 | exit (opterr); | |
126 | } | |
127 | ||
128 | #endif |
0 | /* | |
1 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
2 | * | |
3 | * Permission to use, copy, modify, distribute, and sell this software | |
4 | * and its documentation for any purpose is hereby granted without fee, | |
5 | * provided that the above copyright notice appear in all copies and | |
6 | * that both that copyright notice and this permission notice appear | |
7 | * in supporting documentation. The author makes no representations | |
8 | * about the suitability of this software for any purpose. It is | |
9 | * provided "as is" without express or implied warranty. | |
10 | * | |
11 | */ | |
12 | static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; | |
13 | ||
14 | /* | |
15 | * keybld - builds a finite-state parser for the given keyword list | |
16 | * | |
17 | */ | |
18 | ||
19 | #include <stdio.h> | |
20 | #include "a56.h" | |
21 | ||
22 | char buf[1024]; | |
23 | ||
24 | main() | |
25 | { | |
26 | int line = 0; | |
27 | ||
28 | while(gets(buf)) { | |
29 | char *bp = buf; | |
30 | line++; | |
31 | while(*bp != '\t' && *bp != ' ') bp++; | |
32 | *bp++ = '\0'; | |
33 | while(*bp == '\t' || *bp == ' ') bp++; | |
34 | if(strcmp(buf, ".code") == 0) { | |
35 | printf("%s\n", bp); | |
36 | } else if(add_tok(buf, bp) == -1) { | |
37 | fprintf(stderr, "input line %d: ambiguous\n", line); | |
38 | } | |
39 | } | |
40 | ||
41 | dump_machine(); | |
42 | return 0; | |
43 | } | |
44 | ||
45 | #define MAX_CHAR 'z' | |
46 | ||
47 | #define TRANSITIONS (MAX_CHAR + 1) | |
48 | ||
49 | struct state { | |
50 | int number; | |
51 | char *seen; | |
52 | struct trans { | |
53 | char action; | |
54 | void *arg; | |
55 | } trans[TRANSITIONS]; | |
56 | struct state *next; | |
57 | } empty_state, *stop = NULL, *scur = NULL, *new_state(); | |
58 | int n_states = 0; | |
59 | ||
60 | /* actions */ | |
61 | #define NOMATCH 0 /* argument is nothing */ | |
62 | #define GOTO 1 /* argument is target state */ | |
63 | #define TERMINAL 2 /* argument is which user action to perform */ | |
64 | ||
65 | struct user_action { | |
66 | char *action; | |
67 | struct user_action *next; | |
68 | } *utop = NULL, *ucur = NULL; | |
69 | int n_user_actions = 0; | |
70 | ||
71 | add_tok(tok, actions) | |
72 | char *tok, *actions; | |
73 | { | |
74 | struct state *scur; | |
75 | struct user_action *unew = (struct user_action *)alloc(sizeof *unew); | |
76 | unew->action = strsave(actions); | |
77 | unew->next = NULL; | |
78 | if(ucur) | |
79 | ucur->next = unew; | |
80 | ucur = unew; | |
81 | if(utop == NULL) | |
82 | utop = unew; | |
83 | ||
84 | if(stop == NULL) | |
85 | new_state(NULL); | |
86 | ||
87 | if(follow(*tok, tok + 1, stop) == -1) | |
88 | return -1; | |
89 | ||
90 | n_user_actions++; | |
91 | return 0; | |
92 | } | |
93 | ||
94 | follow(c, tp, sp) | |
95 | char c; | |
96 | char *tp; | |
97 | struct state *sp; | |
98 | { | |
99 | struct trans *arcp, *arcup; | |
100 | ||
101 | if(c >= 'a' && c <= 'z') { | |
102 | c -= 'a' - 'A'; | |
103 | } | |
104 | arcp = sp->trans + c; | |
105 | ||
106 | if(c >= 'A' && c <= 'Z') { | |
107 | arcup = sp->trans + c + 'a' - 'A'; | |
108 | } else { | |
109 | arcup = arcp; | |
110 | } | |
111 | ||
112 | if(c == '\0') { | |
113 | if(arcp->action == TERMINAL) { | |
114 | return -1; | |
115 | } else { | |
116 | arcp->action = arcup->action = TERMINAL; | |
117 | arcp->arg = arcup->arg = (void *)n_user_actions; | |
118 | return 0; | |
119 | } | |
120 | } else { | |
121 | if(arcp->action == GOTO) { | |
122 | return follow(*tp, tp + 1, arcp->arg); | |
123 | } else { | |
124 | struct state *new = new_state(tp); | |
125 | arcp->action = arcup->action = GOTO; | |
126 | arcp->arg = arcup->arg = (void *)new; | |
127 | return follow(*tp, tp + 1, new); | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
132 | struct state *new_state(tp) | |
133 | char *tp; | |
134 | { | |
135 | struct state *snew = (struct state *)alloc(sizeof *snew); | |
136 | char tmp[1024]; | |
137 | ||
138 | *snew = empty_state; | |
139 | ||
140 | snew->number = n_states++; | |
141 | ||
142 | snew->next = NULL; | |
143 | ||
144 | if(scur) | |
145 | scur->next = snew; | |
146 | scur = snew; | |
147 | ||
148 | if(stop == NULL) | |
149 | stop = snew; | |
150 | ||
151 | if(tp) { | |
152 | strncpy(tmp, buf, tp - buf); | |
153 | tmp[tp - buf] = '\0'; | |
154 | } else | |
155 | strcpy(tmp, "<nothing>"); | |
156 | ||
157 | snew->seen = strsave(tmp); | |
158 | ||
159 | return snew; | |
160 | } | |
161 | ||
162 | dump_machine() | |
163 | { | |
164 | struct state *sp; | |
165 | struct user_action *up; | |
166 | int n, a; | |
167 | ||
168 | printf("/* state machine generated by keybld */\n"); | |
169 | printf("/* states=%d actions=%d */\n", n_states, n_user_actions); | |
170 | printf("/* %d bytes required for transition table storage */\n", | |
171 | sizeof(short) * TRANSITIONS * n_states); | |
172 | ||
173 | printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS); | |
174 | for(n = 0, sp = stop; sp; sp = sp->next, n++) { | |
175 | printf(" /* state %d: \"%s\" */\n", n, sp->seen); | |
176 | printf(" {"); | |
177 | for(a = 0; a < TRANSITIONS; a++) { | |
178 | struct trans *tp = sp->trans + a; | |
179 | switch(tp->action) { | |
180 | case GOTO: | |
181 | printf("%d", ((struct state *)tp->arg)->number); | |
182 | break; | |
183 | case TERMINAL: | |
184 | printf("%d", -(int)tp->arg - 1); | |
185 | break; | |
186 | case NOMATCH: | |
187 | printf("0"); | |
188 | break; | |
189 | } | |
190 | printf(",%s", a % 20 == 19 ? "\n\t\t" : ""); | |
191 | }; | |
192 | printf("},\n"); | |
193 | } | |
194 | ||
195 | printf("};\n"); | |
196 | ||
197 | printf("\ | |
198 | \n\ | |
199 | kparse(kp)\n\ | |
200 | char *kp;\n\ | |
201 | {\n\ | |
202 | int state = 0;\n\ | |
203 | \n\ | |
204 | for(;;) {\n\ | |
205 | short transition = transitions[state][*kp];\n"); | |
206 | ||
207 | printf("\ | |
208 | if(transition == 0) {\n\ | |
209 | return 0;\n\ | |
210 | } else if(transition > 0) {\n\ | |
211 | kp++;\n\ | |
212 | state = transition;\n\ | |
213 | } else {\n\ | |
214 | switch(-transition) {\n"); | |
215 | ||
216 | for(n = 1, up = utop; up; up = up->next, n++) { | |
217 | printf("\ | |
218 | case %d:\n\ | |
219 | %s;\n\ | |
220 | break;\n", n, up->action); | |
221 | } | |
222 | ||
223 | printf("\ | |
224 | }\n\ | |
225 | return transition;\n\ | |
226 | }\n\ | |
227 | }\n\ | |
228 | }\n"); | |
229 | ||
230 | } |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * lex.c - lexical analyzer envelope. lexyy.c, included below, | |
11 | * is the LEX-generated code. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "a56.h" | |
16 | #include "gram.h" | |
17 | ||
18 | int ldebug = 0; | |
19 | #ifdef LDEBUG | |
20 | #define RET(val) \ | |
21 | {\ | |
22 | if(ldebug) {\ | |
23 | printf("[%s]", tok_print(val));\ | |
24 | fflush(stdout);\ | |
25 | }\ | |
26 | return val;\ | |
27 | } | |
28 | #else | |
29 | #define RET(val) {return val;} | |
30 | #endif | |
31 | ||
32 | extern YYSTYPE yyval; | |
33 | ||
34 | double atof(); | |
35 | ||
36 | /**************** yylex - returns next token *****************************/ | |
37 | ||
38 | #define MAX_TOK 1024 | |
39 | char tok[MAX_TOK]; | |
40 | ||
41 | yylex() | |
42 | { | |
43 | int ltok = next_tok(); | |
44 | int itok; | |
45 | ||
46 | switch(ltok) { | |
47 | case EOF: | |
48 | if(yywrap() == 1) | |
49 | return 0; | |
50 | else | |
51 | return yylex(); | |
52 | break; | |
53 | case SYM: | |
54 | if(itok = is_keyword(tok)) { | |
55 | RET(itok); | |
56 | } else { | |
57 | yylval.sval = strsave(tok); | |
58 | RET(SYM); | |
59 | } | |
60 | break; | |
61 | case CHEX: | |
62 | yylval.n.type = INT; | |
63 | yylval.n.seg = ANY; | |
64 | yylval.n.val.i = strtol(tok, 0, 16); | |
65 | RET(CHEX); | |
66 | break; | |
67 | case CDEC: | |
68 | yylval.n.type= INT; | |
69 | yylval.n.seg = ANY; | |
70 | yylval.n.val.i = atoi(tok); | |
71 | RET(CDEC); | |
72 | break; | |
73 | case FRAC: | |
74 | yylval.n.type = FLT; | |
75 | yylval.n.seg = ANY; | |
76 | yylval.n.val.f = atof(tok); | |
77 | RET(FRAC); | |
78 | case CHAR: | |
79 | yylval.cval = *tok; | |
80 | RET(CHAR); | |
81 | case STRING: | |
82 | yylval.sval = (char *)fixstring(tok); | |
83 | yylval.sval = strsave(yylval.sval); | |
84 | RET(STRING); | |
85 | default: | |
86 | RET(ltok); | |
87 | } | |
88 | } | |
89 | ||
90 | is_keyword(tok) | |
91 | char *tok; | |
92 | { | |
93 | int kval = kparse(tok); | |
94 | if(kval > 0) | |
95 | return kval; | |
96 | ||
97 | return 0; | |
98 | } | |
99 | ||
100 | struct ascii_tab { | |
101 | char *str; | |
102 | int flags; | |
103 | } ascii_tab[]; | |
104 | #define IS_NONE 0x0000 | |
105 | #define IS_NUM 0x0001 | |
106 | #define IS_ALPHA 0x0002 | |
107 | #define IS_HEX 0x0004 | |
108 | #define IS_WHITE 0x0008 | |
109 | ||
110 | extern FILE *yyin; | |
111 | ||
112 | int next_tok() | |
113 | { | |
114 | char *tp = tok; | |
115 | enum {S_TOP, S_HEXNUM, S_NUM, S_ALNUM, S_CHAR, S_ESC_CHAR, S_COMMENT, | |
116 | S_SQ_STRING, S_DQ_STRING, S_SHL, S_SHR} state = S_TOP; | |
117 | static int unget = 0; | |
118 | BOOL dot_seen = FALSE; | |
119 | ||
120 | for(;;) { | |
121 | int c = unget ? unget : lgetc(yyin); | |
122 | int flags; | |
123 | unget = 0; | |
124 | flags = ascii_tab[c & 0x7F].flags; | |
125 | if(tp > tok + MAX_TOK - 2) return LEXBAD; | |
126 | switch(state) { | |
127 | case S_TOP: | |
128 | if(c == EOF) { | |
129 | return EOF; | |
130 | } else if(flags & IS_WHITE) { | |
131 | /* ignore */ ; | |
132 | } else if(flags & IS_ALPHA) { | |
133 | *tp++ = c; | |
134 | state = S_ALNUM; | |
135 | } else if((flags & IS_NUM) || c == '.') { | |
136 | unget = c; | |
137 | state = S_NUM; | |
138 | } else { | |
139 | switch(c) { | |
140 | case '$': state = S_HEXNUM; break; | |
141 | case '"': state = S_DQ_STRING; break; | |
142 | case '\'': state = S_CHAR; break; | |
143 | case '>': state = S_SHR; break; | |
144 | case '<': state = S_SHL; break; | |
145 | case ';': state = S_COMMENT; break; | |
146 | case '\n': return EOL; | |
147 | case '@': return EOS; | |
148 | default: return c; | |
149 | } | |
150 | } | |
151 | break; | |
152 | case S_COMMENT: | |
153 | if(c == EOF) { | |
154 | unget = EOF; | |
155 | *tp = '\0'; | |
156 | return EOL; | |
157 | } else if(c == '\n') { | |
158 | return EOL; | |
159 | } | |
160 | break; | |
161 | case S_SHR: | |
162 | if(c == EOF) { | |
163 | unget = EOF; | |
164 | *tp = '\0'; | |
165 | return '>'; | |
166 | } else if(c == '>') { | |
167 | return SHR; | |
168 | } else { | |
169 | unget = c; | |
170 | return '>'; | |
171 | } | |
172 | break; | |
173 | case S_SHL: | |
174 | if(c == EOF) { | |
175 | unget = EOF; | |
176 | *tp = '\0'; | |
177 | return '<'; | |
178 | } else if(c == '<') { | |
179 | return SHL; | |
180 | } else { | |
181 | unget = c; | |
182 | return '<'; | |
183 | } | |
184 | break; | |
185 | case S_HEXNUM: | |
186 | if(c == EOF) { | |
187 | unget = EOF; | |
188 | *tp = '\0'; | |
189 | return CHEX; | |
190 | } else if(flags & IS_HEX) { | |
191 | *tp++ = c; | |
192 | break; | |
193 | } else { | |
194 | unget = c; | |
195 | *tp = '\0'; | |
196 | return CHEX; | |
197 | } | |
198 | break; | |
199 | case S_ALNUM: | |
200 | if(c == EOF) { | |
201 | unget = EOF; | |
202 | *tp = '\0'; | |
203 | return SYM; | |
204 | } else if(c == ':') { | |
205 | *tp++ = c; | |
206 | *tp = '\0'; | |
207 | return SYM; | |
208 | break; | |
209 | } else if(flags & (IS_ALPHA|IS_NUM)) { | |
210 | *tp++ = c; | |
211 | break; | |
212 | } else { | |
213 | unget = c; | |
214 | *tp = '\0'; | |
215 | return SYM; | |
216 | } | |
217 | break; | |
218 | case S_NUM: | |
219 | if(c == EOF) { | |
220 | unget = EOF; | |
221 | *tp = '\0'; | |
222 | return dot_seen ? FRAC : CDEC; | |
223 | } else if((flags & IS_NUM) || (c == '.' && NOT dot_seen)) { | |
224 | *tp++ = c; | |
225 | if(c == '.') dot_seen = TRUE; | |
226 | break; | |
227 | } else { | |
228 | unget = c; | |
229 | *tp = '\0'; | |
230 | return dot_seen ? FRAC : CDEC; | |
231 | } | |
232 | break; | |
233 | case S_CHAR: | |
234 | if(c == EOF) { | |
235 | unget = EOF; | |
236 | *tp = '\0'; | |
237 | return CHAR; | |
238 | } else if(c == '\\') { | |
239 | state = S_ESC_CHAR; | |
240 | } else if(c == '\'') { | |
241 | *tp = '\0'; | |
242 | return CHAR; | |
243 | } else { | |
244 | *tp++ = c; | |
245 | if(tp > tok + 1) | |
246 | state = S_SQ_STRING; | |
247 | } | |
248 | break; | |
249 | case S_ESC_CHAR: | |
250 | if(c == EOF) { | |
251 | unget = EOF; | |
252 | *tp = '\0'; | |
253 | return CHAR; | |
254 | } | |
255 | switch(c) { | |
256 | case 'b': *tp = '\b'; break; | |
257 | case 'f': *tp = '\f'; break; | |
258 | case 'n': *tp = '\n'; break; | |
259 | case 'r': *tp = '\r'; break; | |
260 | case 't': *tp = '\t'; break; | |
261 | case '\\': *tp = '\\'; break; | |
262 | case '\'': | |
263 | *tp = '\0'; | |
264 | return CHAR; | |
265 | break; | |
266 | default: | |
267 | *tp++ = c; | |
268 | state = S_SQ_STRING; | |
269 | break; | |
270 | } | |
271 | break; | |
272 | case S_SQ_STRING: | |
273 | if(c == EOF) { | |
274 | unget = EOF; | |
275 | *tp = '\0'; | |
276 | return STRING; | |
277 | } else if(c == '\'') { | |
278 | *tp = '\0'; | |
279 | return STRING; | |
280 | } else { | |
281 | *tp++ = c; | |
282 | } | |
283 | break; | |
284 | case S_DQ_STRING: | |
285 | if(c == EOF) { | |
286 | unget = EOF; | |
287 | *tp = '\0'; | |
288 | return STRING; | |
289 | } else if(c == '"') { | |
290 | *tp = '\0'; | |
291 | return STRING; | |
292 | } else { | |
293 | *tp++ = c; | |
294 | } | |
295 | break; | |
296 | } /* switch(state) */ | |
297 | } /* for(;;) */ | |
298 | } | |
299 | ||
300 | struct ascii_tab ascii_tab[] = { | |
301 | {"\\z00", IS_NONE /* 0x00 */}, | |
302 | {"\\z01", IS_NONE /* 0x01 */}, | |
303 | {"\\z02", IS_NONE /* 0x02 */}, | |
304 | {"\\z03", IS_NONE /* 0x03 */}, | |
305 | {"\\z04", IS_NONE /* 0x04 */}, | |
306 | {"\\z05", IS_NONE /* 0x05 */}, | |
307 | {"\\z06", IS_NONE /* 0x06 */}, | |
308 | {"\\z07", IS_NONE /* 0x07 */}, | |
309 | {"\\b", IS_NONE /* 0x08 */}, | |
310 | {"\\t", IS_NONE|IS_WHITE /* 0x09 */}, | |
311 | {"\\n", IS_NONE /* 0x0A */}, | |
312 | {"\\z0B", IS_NONE /* 0x0B */}, | |
313 | {"\\z0C", IS_NONE /* 0x0C */}, | |
314 | {"\\r", IS_NONE /* 0x0D */}, | |
315 | {"\\z0E", IS_NONE /* 0x0E */}, | |
316 | {"\\z0F", IS_NONE /* 0x0F */}, | |
317 | {"\\z10", IS_NONE /* 0x10 */}, | |
318 | {"\\z11", IS_NONE /* 0x11 */}, | |
319 | {"\\z12", IS_NONE /* 0x12 */}, | |
320 | {"\\z13", IS_NONE /* 0x13 */}, | |
321 | {"\\z14", IS_NONE /* 0x14 */}, | |
322 | {"\\z15", IS_NONE /* 0x15 */}, | |
323 | {"\\z16", IS_NONE /* 0x16 */}, | |
324 | {"\\z17", IS_NONE /* 0x17 */}, | |
325 | {"\\z18", IS_NONE /* 0x18 */}, | |
326 | {"\\z19", IS_NONE /* 0x19 */}, | |
327 | {"\\z1A", IS_NONE /* 0x1A */}, | |
328 | {"\\z1B", IS_NONE /* 0x1B */}, | |
329 | {"\\z1C", IS_NONE /* 0x1C */}, | |
330 | {"\\z1D", IS_NONE /* 0x1D */}, | |
331 | {"\\z1E", IS_NONE /* 0x1E */}, | |
332 | {"\\z1F", IS_NONE /* 0x1F */}, | |
333 | {" ", IS_NONE|IS_WHITE /* 0x20 */}, | |
334 | {"!", IS_NONE /* 0x21 */}, | |
335 | {"\"", IS_NONE /* 0x22 */}, | |
336 | {"#", IS_NONE /* 0x23 */}, | |
337 | {"$", IS_NONE /* 0x24 */}, | |
338 | {"%", IS_NONE /* 0x25 */}, | |
339 | {"&", IS_NONE /* 0x26 */}, | |
340 | {"'", IS_NONE /* 0x27 */}, | |
341 | {"(", IS_NONE /* 0x28 */}, | |
342 | {")", IS_NONE /* 0x29 */}, | |
343 | {"*", IS_NONE /* 0x2A */}, | |
344 | {"+", IS_NONE /* 0x2B */}, | |
345 | {",", IS_NONE /* 0x2C */}, | |
346 | {"-", IS_NONE /* 0x2D */}, | |
347 | {".", IS_NONE /* 0x2E */}, | |
348 | {"/", IS_NONE /* 0x2F */}, | |
349 | {"0", IS_NONE|IS_NUM|IS_HEX /* 0x30 */}, | |
350 | {"1", IS_NONE|IS_NUM|IS_HEX /* 0x31 */}, | |
351 | {"2", IS_NONE|IS_NUM|IS_HEX /* 0x32 */}, | |
352 | {"3", IS_NONE|IS_NUM|IS_HEX /* 0x33 */}, | |
353 | {"4", IS_NONE|IS_NUM|IS_HEX /* 0x34 */}, | |
354 | {"5", IS_NONE|IS_NUM|IS_HEX /* 0x35 */}, | |
355 | {"6", IS_NONE|IS_NUM|IS_HEX /* 0x36 */}, | |
356 | {"7", IS_NONE|IS_NUM|IS_HEX /* 0x37 */}, | |
357 | {"8", IS_NONE|IS_NUM|IS_HEX /* 0x38 */}, | |
358 | {"9", IS_NONE|IS_NUM|IS_HEX /* 0x39 */}, | |
359 | {":", IS_NONE /* 0x3A */}, | |
360 | {";", IS_NONE /* 0x3B */}, | |
361 | {"<", IS_NONE /* 0x3C */}, | |
362 | {"=", IS_NONE /* 0x3D */}, | |
363 | {">", IS_NONE /* 0x3E */}, | |
364 | {"?", IS_NONE /* 0x3F */}, | |
365 | {"@", IS_NONE /* 0x40 */}, | |
366 | {"A", IS_NONE|IS_ALPHA|IS_HEX /* 0x41 */}, | |
367 | {"B", IS_NONE|IS_ALPHA|IS_HEX /* 0x42 */}, | |
368 | {"C", IS_NONE|IS_ALPHA|IS_HEX /* 0x43 */}, | |
369 | {"D", IS_NONE|IS_ALPHA|IS_HEX /* 0x44 */}, | |
370 | {"E", IS_NONE|IS_ALPHA|IS_HEX /* 0x45 */}, | |
371 | {"F", IS_NONE|IS_ALPHA|IS_HEX /* 0x46 */}, | |
372 | {"G", IS_NONE|IS_ALPHA /* 0x47 */}, | |
373 | {"H", IS_NONE|IS_ALPHA /* 0x48 */}, | |
374 | {"I", IS_NONE|IS_ALPHA /* 0x49 */}, | |
375 | {"J", IS_NONE|IS_ALPHA /* 0x4A */}, | |
376 | {"K", IS_NONE|IS_ALPHA /* 0x4B */}, | |
377 | {"L", IS_NONE|IS_ALPHA /* 0x4C */}, | |
378 | {"M", IS_NONE|IS_ALPHA /* 0x4D */}, | |
379 | {"N", IS_NONE|IS_ALPHA /* 0x4E */}, | |
380 | {"O", IS_NONE|IS_ALPHA /* 0x4F */}, | |
381 | {"P", IS_NONE|IS_ALPHA /* 0x50 */}, | |
382 | {"Q", IS_NONE|IS_ALPHA /* 0x51 */}, | |
383 | {"R", IS_NONE|IS_ALPHA /* 0x52 */}, | |
384 | {"S", IS_NONE|IS_ALPHA /* 0x53 */}, | |
385 | {"T", IS_NONE|IS_ALPHA /* 0x54 */}, | |
386 | {"U", IS_NONE|IS_ALPHA /* 0x55 */}, | |
387 | {"V", IS_NONE|IS_ALPHA /* 0x56 */}, | |
388 | {"W", IS_NONE|IS_ALPHA /* 0x57 */}, | |
389 | {"X", IS_NONE|IS_ALPHA /* 0x58 */}, | |
390 | {"Y", IS_NONE|IS_ALPHA /* 0x59 */}, | |
391 | {"Z", IS_NONE|IS_ALPHA /* 0x5A */}, | |
392 | {"[", IS_NONE /* 0x5B */}, | |
393 | {"\\", IS_NONE /* 0x5C */}, | |
394 | {"]", IS_NONE /* 0x5D */}, | |
395 | {"^", IS_NONE /* 0x5E */}, | |
396 | {"_", IS_NONE|IS_ALPHA /* 0x5F */}, | |
397 | {"`", IS_NONE /* 0x60 */}, | |
398 | {"a", IS_NONE|IS_ALPHA|IS_HEX /* 0x61 */}, | |
399 | {"b", IS_NONE|IS_ALPHA|IS_HEX /* 0x62 */}, | |
400 | {"c", IS_NONE|IS_ALPHA|IS_HEX /* 0x63 */}, | |
401 | {"d", IS_NONE|IS_ALPHA|IS_HEX /* 0x64 */}, | |
402 | {"e", IS_NONE|IS_ALPHA|IS_HEX /* 0x65 */}, | |
403 | {"f", IS_NONE|IS_ALPHA|IS_HEX /* 0x66 */}, | |
404 | {"g", IS_NONE|IS_ALPHA /* 0x67 */}, | |
405 | {"h", IS_NONE|IS_ALPHA /* 0x68 */}, | |
406 | {"i", IS_NONE|IS_ALPHA /* 0x69 */}, | |
407 | {"j", IS_NONE|IS_ALPHA /* 0x6A */}, | |
408 | {"k", IS_NONE|IS_ALPHA /* 0x6B */}, | |
409 | {"l", IS_NONE|IS_ALPHA /* 0x6C */}, | |
410 | {"m", IS_NONE|IS_ALPHA /* 0x6D */}, | |
411 | {"n", IS_NONE|IS_ALPHA /* 0x6E */}, | |
412 | {"o", IS_NONE|IS_ALPHA /* 0x6F */}, | |
413 | {"p", IS_NONE|IS_ALPHA /* 0x70 */}, | |
414 | {"q", IS_NONE|IS_ALPHA /* 0x71 */}, | |
415 | {"r", IS_NONE|IS_ALPHA /* 0x72 */}, | |
416 | {"s", IS_NONE|IS_ALPHA /* 0x73 */}, | |
417 | {"t", IS_NONE|IS_ALPHA /* 0x74 */}, | |
418 | {"u", IS_NONE|IS_ALPHA /* 0x75 */}, | |
419 | {"v", IS_NONE|IS_ALPHA /* 0x76 */}, | |
420 | {"w", IS_NONE|IS_ALPHA /* 0x77 */}, | |
421 | {"x", IS_NONE|IS_ALPHA /* 0x78 */}, | |
422 | {"y", IS_NONE|IS_ALPHA /* 0x79 */}, | |
423 | {"z", IS_NONE|IS_ALPHA /* 0x7A */}, | |
424 | {"{", IS_NONE /* 0x7B */}, | |
425 | {"|", IS_NONE /* 0x7C */}, | |
426 | {"}", IS_NONE /* 0x7D */}, | |
427 | {"~", IS_NONE /* 0x7E */}, | |
428 | {"\\z7F", IS_NONE /* 0x7F */}, | |
429 | }; | |
430 | ||
431 | ||
432 | /**************** lgetc - returns next character *************************/ | |
433 | ||
434 | #define INLINE 1024 | |
435 | ||
436 | char line_buf[INLINE]; | |
437 | char *cur_line = line_buf; /* points to current line buffer */ | |
438 | char *clp = NULL; /* where we're at in cur_line */ | |
439 | ||
440 | lgetc(fp) | |
441 | FILE *fp; | |
442 | { | |
443 | int c; | |
444 | ||
445 | if(clp == NULL) { | |
446 | if(fgets(cur_line, INLINE, fp) == NULL) { | |
447 | c = EOF; | |
448 | } else { | |
449 | clp = cur_line; | |
450 | c = *clp++; | |
451 | } | |
452 | } else { | |
453 | c = *clp++; | |
454 | } | |
455 | ||
456 | switch(c) { | |
457 | case EOF: | |
458 | /* at EOF: all done */ | |
459 | if(ldebug) | |
460 | printf("<eof>\n"); | |
461 | return EOF; | |
462 | break; | |
463 | case '\0': | |
464 | c = '\n'; | |
465 | case '\n': | |
466 | clp = NULL; | |
467 | break; | |
468 | default: | |
469 | break; | |
470 | } | |
471 | ||
472 | if(ldebug) | |
473 | printf(c < ' ' ? "<\\z%02X>%s" : "<%c>", c, c == '\n' ? "\n" : ""); | |
474 | ||
475 | return c; | |
476 | } |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
11 | * | |
12 | * Permission to use, copy, modify, distribute, and sell this software | |
13 | * and its documentation for any purpose is hereby granted without fee, | |
14 | * provided that the above copyright notice appear in all copies and | |
15 | * that both that copyright notice and this permission notice appear | |
16 | * in supporting documentation. The author makes no representations | |
17 | * about the suitability of this software for any purpose. It is | |
18 | * provided "as is" without express or implied warranty. | |
19 | * | |
20 | */ | |
21 | static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; | |
22 | ||
23 | /* | |
24 | * main.c - The "main" code for the assembler. | |
25 | * | |
26 | */ | |
27 | ||
28 | #include "a56.h" | |
29 | ||
30 | #define MAX 1024 | |
31 | ||
32 | int pass; | |
33 | int error, warning; | |
34 | extern unsigned long pc; | |
35 | extern int seg; | |
36 | BOOL binary_listing = FALSE; | |
37 | BOOL list_includes = FALSE; | |
38 | FILE *obj = NULL; | |
39 | extern BOOL list_on; | |
40 | BOOL list_on_next = TRUE; | |
41 | char *alloc(); | |
42 | ||
43 | main(argc,argv) | |
44 | int argc; | |
45 | char *argv[]; | |
46 | { | |
47 | int i; | |
48 | extern char *optarg; | |
49 | extern int optind; | |
50 | int c; | |
51 | char *output_file = "a56.out"; | |
52 | char *input_file; | |
53 | char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n"; | |
54 | ||
55 | while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) { | |
56 | case 'b': | |
57 | binary_listing++; | |
58 | break; | |
59 | case 'l': | |
60 | list_includes++; | |
61 | break; | |
62 | case 'd': | |
63 | ldebug++; | |
64 | break; | |
65 | case 'o': | |
66 | output_file = optarg; | |
67 | break; | |
68 | case '?': | |
69 | default: | |
70 | fatal(usage); | |
71 | } | |
72 | input_file = argv[optind++]; | |
73 | if(input_file == NULL) fatal(usage); | |
74 | obj = open_write(output_file); | |
75 | ||
76 | pc = 0; | |
77 | seg = 0; | |
78 | pass = 1; | |
79 | reset_psects(); | |
80 | include(input_file); | |
81 | ||
82 | pc = 0; | |
83 | seg = 0; | |
84 | pass = 2; | |
85 | reset_psects(); | |
86 | include(input_file); | |
87 | ||
88 | psect_summary(); | |
89 | dump_symtab(); | |
90 | fclose(obj); | |
91 | printf("errors=%d\n", error); | |
92 | printf("warnings=%d\n", warning); | |
93 | return error ? 1 : 0; | |
94 | } | |
95 | ||
96 | struct inc inc[MAX_NEST]; | |
97 | int inc_p = 0; | |
98 | FILE *yyin; | |
99 | ||
100 | include(file) | |
101 | char *file; | |
102 | { | |
103 | FILE *fp = open_read(file); | |
104 | ||
105 | inc_p++; | |
106 | if(inc_p >= MAX_NEST) | |
107 | fatal("%s: include nesting too deep\n", file); | |
108 | ||
109 | inc[inc_p].file = file; | |
110 | inc[inc_p].fp = fp; | |
111 | inc[inc_p].line = 1; | |
112 | ||
113 | list_on_next = TRUE; | |
114 | if(inc_p > 1 && NOT list_includes) | |
115 | list_on_next = FALSE; | |
116 | ||
117 | yyin = inc[inc_p].fp; | |
118 | if(inc_p == 1) | |
119 | #ifdef FLEX | |
120 | { | |
121 | static int started = 0; | |
122 | if(started) | |
123 | yyrestart(yyin); | |
124 | else | |
125 | started = 1; | |
126 | yyparse(); | |
127 | } | |
128 | #else | |
129 | yyparse(); | |
130 | #endif | |
131 | } | |
132 | ||
133 | yywrap() | |
134 | { | |
135 | fclose(inc[inc_p].fp); | |
136 | inc_p--; | |
137 | list_on = list_on_next = TRUE; | |
138 | if(inc_p > 1) | |
139 | list_on = list_on_next = FALSE; | |
140 | if(inc_p) { | |
141 | yyin = inc[inc_p].fp; | |
142 | return 0; | |
143 | } else { | |
144 | return 1; | |
145 | } | |
146 | } | |
147 | ||
148 | struct n | |
149 | sym_ref(sym) /* return symbol value or UNDEF if not defined yet */ | |
150 | char *sym; | |
151 | { | |
152 | struct sym *sp, *find_sym(); | |
153 | struct n result; | |
154 | ||
155 | result.type = UNDEF; | |
156 | ||
157 | sp = find_sym(sym); | |
158 | if(NOT sp) { | |
159 | if(pass == 2) { | |
160 | yyerror("%s: undefined symbol", sym); | |
161 | } | |
162 | return result; | |
163 | } | |
164 | ||
165 | return sp->n; | |
166 | } | |
167 | ||
168 | #define HASHSIZE 128 | |
169 | ||
170 | #define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE) | |
171 | ||
172 | struct sym *symtab[HASHSIZE]; | |
173 | ||
174 | sym_def(sym, type, seg, i, f) | |
175 | char *sym; | |
176 | int type; | |
177 | int seg; | |
178 | int i; | |
179 | double f; | |
180 | { | |
181 | struct sym *sp, **stop, *find_sym(); | |
182 | ||
183 | if(pass == 1) { | |
184 | if(find_sym(sym)) { | |
185 | pass = 2; /* what a kludge */ | |
186 | yyerror("%s: multiply defined symbol", sym); | |
187 | pass = 1; | |
188 | return; | |
189 | } | |
190 | stop = &symtab[HASH(sym)]; | |
191 | sp = NEW(struct sym); | |
192 | sp->next = *stop; | |
193 | *stop = sp; | |
194 | sp->name = strsave(sym); | |
195 | sp->n.type = type; | |
196 | sp->n.seg = seg; | |
197 | if(type == INT) | |
198 | sp->n.val.i = i & 0xFFFFFF; | |
199 | else | |
200 | sp->n.val.f = f; | |
201 | } else { | |
202 | sp = find_sym(sym); | |
203 | if(NOT sp) | |
204 | fatal("internal error 304\n"); | |
205 | if(sp->n.type != type || | |
206 | type == INT && sp->n.val.i != (i & 0xFFFFFF) || | |
207 | type == FLT && sp->n.val.f != f) | |
208 | yyerror("%s: assembler phase error", sym); | |
209 | } | |
210 | } | |
211 | ||
212 | struct sym *find_sym(sym) | |
213 | char *sym; | |
214 | { | |
215 | struct sym *sp, **stop; | |
216 | ||
217 | stop = &symtab[HASH(sym)]; | |
218 | for(sp = *stop; sp; sp = sp->next) | |
219 | if(strcmp(sp->name, sym) == 0) | |
220 | return sp; | |
221 | ||
222 | return NULL; | |
223 | } | |
224 | ||
225 | extern char segs[]; | |
226 | dump_symtab() | |
227 | { | |
228 | struct sym *sp, **stop; | |
229 | int i; | |
230 | ||
231 | printf("\n\ | |
232 | Symbol Table\n\ | |
233 | -------------------------------------\n"); | |
234 | /* | |
235 | SSSSSSSSSSSSSSSS S XXXXXX | |
236 | SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD | |
237 | */ | |
238 | ||
239 | for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) { | |
240 | for(sp = *stop; sp; sp = sp->next) { | |
241 | if(sp->n.type == INT) { | |
242 | printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i); | |
243 | fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name); | |
244 | } else { | |
245 | printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f); | |
246 | fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name); | |
247 | } | |
248 | } | |
249 | } | |
250 | } | |
251 | ||
252 | char *printcode(word) | |
253 | int word; | |
254 | { | |
255 | static char list[MAX], *lp; | |
256 | int i; | |
257 | ||
258 | word &= 0xFFFFFF; | |
259 | ||
260 | if(binary_listing) { | |
261 | sprintf(list, "%06X<", word); | |
262 | for(i = 0, lp = &list[7]; i < 24; i++, lp++) { | |
263 | *lp = word & 1 << 23 - i ? '1' : '0'; | |
264 | if(i && i % 4 == 3) | |
265 | *++lp = i % 8 == 7 ? ' ' : ','; | |
266 | } | |
267 | lp[-1] = '>'; | |
268 | lp[0] = '\0'; | |
269 | } else { | |
270 | sprintf(list, "%06X", word); | |
271 | } | |
272 | return list; | |
273 | } | |
274 | ||
275 | char *spacespace[2] = { | |
276 | /*P:XXXX_XXXXXX_*/ | |
277 | " ", | |
278 | /*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/ | |
279 | " "}; | |
280 | char *spaces(n) | |
281 | int n; | |
282 | { | |
283 | return spacespace[binary_listing ? 1 : 0] + n; | |
284 | } | |
285 | ||
286 | extern char segs[]; | |
287 | ||
288 | gencode(seg, pc, word) | |
289 | int seg, pc, word; | |
290 | { | |
291 | fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF); | |
292 | } | |
293 | ||
294 | char fixbuf[1024]; | |
295 | ||
296 | char *fixstring(s) | |
297 | char *s; | |
298 | { | |
299 | char *bp = fixbuf; | |
300 | int ival; | |
301 | ||
302 | while(*s) { | |
303 | switch (*s) { | |
304 | case '\'': | |
305 | case '\"': | |
306 | s++; | |
307 | break; | |
308 | case '\\': | |
309 | switch (*++s) { | |
310 | case 'b': *bp++ = '\b'; break; | |
311 | case 'r': *bp++ = '\r'; break; | |
312 | case 'f': *bp++ = '\f'; break; | |
313 | case 'n': *bp++ = '\n'; break; | |
314 | case 't': *bp++ = '\t'; break; | |
315 | case '\\': *bp++ = '\\'; break; | |
316 | case '0': | |
317 | ival = 0; | |
318 | while(*s >= '0' && *s <= '9') { | |
319 | ival <<= 3; | |
320 | ival += *s++ - '0'; | |
321 | } | |
322 | *bp++ = ival; | |
323 | break; | |
324 | } | |
325 | break; | |
326 | default: | |
327 | *bp++ = *s++; | |
328 | break; | |
329 | } | |
330 | } | |
331 | *bp = '\0'; | |
332 | return fixbuf; | |
333 | } | |
334 | ||
335 | #define ONE 0x4000000 | |
336 | ||
337 | makefrac(s) | |
338 | char *s; | |
339 | { | |
340 | int frac = 0, div = 1; | |
341 | int scale = 1; | |
342 | ||
343 | while(*s) { | |
344 | switch(*s) { | |
345 | case '-': | |
346 | scale = -1; | |
347 | break; | |
348 | case '.': | |
349 | div = 10; | |
350 | break; | |
351 | default: | |
352 | frac += (*s - '0') * scale * ONE / div; | |
353 | div *= 10; | |
354 | break; | |
355 | } | |
356 | s++; | |
357 | } | |
358 | ||
359 | return frac + scale * 4 >> 3 & 0xFFFFFF; | |
360 | } | |
361 | ||
362 | /***************** psect stuff ************************/ | |
363 | ||
364 | struct psect *ptop = NULL, *cur_psect = NULL; | |
365 | ||
366 | reset_psects() | |
367 | { | |
368 | struct psect *pp; | |
369 | ||
370 | for(pp = ptop; pp; pp = pp->next) { | |
371 | pp->pc = pp->bottom; | |
372 | } | |
373 | ||
374 | set_psect(NULL); | |
375 | } | |
376 | ||
377 | psect_summary() | |
378 | { | |
379 | printf("\nSummary of psect usage\n\n"); | |
380 | ||
381 | printf("\ | |
382 | section seg base last top used avail total\n\ | |
383 | -------------------------------------------------------------------------\n"); | |
384 | /* | |
385 | SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999 | |
386 | */ | |
387 | ||
388 | summarize(ptop); /* do it recursively to place back in order */ | |
389 | printf("\n"); | |
390 | } | |
391 | ||
392 | summarize(pp) | |
393 | struct psect *pp; | |
394 | { | |
395 | int used, avail, of; | |
396 | ||
397 | if(pp == NULL) | |
398 | return; | |
399 | ||
400 | used = pp->pc - pp->bottom; | |
401 | avail = pp->top - pp->pc; | |
402 | of = pp->top - pp->bottom; | |
403 | ||
404 | summarize(pp->next); | |
405 | ||
406 | printf("%24.24s %c %04X %04X %04X %5d %3d%% %5d %3d%% %5d\n", | |
407 | pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top, | |
408 | used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0, | |
409 | of); | |
410 | } | |
411 | ||
412 | struct psect *find_psect(name) | |
413 | char *name; | |
414 | { | |
415 | struct psect *pp; | |
416 | ||
417 | for(pp = ptop; pp; pp = pp->next) | |
418 | if(strcmp(pp->name, name) == 0) | |
419 | return pp; | |
420 | ||
421 | return NULL; | |
422 | } | |
423 | ||
424 | set_psect(pp) | |
425 | struct psect *pp; | |
426 | { | |
427 | cur_psect = pp; | |
428 | } | |
429 | ||
430 | check_psect(seg, pc) | |
431 | int seg; | |
432 | unsigned int pc; | |
433 | { | |
434 | if(cur_psect) { | |
435 | if(seg == cur_psect->seg && pc >= cur_psect->bottom && | |
436 | pc <= cur_psect->top) { | |
437 | cur_psect->pc = pc; | |
438 | return TRUE; | |
439 | } else { | |
440 | return FALSE; | |
441 | } | |
442 | } else { | |
443 | return TRUE; | |
444 | } | |
445 | } | |
446 | ||
447 | struct psect *new_psect(name, seg, bottom, top) | |
448 | char *name; | |
449 | int seg; | |
450 | unsigned int bottom, top; | |
451 | { | |
452 | struct psect *pp = find_psect(name); | |
453 | ||
454 | if(NOT pp) { | |
455 | pp = (struct psect *)alloc(sizeof *pp); | |
456 | pp->next = ptop; | |
457 | ptop = pp; | |
458 | pp->name = strsave(name); | |
459 | pp->seg = seg; | |
460 | pp->pc = bottom; | |
461 | } | |
462 | pp->bottom = bottom; | |
463 | pp->top = top; | |
464 | ||
465 | return pp; | |
466 | } |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
11 | * | |
12 | * Permission to use, copy, modify, distribute, and sell this software | |
13 | * and its documentation for any purpose is hereby granted without fee, | |
14 | * provided that the above copyright notice appear in all copies and | |
15 | * that both that copyright notice and this permission notice appear | |
16 | * in supporting documentation. The author makes no representations | |
17 | * about the suitability of this software for any purpose. It is | |
18 | * provided "as is" without express or implied warranty. | |
19 | * | |
20 | */ | |
21 | static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; | |
22 | ||
23 | /* | |
24 | * subs.c - Some subroutines for the assembler. | |
25 | * | |
26 | */ | |
27 | ||
28 | #include "a56.h" | |
29 | ||
30 | #define MAX 1024 | |
31 | ||
32 | char *alloc(); | |
33 | ||
34 | FILE *open_read(file) | |
35 | char *file; | |
36 | { | |
37 | FILE *fp; | |
38 | ||
39 | if(strcmp(file, "-") == 0) | |
40 | fp = stdin; | |
41 | else if ((fp = fopen(file, "r")) == NULL) { | |
42 | perror(file); | |
43 | exit(1); | |
44 | } | |
45 | return fp; | |
46 | } | |
47 | ||
48 | FILE *open_write(file) | |
49 | char *file; | |
50 | { | |
51 | FILE *fp; | |
52 | if ((fp = fopen(file, "w")) == NULL) { | |
53 | perror(file); | |
54 | exit(1); | |
55 | } | |
56 | return fp; | |
57 | } | |
58 | ||
59 | FILE *open_append(file) | |
60 | char *file; | |
61 | { | |
62 | FILE *fp; | |
63 | if ((fp = fopen(file, "a")) == NULL) { | |
64 | perror(file); | |
65 | exit(1); | |
66 | } | |
67 | return fp; | |
68 | } | |
69 | ||
70 | fatal(c, a1, a2, a3, a4, a5, a6, a7, a8) | |
71 | char *c, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; | |
72 | { | |
73 | fprintf(stderr, c, a1, a2, a3, a4, a5, a6, a7, a8); | |
74 | exit(1); | |
75 | } | |
76 | ||
77 | #define TABS 8 | |
78 | #define MAX_BUF 256 | |
79 | ||
80 | char tabbuf[MAX_BUF], *untabn(); | |
81 | char *untab(s) /* expand tabs in s */ | |
82 | register char *s; | |
83 | { | |
84 | return untabn(s, TABS); | |
85 | } | |
86 | ||
87 | char *untabn(s, stops) /* expand tabs in s */ | |
88 | register char *s; | |
89 | register int stops; | |
90 | { | |
91 | char *o = s; | |
92 | ||
93 | /* copy input string into buffer to scan while input string is modified */ | |
94 | ||
95 | register char *b = tabbuf; | |
96 | ||
97 | strncpy(b, s, MAX_BUF); | |
98 | ||
99 | /* iterate until the copy of the input string is depleted */ | |
100 | ||
101 | while(*b) { | |
102 | if(*b == '\t') { | |
103 | do | |
104 | *s = ' '; | |
105 | while ((++s - o) % stops); | |
106 | } else { | |
107 | *s = *b; s++; | |
108 | } | |
109 | b++; | |
110 | } | |
111 | ||
112 | /* null terminate the resultant string */ | |
113 | ||
114 | *s = '\0'; | |
115 | ||
116 | return o; | |
117 | } | |
118 | ||
119 | char *alloc(size) | |
120 | int size; | |
121 | { | |
122 | char *p = (char *)malloc(size); | |
123 | if(NOT p) | |
124 | fatal("alloc: insufficient virtual memory to allocate %d bytes\n", | |
125 | size); | |
126 | return p; | |
127 | } | |
128 | ||
129 | #define ascii2n(c) \ | |
130 | ((c) >= 'a' ? (c) - 'a' + 10 : ((c) >= 'A' ? (c) - 'A' + 10 : (c) - '0')) | |
131 | ||
132 | #define valid(c) ((c) >= '0' && (c) <= '9' || \ | |
133 | (c) >= 'A' && (c) <= 'Z' || \ | |
134 | (c) >= 'a' && (c) <= 'z') | |
135 | ||
136 | strtol(s, p, base) | |
137 | register char *s, **p; | |
138 | register int base; | |
139 | { | |
140 | register long result = 0; | |
141 | register int sign = 0; | |
142 | ||
143 | while(*s == ' ' || *s == '\t') | |
144 | s++; | |
145 | ||
146 | if(*s == '-') { | |
147 | s++; | |
148 | sign++; | |
149 | } | |
150 | ||
151 | while(valid(*s)) { | |
152 | register int dig = ascii2n(*s); | |
153 | if(dig >= base) | |
154 | break; | |
155 | result *= base; | |
156 | result += dig; | |
157 | s++; | |
158 | } | |
159 | ||
160 | if(p) | |
161 | *p = s; | |
162 | ||
163 | return sign ? -result : result; | |
164 | } |
0 | BEGIN {printf("struct {int n; char *name;} tok_tab[] = {\n");} | |
1 | /#define/ {printf(" {%d, \"%s\"},\n", $3, $2);} | |
2 | /# define/ {printf(" {%d, \"%s\"},\n", $4, $3);} | |
3 | END {printf("};\n#define N_TOK (sizeof tok_tab / sizeof tok_tab[0])\nint n_tok = N_TOK;\n");} |
0 | struct {int n; char *name;} tok_tab[] = { | |
1 | {257, "CHEX"}, | |
2 | {258, "CDEC"}, | |
3 | {259, "FRAC"}, | |
4 | {260, "AREG"}, | |
5 | {261, "BREG"}, | |
6 | {262, "MREG"}, | |
7 | {263, "NREG"}, | |
8 | {264, "RREG"}, | |
9 | {265, "XREG"}, | |
10 | {266, "YREG"}, | |
11 | {267, "OP"}, | |
12 | {268, "OPA"}, | |
13 | {269, "OPP"}, | |
14 | {270, "OP_JCC"}, | |
15 | {271, "OP_JSCC"}, | |
16 | {272, "OP_TCC"}, | |
17 | {273, "SYM"}, | |
18 | {274, "STRING"}, | |
19 | {275, "CHAR"}, | |
20 | {276, "XMEM"}, | |
21 | {277, "YMEM"}, | |
22 | {278, "LMEM"}, | |
23 | {279, "PMEM"}, | |
24 | {280, "AAAA"}, | |
25 | {281, "A10"}, | |
26 | {282, "BBBB"}, | |
27 | {283, "B10"}, | |
28 | {284, "AABB"}, | |
29 | {285, "BBAA"}, | |
30 | {286, "XXXX"}, | |
31 | {287, "YYYY"}, | |
32 | {288, "SR"}, | |
33 | {289, "MR"}, | |
34 | {290, "CCR"}, | |
35 | {291, "OMR"}, | |
36 | {292, "SP"}, | |
37 | {293, "SSH"}, | |
38 | {294, "SSL"}, | |
39 | {295, "LA"}, | |
40 | {296, "LC"}, | |
41 | {297, "EOL"}, | |
42 | {298, "EOS"}, | |
43 | {299, "LEXBAD"}, | |
44 | {300, "OP_ABS"}, | |
45 | {301, "OP_ADC"}, | |
46 | {302, "OP_ADD"}, | |
47 | {303, "OP_ADDL"}, | |
48 | {304, "OP_ADDR"}, | |
49 | {305, "OP_ASL"}, | |
50 | {306, "OP_ASR"}, | |
51 | {307, "OP_CLR"}, | |
52 | {308, "OP_CMP"}, | |
53 | {309, "OP_CMPM"}, | |
54 | {310, "OP_DIV"}, | |
55 | {311, "OP_MAC"}, | |
56 | {312, "OP_MACR"}, | |
57 | {313, "OP_MPY"}, | |
58 | {314, "OP_MPYR"}, | |
59 | {315, "OP_NEG"}, | |
60 | {316, "OP_NORM"}, | |
61 | {317, "OP_RND"}, | |
62 | {318, "OP_SBC"}, | |
63 | {319, "OP_SUB"}, | |
64 | {320, "OP_SUBL"}, | |
65 | {321, "OP_SUBR"}, | |
66 | {322, "OP_TFR"}, | |
67 | {323, "OP_TST"}, | |
68 | {324, "OP_AND"}, | |
69 | {325, "OP_ANDI"}, | |
70 | {326, "OP_EOR"}, | |
71 | {327, "OP_LSL"}, | |
72 | {328, "OP_LSR"}, | |
73 | {329, "OP_NOT"}, | |
74 | {330, "OP_OR"}, | |
75 | {331, "OP_ORI"}, | |
76 | {332, "OP_ROL"}, | |
77 | {333, "OP_ROR"}, | |
78 | {334, "OP_BCLR"}, | |
79 | {335, "OP_BSET"}, | |
80 | {336, "OP_BCHG"}, | |
81 | {337, "OP_BTST"}, | |
82 | {338, "OP_DO"}, | |
83 | {339, "OP_ENDDO"}, | |
84 | {340, "OP_LUA"}, | |
85 | {341, "OP_MOVE"}, | |
86 | {342, "OP_MOVEC"}, | |
87 | {343, "OP_MOVEM"}, | |
88 | {344, "OP_MOVEP"}, | |
89 | {345, "OP_ILLEGAL"}, | |
90 | {346, "OP_INCLUDE"}, | |
91 | {347, "OP_JMP"}, | |
92 | {348, "OP_JCLR"}, | |
93 | {349, "OP_JSET"}, | |
94 | {350, "OP_JSR"}, | |
95 | {351, "OP_JSCLR"}, | |
96 | {352, "OP_JSSET"}, | |
97 | {353, "OP_NOP"}, | |
98 | {354, "OP_REP"}, | |
99 | {355, "OP_RESET"}, | |
100 | {356, "OP_RTI"}, | |
101 | {357, "OP_RTS"}, | |
102 | {358, "OP_STOP"}, | |
103 | {359, "OP_SWI"}, | |
104 | {360, "OP_WAIT"}, | |
105 | {361, "OP_EQU"}, | |
106 | {362, "OP_ORG"}, | |
107 | {363, "OP_DC"}, | |
108 | {364, "OP_DS"}, | |
109 | {365, "OP_DSM"}, | |
110 | {366, "OP_END"}, | |
111 | {367, "OP_PAGE"}, | |
112 | {368, "OP_PSECT"}, | |
113 | {369, "OP_ALIGN"}, | |
114 | {370, "OP_INT"}, | |
115 | {371, "SHL"}, | |
116 | {372, "SHR"}, | |
117 | {373, "OP_PI"}, | |
118 | {374, "OP_SIN"}, | |
119 | {375, "OP_COS"}, | |
120 | {376, "OP_TAN"}, | |
121 | {377, "OP_ATAN"}, | |
122 | {378, "OP_ASIN"}, | |
123 | {379, "OP_ACOS"}, | |
124 | {380, "OP_EXP"}, | |
125 | {381, "OP_LN"}, | |
126 | {382, "OP_LOG"}, | |
127 | {383, "OP_POW"}, | |
128 | }; | |
129 | #define N_TOK (sizeof tok_tab / sizeof tok_tab[0]) | |
130 | int n_tok = N_TOK; |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
11 | * | |
12 | * Permission to use, copy, modify, distribute, and sell this software | |
13 | * and its documentation for any purpose is hereby granted without fee, | |
14 | * provided that the above copyright notice appear in all copies and | |
15 | * that both that copyright notice and this permission notice appear | |
16 | * in supporting documentation. The author makes no representations | |
17 | * about the suitability of this software for any purpose. It is | |
18 | * provided "as is" without express or implied warranty. | |
19 | * | |
20 | */ | |
21 | static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; | |
22 | ||
23 | /* | |
24 | * This small program converts the a56.out file from the assembler | |
25 | * into a file suitable for loading into 56001 memory via the | |
26 | * SLOADER.ASM serial loader program provided on the Motorola | |
27 | * Dr. Bubb BBS. | |
28 | * | |
29 | */ | |
30 | ||
31 | #define MAX 256 | |
32 | ||
33 | main(argc,argv) | |
34 | int argc; | |
35 | char *argv[]; | |
36 | { | |
37 | char buf[MAX]; | |
38 | int curaddr = 0; | |
39 | int line = 0; | |
40 | int curseg = '\0'; | |
41 | int startaddr = -1; | |
42 | ||
43 | while(gets(buf)) { | |
44 | char seg; | |
45 | int addr, data; | |
46 | line++; | |
47 | if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) { | |
48 | if(seg == 'I' || seg == 'F') break; | |
49 | if(seg != curseg || curaddr != addr) { | |
50 | printf("\n_DATA %c %04X\n", curseg = seg, curaddr = addr); | |
51 | } | |
52 | if(startaddr == -1 && seg == 'P') | |
53 | startaddr = addr; | |
54 | printf("%06X ", data & 0xFFFFFF); | |
55 | curaddr++; | |
56 | } | |
57 | } | |
58 | printf("\n_END %04X\n", startaddr); | |
59 | } |
0 | /******************************************************* | |
1 | * | |
2 | * a56 - a DSP56001 assembler | |
3 | * | |
4 | * Written by Quinn C. Jensen | |
5 | * July 1990 | |
6 | * | |
7 | *******************************************************\ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 1990-1994 Quinn C. Jensen | |
11 | * | |
12 | * Permission to use, copy, modify, distribute, and sell this software | |
13 | * and its documentation for any purpose is hereby granted without fee, | |
14 | * provided that the above copyright notice appear in all copies and | |
15 | * that both that copyright notice and this permission notice appear | |
16 | * in supporting documentation. The author makes no representations | |
17 | * about the suitability of this software for any purpose. It is | |
18 | * provided "as is" without express or implied warranty. | |
19 | * | |
20 | */ | |
21 | static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; | |
22 | ||
23 | /* | |
24 | * This program converts the a56.out assembler output file into | |
25 | * raw binary, suitable for conversion to S-records for an EPROM burner. | |
26 | * | |
27 | */ | |
28 | ||
29 | ||
30 | #define MAX 256 | |
31 | ||
32 | main(argc,argv) | |
33 | int argc; | |
34 | char *argv[]; | |
35 | { | |
36 | char buf[MAX]; | |
37 | int curaddr = 0; | |
38 | int line = 0; | |
39 | ||
40 | while(gets(buf)) { | |
41 | char seg; | |
42 | int addr, data; | |
43 | line++; | |
44 | if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) { | |
45 | if(seg == 'I') { | |
46 | break; | |
47 | } else { | |
48 | if(addr < curaddr) { | |
49 | fatal("%s: input line %d: can't go back\n", argv[0], line); | |
50 | } else if(addr != curaddr) { | |
51 | while(curaddr < addr) { | |
52 | putword(0); | |
53 | curaddr++; | |
54 | } | |
55 | } | |
56 | putword(data); | |
57 | curaddr++; | |
58 | } | |
59 | } | |
60 | } | |
61 | } | |
62 | ||
63 | putword(data) | |
64 | int data; | |
65 | { | |
66 | putchar(data >> 0 & 0xFF); | |
67 | putchar(data >> 8 & 0xFF); | |
68 | putchar(data >> 16 & 0xFF); | |
69 | } |