]> git.sur5r.net Git - cc65/blob - src/ca65/ea65.c
4510 support: added some other small improvements:
[cc65] / src / ca65 / ea65.c
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 }