38f6f94b6c787f5143c40bb98cdc0e7f806c8a0f
[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
29                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
30                         return ERROR;
31
32                 AMn = IMMED;
33         }
34
35         // Small problem with this is that the opening parentheses might be an
36         // expression that's part of a displacement; this code will falsely flag
37         // that as an error.
38
39         // (An)
40         // (An)+
41         // (An,Xn[.siz][*scale])
42         // (PC,Xn[.siz][*scale])
43         // (d16,An)
44         // (d8,An,Xn[.siz][*scale])
45         // (d16,PC)
46         // (d8,PC,Xn[.siz][*scale])
47         // ([bd,An],Xn,od)
48         // ([bd,An,Xn],od)
49         // ([bd,PC],Xn,od)
50         // ([bd,PC,Xn],od)
51         else if (*tok == '(')
52         {
53                 tok++;
54
55                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
56                 {
57                         AnREG = *tok++ & 7;
58
59                         if (*tok == ')')
60                         {
61                                 tok++;
62
63                                 if (*tok == '+')
64                                 {
65                                         tok++;
66                                         AMn = APOSTINC;
67                                 }
68                                 else
69                                         AMn = AIND;
70
71                                 goto AnOK;
72                         }
73
74                         AMn = AINDEXED;
75                         goto AMn_IX0;                                      // Handle ",Xn[.siz][*scale])"
76                 }
77                 else if (*tok == KW_PC)
78                 {                            // (PC,Xn[.siz][*scale]) 
79                         tok++;
80                         AMn = PCINDEXED;
81
82                         // Common index handler; enter here with `tok' pointing at the comma.
83
84                         AMn_IX0:                                           // Handle indexed with missing expr
85
86                         AnEXVAL = 0;
87                         AnEXATTR = ABS | DEFINED;
88
89                         AMn_IXN:                                           // Handle any indexed (tok -> a comma)
90
91                         if (*tok++ != ',')
92                                 goto badmode;
93
94                         if (*tok < KW_D0 || *tok > KW_A7)
95                                 goto badmode;
96
97                         AnIXREG = *tok++ & 15;
98
99                         switch ((int)*tok)
100                         {                                // Index reg size: <empty> | .W | .L 
101                         case DOTW:
102                                 tok++;
103                         default:
104                                 AnIXSIZ = 0;
105                                 break;
106                         case DOTL:
107                                 AnIXSIZ = 0x0800;
108                                 tok++;
109                                 break;
110                         case DOTB:                                      // .B not allowed here...
111                                 goto badmode;
112                         }
113
114                         if (*tok == '*')
115                         {                                  // scale: *1, *2, *4, *8 
116                                 tok++;
117
118                                 if (*tok++ != CONST || *tok > 8)
119                                         goto badmode;
120
121                                 switch ((int)*tok++)
122                                 {
123                                 case 1:
124                                         break;
125                                 case 2:
126                                         AnIXSIZ |= TIMES2;
127                                         break;
128                                 case 4:
129                                         AnIXSIZ |= TIMES4;
130                                         break;
131                                 case 8:
132                                         AnIXSIZ |= TIMES8;
133                                         break;
134                                 default:
135                                         goto badmode;
136                                 }
137                         }
138
139                         if (*tok++ != ')')                                  // final ")" 
140                                 goto badmode;
141
142                         goto AnOK;
143                 }
144                 else if (*tok == '[')
145                 {                              // ([... 
146                         goto unmode;
147                 }
148                 else
149                 {                                              // (expr... 
150                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
151                                 return ERROR;
152
153                         // It could be that this is really just an expression prefixing a
154                         // register as a displacement...
155                         if (*tok == ')')
156                         {
157                                 tok++;
158                                 goto CHK_FOR_DISPn;
159                         }
160
161                         // Otherwise, check for PC & etc displacements...
162                         if (*tok++ != ',')
163                                 goto badmode;
164
165                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
166                         {
167                                 AnREG = *tok & 7;
168                                 tok++;
169
170                                 if (*tok == ',')
171                                 {
172                                         AMn = AINDEXED;
173                                         goto AMn_IXN;
174                                 }
175                                 else if (*tok == ')')
176                                 {
177                                         AMn = ADISP;
178                                         tok++;
179                                         goto AnOK;
180                                 }
181                                 else
182                                         goto badmode;
183                         }
184                         else if (*tok == KW_PC)
185                         {
186                                 if (*++tok == ',')
187                                 {                             // expr(PC,Xn...)
188                                         AMn = PCINDEXED;
189                                         goto AMn_IXN;
190                                 }
191                                 else if (*tok == ')')
192                                 {
193                                         AMn = PCDISP;                                // expr(PC) 
194                                         tok++;
195                                         goto AnOK;
196                                 }
197                                 else
198                                         goto badmode;
199                         }
200                         else
201                                 goto badmode;
202                 }
203         }
204         else if (*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')')
205         {
206                 AMn = APREDEC;
207                 AnREG = tok[2] & 7;
208                 tok += 4;
209         }
210         else if (*tok == KW_CCR)
211         {
212                 AMn = AM_CCR;
213                 tok++;
214                 goto AnOK;
215         }
216         else if (*tok == KW_SR)
217         {
218                 AMn = AM_SR;
219                 tok++;
220                 goto AnOK;
221         }
222         else if (*tok == KW_USP)
223         {
224                 AMn = AM_USP;
225                 tok++;
226                 goto AnOK;
227         }
228         // expr
229         // expr.w
230         // expr.l
231         // d16(An)
232         // d8(An,Xn[.siz])
233         // d16(PC)
234         // d8(PC,Xn[.siz])
235         else
236         {
237                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
238                         return ERROR;
239
240 CHK_FOR_DISPn:
241                 if (*tok == DOTW)
242                 {
243                         // expr.W 
244                         tok++;
245                         AMn = ABSW;
246                         goto AnOK;
247                 }
248                 else if (*tok != '(')
249                 {
250                         // expr[.L]
251                         AMn = ABSL;
252
253                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
254                         // to absolute short
255                         if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
256                                 AMn = ABSW;
257
258                         // Is .L forced here?
259                         if (*tok == DOTL)
260                         {
261                                 tok++;
262                                 AMn = ABSL;
263                         }
264
265                         goto AnOK;
266                 }
267
268                 tok++;
269
270                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
271                 {
272                         AnREG = *tok++ & 7;
273
274                         if (*tok == ')')
275                         {
276                                 AMn = ADISP;
277                                 tok++;
278                                 goto AnOK;
279                         }
280
281                         AMn = AINDEXED;
282                         goto AMn_IXN;
283                 }
284                 else if (*tok == KW_PC)
285                 {
286                         if (*++tok == ')')
287                         {
288                                 AMn = PCDISP;
289                                 tok++;
290                                 goto AnOK;
291                         }
292
293                         AMn = PCINDEXED;
294                         goto AMn_IXN;
295                 }
296                 goto badmode;
297         }
298
299         // Addressing mode OK
300
301         AnOK:
302         ;
303 }
304
305 // Clean up dirty little macros
306 #undef AnOK
307 #undef AMn
308 #undef AnREG
309 #undef AnIXREG
310 #undef AnIXSIZ
311 #undef AnEXPR
312 #undef AnEXVAL
313 #undef AnEXATTR
314 #undef AnOEXPR
315 #undef AnOEXVAL
316 #undef AnOEXATTR
317 #undef AnESYM
318 #undef AMn_IX0
319 #undef AMn_IXN
320 #undef CHK_FOR_DISPn