More readability cleanups.
[rmac] / parmode.h
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
7 //
8
9 // This file is included (twice) to parse two addressing modes, into slightly
10 // different var names
11 {
12         // Dn
13         // An
14         // # expression
15         if ((*tok >= KW_D0) && (*tok <= KW_D7))
16         {
17                 AMn = DREG;
18                 AnREG = *tok++ & 7;
19         }
20         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
21         {
22                 AMn = AREG;
23                 AnREG = *tok++ & 7;
24         }
25         else if (*tok == '#')
26         {
27                 ++tok;
28                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
29                         return ERROR;
30
31                 AMn = IMMED;
32         }
33         // (An)
34         // (An)+
35         // (An,Xn[.siz][*scale])
36         // (PC,Xn[.siz][*scale])
37         // (d16,An)
38         // (d8,An,Xn[.siz][*scale])
39         // (d16,PC)
40         // (d8,PC,Xn[.siz][*scale])
41         // ([bd,An],Xn,od)
42         // ([bd,An,Xn],od)
43         // ([bd,PC],Xn,od)
44         // ([bd,PC,Xn],od)
45         else if (*tok == '(')
46         {
47                 ++tok;
48
49                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
50                 {
51                         AnREG = *tok++ & 7;
52
53                         if (*tok == ')')
54                         {
55                                 ++tok;
56
57                                 if (*tok == '+')
58                                 {
59                                         ++tok;
60                                         AMn = APOSTINC;
61                                 }
62                                 else
63                                         AMn = AIND;
64
65                                 goto AnOK;
66                         }
67
68                         AMn = AINDEXED;
69                         goto AMn_IX0;                                      // Handle ",Xn[.siz][*scale])"
70                 }
71                 else if (*tok == KW_PC)
72                 {                            // (PC,Xn[.siz][*scale]) 
73                         ++tok;
74                         AMn = PCINDEXED;
75
76                         // Common index handler; enter here with `tok' pointing at the comma.
77
78                         AMn_IX0:                                           // Handle indexed with missing expr
79
80                         AnEXVAL = 0;
81                         AnEXATTR = ABS | DEFINED;
82
83                         AMn_IXN:                                           // Handle any indexed (tok -> a comma)
84
85                         if (*tok++ != ',')
86                                 goto badmode;
87
88                         if (*tok < KW_D0 || *tok > KW_A7)
89                                 goto badmode;
90
91                         AnIXREG = *tok++ & 15;
92
93                         switch ((int)*tok)
94                         {                                // Index reg size: <empty> | .W | .L 
95                         case DOTW:
96                                 ++tok;
97                         default:
98                                 AnIXSIZ = 0;
99                                 break;
100                         case DOTL:
101                                 AnIXSIZ = 0x0800;
102                                 ++tok;
103                                 break;
104                         case DOTB:                                      // .B not allowed here...
105                                 goto badmode;
106                         }
107
108                         if (*tok == '*')
109                         {                                  // scale: *1, *2, *4, *8 
110                                 ++tok;
111                                 if (*tok++ != CONST || *tok > 8)
112                                         goto badmode;
113
114                                 switch ((int)*tok++)
115                                 {
116                                 case 1:
117                                         break;
118                                 case 2:
119                                         AnIXSIZ |= TIMES2;
120                                         break;
121                                 case 4:
122                                         AnIXSIZ |= TIMES4;
123                                         break;
124                                 case 8:
125                                         AnIXSIZ |= TIMES8;
126                                         break;
127                                 default:
128                                         goto badmode;
129                                 }
130                         }
131
132                         if (*tok++ != ')')                                  // final ")" 
133                                 goto badmode;
134
135                         goto AnOK;
136                 }
137                 else if (*tok == '[')
138                 {                              // ([... 
139                         goto unmode;
140                 }
141                 else
142                 {                                              // (expr... 
143                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
144                                 return ERROR;
145
146                         if (*tok++ != ',')
147                                 goto badmode;
148
149                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
150                         {
151                                 AnREG = *tok & 7;
152                                 ++tok;
153
154                                 if (*tok == ',')
155                                 {
156                                         AMn = AINDEXED;
157                                         goto AMn_IXN;
158                                 }
159                                 else if (*tok == ')')
160                                 {
161                                         AMn = ADISP;
162                                         ++tok;
163                                         goto AnOK;
164                                 }
165                                 else
166                                         goto badmode;
167                         }
168                         else if (*tok == KW_PC)
169                         {
170                                 if (*++tok == ',')
171                                 {                             // expr(PC,Xn...)
172                                         AMn = PCINDEXED;
173                                         goto AMn_IXN;
174                                 }
175                                 else if (*tok == ')')
176                                 {
177                                         AMn = PCDISP;                                // expr(PC) 
178                                         ++tok;
179                                         goto AnOK;
180                                 }
181                                 else
182                                         goto badmode;
183                         }
184                         else
185                                 goto badmode;
186                 }
187         }
188         else if (*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')')
189         {
190                 AMn = APREDEC;
191                 AnREG = tok[2] & 7;
192                 tok += 4;
193         }
194         else if (*tok == KW_CCR)
195         {
196                 AMn = AM_CCR;
197                 ++tok;
198                 goto AnOK;
199         }
200         else if (*tok == KW_SR)
201         {
202                 AMn = AM_SR;
203                 ++tok;
204                 goto AnOK;
205         }
206         else if (*tok == KW_USP)
207         {
208                 AMn = AM_USP;
209                 ++tok;
210                 goto AnOK;
211         }
212         // expr
213         // expr.w
214         // expr.l
215         // d16(An)
216         // d8(An,Xn[.siz])
217         // d16(PC)
218         // d8(PC,Xn[.siz])
219         else
220         {
221                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
222                         return ERROR;
223
224                 if (*tok == DOTW)
225                 {                                    // expr.W 
226                         ++tok;
227                         AMn = ABSW;
228                         goto AnOK;
229                 }
230                 else if (*tok != '(')
231                 {                              // expr[.L]
232                         AMn = ABSL;
233                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized to absolute short
234
235                         if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
236                                 AMn = ABSW;
237
238                         if (*tok == DOTL)
239                         {                                 // force .L 
240                                 ++tok;
241                                 AMn = ABSL;
242                         }
243
244                         goto AnOK;
245                 }
246
247                 ++tok;
248
249                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
250                 {
251                         AnREG = *tok++ & 7;
252
253                         if (*tok == ')')
254                         {
255                                 AMn = ADISP;
256                                 ++tok;
257                                 goto AnOK;
258                         }
259
260                         AMn = AINDEXED;
261                         goto AMn_IXN;
262                 }
263                 else if (*tok == KW_PC)
264                 {
265                         if (*++tok == ')')
266                         {
267                                 AMn = PCDISP;
268                                 ++tok;
269                                 goto AnOK;
270                         }
271
272                         AMn = PCINDEXED;
273                         goto AMn_IXN;
274                 }
275                 goto badmode;
276         }
277
278         // Addressing mode OK
279
280         AnOK:
281         ;
282 }
283
284 // Cleanup dirty little macros
285 #undef AnOK
286 #undef AMn
287 #undef AnREG
288 #undef AnIXREG
289 #undef AnIXSIZ
290 #undef AnEXPR
291 #undef AnEXVAL
292 #undef AnEXATTR
293 #undef AnOEXPR
294 #undef AnOEXVAL
295 #undef AnOEXATTR
296 #undef AnESYM
297 #undef AMn_IX0
298 #undef AMn_IXN