Codebase list a56 / 63ada6c
Import Upstream version 1.3+dfsg Thorsten Alteholz 6 years ago
17 changed file(s) with 4826 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
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;}
+2114
-0
a56.y less more
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 }
+477
-0
lex.c less more
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 }