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
53void 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