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