1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* ea65.c */ |
4 | /* */ |
5 | /* 65XX effective address parsing for the ca65 macroassembler */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 1998-2011, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | /* ca65 */ |
37 | #include "ea.h" |
38 | #include "ea65.h" |
39 | #include "error.h" |
40 | #include "expr.h" |
41 | #include "instr.h" |
42 | #include "nexttok.h" |
43 | #include "global.h" |
44 | |
45 | |
46 | |
47 | /*****************************************************************************/ |
48 | /* Code */ |
49 | /*****************************************************************************/ |
50 | |
51 | |
52 | |
53 | void GetEA (EffAddr* A) |
54 | /* Parse an effective address, return the result in A */ |
55 | { |
56 | unsigned long Restrictions; |
57 | token_t IndirectEnter; |
58 | token_t IndirectLeave; |
59 | const char* IndirectExpect; |
60 | |
61 | /* Choose syntax for indirection */ |
62 | if (BracketAsIndirect) { |
63 | IndirectEnter = TOK_LBRACK; |
64 | IndirectLeave = TOK_RBRACK; |
65 | IndirectExpect = "']' expected" ; |
66 | } else { |
67 | IndirectEnter = TOK_LPAREN; |
68 | IndirectLeave = TOK_RPAREN; |
69 | IndirectExpect = "')' expected" ; |
70 | } |
71 | |
72 | /* Clear the output struct */ |
73 | A->AddrModeSet = 0; |
74 | A->Expr = 0; |
75 | |
76 | /* Handle an addressing size override */ |
77 | switch (CurTok.Tok) { |
78 | case TOK_OVERRIDE_ZP: |
79 | Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y; |
80 | NextTok (); |
81 | break; |
82 | |
83 | case TOK_OVERRIDE_ABS: |
84 | Restrictions = AM65_ABS | AM65_ABS_X | AM65_ABS_Y; |
85 | NextTok (); |
86 | break; |
87 | |
88 | case TOK_OVERRIDE_FAR: |
89 | Restrictions = AM65_ABS_LONG | AM65_ABS_LONG_X; |
90 | NextTok (); |
91 | break; |
92 | |
93 | default: |
94 | Restrictions = ~0UL; /* None */ |
95 | break; |
96 | } |
97 | |
98 | /* Parse the effective address */ |
99 | if (TokIsSep (CurTok.Tok)) { |
100 | |
101 | A->AddrModeSet = AM65_IMPLICIT; |
102 | |
103 | } else if (CurTok.Tok == TOK_HASH) { |
104 | |
105 | /* #val */ |
106 | NextTok (); |
107 | A->Expr = Expression (); |
108 | A->AddrModeSet = AM65_ALL_IMM; |
109 | |
110 | } else if (CurTok.Tok == TOK_A) { |
111 | |
112 | NextTok (); |
113 | A->AddrModeSet = AM65_ACCU; |
114 | |
115 | } else if (CurTok.Tok == IndirectEnter) { |
116 | |
117 | /* One of the indirect modes */ |
118 | NextTok (); |
119 | A->Expr = Expression (); |
120 | |
121 | if (CurTok.Tok == TOK_COMMA) { |
122 | |
123 | /* (expr,X) or (rel,S),y */ |
124 | NextTok (); |
125 | if (CurTok.Tok == TOK_X) { |
126 | /* (adr,x) */ |
127 | NextTok (); |
128 | A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND; |
129 | Consume (IndirectLeave, IndirectExpect); |
130 | } else if (CurTok.Tok == TOK_S) { |
131 | /* (rel,s),y */ |
132 | NextTok (); |
133 | A->AddrModeSet = AM65_STACK_REL_IND_Y; |
134 | Consume (IndirectLeave, IndirectExpect); |
135 | ConsumeComma (); |
136 | Consume (TOK_Y, "'Y' expected" ); |
137 | } else { |
138 | Error ("Syntax error" ); |
139 | } |
140 | |
141 | } else { |
142 | |
143 | /* (adr), (adr),y or (adr),z */ |
144 | Consume (IndirectLeave, IndirectExpect); |
145 | if (CurTok.Tok == TOK_COMMA) { |
146 | /* (adr),y */ |
147 | NextTok (); |
148 | switch (CurTok.Tok) { |
149 | case TOK_Z: |
150 | /* only set by scanner.c if in 4510-mode */ |
151 | NextTok (); |
152 | A->AddrModeSet = AM65_DIR_IND; |
153 | break; |
154 | default: |
155 | Consume (TOK_Y, "'Y' expected" ); |
156 | A->AddrModeSet = AM65_DIR_IND_Y; |
157 | break; |
158 | } |
159 | } else { |
160 | /* (adr) */ |
161 | A->AddrModeSet = (CPU == CPU_4510) ? AM65_ABS_IND |
162 | : AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND; |
163 | } |
164 | } |
165 | |
166 | } else if (CurTok.Tok == TOK_LBRACK) { |
167 | |
168 | /* Never executed if BracketAsIndirect feature is enabled. */ |
169 | /* [dir] or [dir],y */ |
170 | NextTok (); |
171 | A->Expr = Expression (); |
172 | Consume (TOK_RBRACK, "']' expected" ); |
173 | if (CurTok.Tok == TOK_COMMA) { |
174 | /* [dir],y */ |
175 | NextTok (); |
176 | Consume (TOK_Y, "'Y' expected" ); |
177 | A->AddrModeSet = AM65_DIR_IND_LONG_Y; |
178 | } else { |
179 | /* [dir] */ |
180 | A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG; |
181 | } |
182 | |
183 | } else { |
184 | |
185 | /* Remaining stuff: |
186 | ** |
187 | ** adr |
188 | ** adr,x |
189 | ** adr,y |
190 | ** adr,s |
191 | */ |
192 | A->Expr = Expression (); |
193 | |
194 | if (CurTok.Tok == TOK_COMMA) { |
195 | |
196 | NextTok (); |
197 | switch (CurTok.Tok) { |
198 | |
199 | case TOK_X: |
200 | A->AddrModeSet = AM65_ABS_LONG_X | AM65_ABS_X | AM65_DIR_X; |
201 | NextTok (); |
202 | break; |
203 | |
204 | case TOK_Y: |
205 | A->AddrModeSet = AM65_ABS_Y | AM65_DIR_Y; |
206 | NextTok (); |
207 | break; |
208 | |
209 | case TOK_S: |
210 | A->AddrModeSet = AM65_STACK_REL; |
211 | NextTok (); |
212 | break; |
213 | |
214 | default: |
215 | Error ("Syntax error" ); |
216 | |
217 | } |
218 | |
219 | } else { |
220 | |
221 | A->AddrModeSet = AM65_ABS_LONG | AM65_ABS | AM65_DIR; |
222 | |
223 | } |
224 | } |
225 | |
226 | /* Apply addressing mode overrides */ |
227 | A->AddrModeSet &= Restrictions; |
228 | } |
229 | |