Code cleanup from last patch, also, version bump for same. :-)
[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, 2017 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_D0) && (*tok <= KW_D7))
78                 {
79                         //Since index register isn't used here, store register number in this field
80                         AnIXREG = *tok++ & 7;                                // (Dn)
81                         if (*tok == ')')
82                         {
83                                 tok++;
84                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
85                                 AnEXTEN |= EXT_BS;          // Base register suppressed
86                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
87                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
88                                 AMn= MEMPOST;
89                                 AnREG = 6 << 3;         // stuff 110 to mode field
90                                 goto AnOK;
91                         }
92                         else if (*tok == 'L')
93                         {
94                                 // TODO: does DINDL gets used at all?
95                                 //AMn=DINDL;                                     // (Dn.l)
96                                 //AnEXTEN = 1 << 1;   // Long index size
97                                 //tok++;
98                         }
99                         else if (*tok == 'W')                                // (Dn.w)
100                         {
101                                 // TODO: does DINDW gets used at all?
102                                 //AMn=DINDW;
103                                 //AnEXTEN = 1 << 1;   // Word index size
104                                 //tok++;
105                         }
106                         else if (*tok == ',')
107                         {
108                                 // ([bd,An],Xn..) without bd, An
109                                 // Base displacement is suppressed
110                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
111                                 AnEXTEN |= EXT_BS;          // Base register suppressed
112                                 AnEXTEN |= EXT_BDSIZE0;
113                                 AnREG = 6 << 3;         // stuff 110 to mode field
114                                 tok++;
115                                 goto CHECKODn;
116                         }
117                         else
118                                 return error("(Dn) error");
119
120                         if (*tok == ')')
121                         {
122                                 tok++;
123                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
124                                 AnEXTEN |= EXT_BS;          // Base register suppressed
125                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
126                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
127                                 AnREG = 6 << 3;         // stuff 110 to mode field
128                                 AMn = MEMPOST;
129                                 goto AnOK;
130                         }
131                         else
132                                 return error("unhandled so far");
133                 }
134                 else if (*tok == KW_PC)
135                 {                            // (PC,Xn[.siz][*scale])
136                         tok++;
137                         AMn = PCINDEXED;
138
139                         // Common index handler; enter here with 'tok' pointing at the
140                         // comma.
141
142                         AMn_IX0:                 // Handle indexed with missing expr
143
144                         AnEXVAL = 0;
145                         AnEXATTR = ABS | DEFINED;
146
147                         AMn_IXN:                 // Handle any indexed (tok -> a comma)
148
149                         if (*tok++ != ',')
150                                 goto badmode;
151
152                         if (*tok < KW_D0 || *tok > KW_A7)
153                                 goto badmode;
154
155                         AnIXREG = *tok++ & 15;
156
157                         switch ((int)*tok)
158                         {                        // Index reg size: <empty> | .W | .L
159                         case DOTW:
160                                 tok++;
161                         default:
162                                 AnIXSIZ = 0;
163                                 break;
164                         case DOTL:
165                                 AnIXSIZ = 0x0800;
166                                 tok++;
167                                 break;
168                         case DOTB:               // .B not allowed here...
169                                 goto badmode;
170                         }
171
172                         if (*tok == '*')
173                         {                        // scale: *1, *2, *4, *8
174                                 tok++;
175
176                                 if (*tok++ != CONST || *tok > 8)
177                                         goto badmode;
178
179                                 switch ((int)*tok++)
180                                 {
181                                 case 1:
182                                         break;
183                                 case 2:
184                                         AnIXSIZ |= TIMES2;
185                                         break;
186                                 case 4:
187                                         AnIXSIZ |= TIMES4;
188                                         break;
189                                 case 8:
190                                         AnIXSIZ |= TIMES8;
191                                         break;
192                                 default:
193                                         goto badmode;
194                                 }
195                         }
196
197                         if (*tok++ != ')')         // final ")"
198                                 goto badmode;
199
200                         goto AnOK;
201                 }
202                 else if (*tok == '[')
203                 {                              // ([...
204                         tok++;
205                         AnEXTEN|=EXT_FULLWORD;     //Definitely using full extension format, so set bit 8
206                         // Check to see if base displacement is present
207                         //WARNING("expr will return a bad expression error here but this is expected, it needs to be silenced!");
208                         if (*tok!=CONST && *tok !=SYMBOL)
209                         //if (expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM) != OK)
210                         {
211                                 AnEXTEN|=EXT_BDSIZE0;
212                                 //tok++;
213                                 //tok--;                 //Rewind tok since expr advances it forward
214                         }
215                         else
216                         {
217                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
218                                 if (optim_flags[OPT_BASE_DISP] && AnBEXVAL==0 && AnEXATTR!=0)
219                                 {
220                                         // bd=0 so let's optimise it out
221                                         AnEXTEN|=EXT_BDSIZE0;
222                                 }
223                                 else if (*tok==DOTL)
224                                 {                                                  // ([bd.l,...
225                                                 AnEXTEN|=EXT_BDSIZEL;
226                                                 tok++;
227                                 }
228                                 else
229                                 {                                                  // ([bd[.w],... or ([bd,...
230                                         // Is .W forced here?
231                                         if (*tok == DOTW)
232                                         {
233                                         AnEXTEN|=EXT_BDSIZEW;
234                                                 tok++;
235                                         }
236                                         else
237                                         {
238                                                 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
239                                                 // to absolute short
240                                                 if (optim_flags[OPT_ABS_SHORT]
241                                                         && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
242                                                         && ((AnBEXVAL + 0x8000) < 0x10000))
243                                                 {
244                                                         AnEXTEN |= EXT_BDSIZEW;
245                                                         warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
246                                                 }
247                                                 else
248                                                 {
249                                                         AnEXTEN |= EXT_BDSIZEL;
250                                                 }
251                                         }
252                                 }
253
254                                 if (*tok == ',')
255                                         tok++;
256                                 //else
257                                 //      return error("Comma expected after base displacement");
258                         }
259
260                         // Check for address register or PC, suppress base register
261                         // otherwise
262
263                         if (*tok == KW_PC)
264                         {                                       // ([bd,PC,...
265                                 AnREG = (7 << 3) | 3;   // PC is special case - stuff 011 to register field and 111 to the mode field
266                                 tok++;
267                         }
268                         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
269                         {                                       // ([bd,An,...
270                                 AnREG = (6<<3)|*tok & 7;
271                                 tok++;
272                         }
273                         else if ((*tok >= KW_D0) && (*tok <= KW_D7))
274                         {
275                                 // ([bd,Dn,...
276                                 AnREG = (6 << 3);
277                                 AnEXTEN |= ((*tok & 7) << 12);
278                                 AnEXTEN |= EXT_D;
279                                 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
280                                 tok++;
281
282                                 // Check for size
283                                 {
284                                         // ([bd,An/PC],Xn.W/L...)
285                                         switch ((int)*tok)
286                                         {
287                                         // Index reg size: <empty> | .W | .L
288                                         case DOTW:
289                                                 tok++;
290                                                 break;
291                                         default:
292                                                 break;
293                                         case DOTL:
294                                                 AnEXTEN |= EXT_L;
295                                                 tok++;
296                                                 break;
297                                         case DOTB:
298                                                 // .B not allowed here...
299                                                 goto badmode;
300                                         }
301                                 }
302
303                                 // Check for scale
304                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
305                                 {
306                                         tok++;
307
308                                         if (*tok == CONST)      // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
309                                                 tok++;
310
311                                         switch ((int)*tok++)
312                                         {
313                                         case 1:
314                                                 break;
315                                         case 2:
316                                                 AnEXTEN |= EXT_TIMES2;
317                                                 break;
318                                         case 4:
319                                                 AnEXTEN |= EXT_TIMES4;
320                                                 break;
321                                         case 8:
322                                                 AnEXTEN |= EXT_TIMES8;
323                                                 break;
324                                         default:
325                                                 goto badmode;
326                                         }
327                                 }
328
329                                 if (*tok == ']')  // ([bd,Dn]...
330                                 {
331                                         tok++;
332                                         goto IS_SUPPRESSEDn;
333                                 }
334                         }
335                         else if (*tok == ']')
336                         {
337                                 // PC and Xn is suppressed
338                                 AnREG = 6 << 3;         // stuff 110 to mode field
339                                 //AnEXTEN|=EXT_BS|EXT_IS;
340                                 AnEXTEN |= EXT_BS;
341                         }
342                         else
343                         {
344                                 goto badmode;
345                         }
346
347                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
348                         if (*tok == ']')
349                         {
350                                 //([bd,An/PC],Xn,od)
351                                 // Check for Xn
352                                 tok++;
353
354                                 if (*tok == ')')
355                                 {
356                                         //Xn and od are non existent, get out of jail free card
357                                         AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
358                                         AnEXTEN |= EXT_IS | EXT_IISPREN;        //Suppress Xn and od
359                                         tok++;
360                                         goto AnOK;
361                                 }
362                                 else if (*tok != ',')
363                                         return error("comma expected after ]");
364                                 else
365                                         tok++;                          // eat the comma
366
367                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
368                                 {
369                                         AnIXREG = ((*tok & 7) << 12);
370                                         AnEXTEN |= EXT_A;
371                                         tok++;
372                                 }
373                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
374                                 {
375                                         AnEXTEN |= ((*tok & 7) << 12);
376                                         AnEXTEN |= EXT_D;
377                                         tok++;
378                                 }
379                                 else
380                                 {
381                                         //No index found, suppress it
382                                         AnEXTEN |= EXT_IS;
383                                         tok--;                                                  // Rewind tok to point to the comma
384                                         goto IS_SUPPRESSEDn;                    // https://xkcd.com/292/ - what does he know anyway?
385                                 }
386
387                                 // Check for size
388                                 {
389                                         // ([bd,An/PC],Xn.W/L...)
390                                         switch ((int)*tok)
391                                         {
392                                         // Index reg size: <empty> | .W | .L
393                                         case DOTW:
394                                                 tok++;
395                                                 break;
396                                         default:
397                                                 break;
398                                         case DOTL:
399                                                 AnEXTEN |= EXT_L;
400                                                 tok++;
401                                                 break;
402                                         case DOTB:
403                                                 // .B not allowed here...
404                                                 goto badmode;
405                                         }
406                                 }
407
408                                 // Check for scale
409                                 if (*tok == '*')
410                                 {
411                                         // ([bd,An/PC],Xn*...)
412                                         tok++;
413
414                                         if (*tok == CONST)      // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
415                                                 tok++;
416
417                                         switch ((int)*tok++)
418                                         {
419                                         case 1:
420                                                 break;
421                                         case 2:
422                                                 AnEXTEN |= EXT_TIMES2;
423                                                 break;
424                                         case 4:
425                                                 AnEXTEN |= EXT_TIMES4;
426                                                 break;
427                                         case 8:
428                                                 AnEXTEN |= EXT_TIMES8;
429                                                 break;
430                                         default:
431                                                 goto badmode;
432                                         }
433                                 }
434
435                                 // Check for od
436                                 if (*tok == ')')        // ([bd,An/PC],Xn)
437                                 {
438                                         //od is non existant, get out of jail free card
439                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
440                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
441                                         tok++;
442                                         goto AnOK;
443                                 }
444                                 else if (*tok!=',')
445                                         return error("comma expected");
446                                 else
447                                         tok++;  // eat the comma
448
449                                 CHECKODn:
450
451                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
452                                         goto badmode;
453
454                                 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
455                                 {
456                                         // od=0 so optimise it out
457                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
458                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
459                                         tok++;
460                                         goto AnOK;
461                                 }
462
463                                 // ([bd,An/PC],Xn,od)
464                                 if (*tok == DOTL)
465                                 {
466                                         // expr.L
467                                         AnEXTEN |= EXT_IISPOSL; // Long outer displacement
468                                         AMn = MEMPOST;
469
470                                         // Defined, absolute values from $FFFF8000..$00007FFF get
471                                         // optimized to absolute short
472                                         if (optim_flags[OPT_ABS_SHORT]
473                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
474                                                 && ((AnEXVAL + 0x8000) < 0x10000))
475                                         {
476                                                 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
477                                                 AMn = MEMPOST;
478                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
479                                         }
480
481                                 }
482                                 else
483                                 {
484                                         // expr[.W]
485                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
486                                         AMn = MEMPOST;
487
488                                         // Is .W forced here?
489                                         if (*tok == DOTW)
490                                         {
491                                                 tok++;
492                                         }
493                                 }
494
495                                 // Check for final closing parenthesis
496                                 if (*tok == ')')
497                                 {
498                                         tok++;
499                                         goto AnOK;
500                                 }
501                                 else
502                                         return error("Closing parenthesis missing on addressing mode");
503
504                                 IS_SUPPRESSEDn:
505
506                                 // Check for od
507                                 if (*tok == ')')        // ([bd,An/PC],Xn)
508                                 {
509                                         //od is non existant, get out of jail free card
510                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
511                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
512                                         tok++;
513                                         goto AnOK;
514                                 }
515                                 else if (*tok!=',')
516                                         return error("comma expected");
517                                 else
518                                         tok++;  // eat the comma
519
520                 if ((*tok != CONST) && (*tok != SYMBOL))
521                                         goto badmode;
522
523                                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
524
525                                 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
526                                 {
527                                         // od=0 so optimise it out
528                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
529                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
530                                         tok++;
531                                         goto AnOK;
532                                 }
533
534                                 // ([bd,An/PC],Xn,od)
535                                 if (*tok == DOTL)
536                                 {
537                                         // expr.L
538                                         tok++;
539                                         AMn = MEMPOST;
540                                         AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
541                                 }
542                                 else
543                                 {
544                                         // expr[.W][]
545                                         AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
546                                         AMn = MEMPRE;
547
548                                         if (*tok == DOTW)
549                                         {
550                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
551                                                 AMn = MEMPOST;
552                                                 tok++;
553                                         }
554
555                                         // Defined, absolute values from $FFFF8000..$00007FFF get
556                                         // optimized to absolute short
557                                         else if (optim_flags[OPT_BASE_DISP]
558                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
559                                                 && ((AnEXVAL + 0x8000) < 0x10000))
560                                         {
561                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
562                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
563                                         }
564                                 }
565
566                                 // Check for final closing parenthesis
567                                 if (*tok == ')')
568                                 {
569                                         tok++;
570                                         goto AnOK;
571                                 }
572                                 else
573                                         return error("Closing parenthesis missing on addressing mode");
574                         }
575                         else if (*tok == ',')
576                         {
577                                 *tok++;                 // ([bd,An,Xn.size*scale],od)
578
579                                 //Check for Xn
580                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
581                                 {
582                                         AnEXTEN |= ((*tok & 7) << 12);
583                                         AnEXTEN |= EXT_A;
584                                         tok++;
585                                 }
586                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
587                                 {
588                                         AnEXTEN |= ((*tok & 7) << 12);
589                                         AnEXTEN |= EXT_D;
590                                         tok++;
591                                 }
592
593                                 // Check for size
594                                 {
595                                         // ([bd,An/PC],Xn.W/L...)
596                                         switch ((int)*tok)
597                                         {
598                                         // Index reg size: <empty> | .W | .L
599                                         case DOTW:
600                                                 tok++;
601                                                 break;
602                                         default:
603                                                 break;
604                                         case DOTL:
605                                                 tok++;
606                                                 AnEXTEN |= EXT_L;
607                                                 break;
608                                         case DOTB:
609                                                 // .B not allowed here...
610                                                 goto badmode;
611                                         }
612                                 }
613
614                                 // Check for scale
615                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
616                                 {
617                                         tok++;
618
619                                         if (*tok == CONST)      // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
620                                                 tok++;
621
622                                         switch ((int)*tok++)
623                                         {
624                                         case 1:
625                                                 break;
626                                         case 2:
627                                                 AnEXTEN |= EXT_TIMES2;
628                                                 break;
629                                         case 4:
630                                                 AnEXTEN |= EXT_TIMES4;
631                                                 break;
632                                         case 8:
633                                                 AnEXTEN |= EXT_TIMES8;
634                                                 break;
635                                         default:
636                                                 goto badmode;
637                                         }
638                                 }
639
640                                 //Check for ]
641                                 if (*tok != ']')
642                                         return error("Expected closing bracket ]");
643
644                                 tok++;                  // Eat the bracket
645
646                                 //Check for od
647                                 if (*tok == ')')        // ([bd,An/PC,Xn]...
648                                 {
649                                         //od is non existant, get out of jail free card
650                                         //AnEXVAL=0;            // zero outer displacement
651                                         AMn = MEMPRE;                   // let's say it's ([bd,An,Xn],od) with od suppressed then
652                                         AnEXTEN |= EXT_IISPREN; // No outer displacement
653                                         tok++;
654                                         goto AnOK;
655                                 }
656                                 else if (*tok++!=',')
657                                         return error("comma expected after ]");
658
659                                 WARNING(Put symbol and constant checks here!)
660
661                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
662                                         goto badmode;
663
664                                 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
665                                 {
666                                         // od=0 so optimise it out
667                                         AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
668                                         AnEXTEN |= EXT_IISPRE0; // No outer displacement
669                                         tok++;
670                                         goto AnOK;
671                                 }
672
673                                 // ([bd,An/PC,Xn],od)
674                                 if (*tok == DOTL)
675                                 {
676                                         // expr.L
677                                         AMn = MEMPRE;
678                                         tok++;
679                                         AnEXTEN |= EXT_IISPREL;
680                                 }
681                                 else
682                                 {
683                                         // expr.[W]
684                                         //tok++;
685
686                                         AnEXTEN |= EXT_IISPREW;
687                                         AMn = MEMPRE;
688
689                     // Is .W forced here?
690                                         if (*tok == DOTW)
691                                         {
692                                                 tok++;
693                                         }
694
695                                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
696                                         // to absolute short
697                                         else if (optim_flags[OPT_BASE_DISP]
698                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
699                                                 && ((AnEXVAL + 0x8000) < 0x10000))
700                                         {
701                                                 AnEXTEN |= EXT_IISPREW;
702                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
703                                         }
704                                 }
705
706                                 // Check for final closing parenthesis
707                                 if (*tok == ')')
708                                 {
709                                         tok++;
710                                         goto AnOK;
711                                 }
712                                 else
713                                         return error("Closing parenthesis missing on addressing mode");
714                         }
715                         else
716                                 goto badmode;
717                 }
718                 else
719                 {
720                         // (expr...
721                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
722                                 return ERROR;
723
724                         // It could be that this is really just an expression prefixing a
725                         // register as a displacement...
726                         if (*tok == ')')
727                         {
728                                 tok++;
729                                 goto CHK_FOR_DISPn;
730                         }
731
732                         // Otherwise, check for PC & etc displacements...
733                         if (*tok++ != ',')
734                                 goto badmode;
735
736                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
737                         {
738                                 AnREG = *tok & 7;
739                                 tok++;
740
741                                 if (*tok == ',')
742                                 {
743                                         AMn = AINDEXED;
744                                         goto AMn_IXN;
745                                 }
746                                 else if (*tok == ')')
747                                 {
748                                         AMn = ADISP;
749                                         tok++;
750                                         goto AnOK;
751                                 }
752                                 else
753                                         goto badmode;
754                         }
755                         else if (*tok == KW_PC)
756                         {
757                                 if (*++tok == ',')
758                                 {                             // expr(PC,Xn...)
759                                         AMn = PCINDEXED;
760                                         goto AMn_IXN;
761                                 }
762                                 else if (*tok == ')')
763                                 {
764                                         AMn = PCDISP;                                // expr(PC)
765                                         tok++;
766                                         goto AnOK;
767                                 }
768                                 else
769                                         goto badmode;
770                         }
771                         else
772                                 goto badmode;
773                 }
774         }
775         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
776         {
777                 AMn = APREDEC;
778                 AnREG = tok[2] & 7;
779                 tok += 4;
780         }
781         else if (*tok == KW_CCR)
782         {
783                 AMn = AM_CCR;
784                 tok++;
785                 goto AnOK;
786         }
787         else if (*tok == KW_SR)
788         {
789                 AMn = AM_SR;
790                 tok++;
791                 goto AnOK;
792         }
793         else if (*tok == KW_USP)
794         {
795                 AMn = AM_USP;
796                 tok++;
797                 AnREG = 2;      //Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
798                 goto AnOK;
799         }
800         else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
801         {
802                 AMn = CACHES;
803                 AnREG = *tok++ - KW_IC40;
804
805                 // After a cache keyword only a comma or EOL is allowed
806                 if ((*tok != ',') && (*tok != EOL))
807                         return ERROR;
808
809                 goto AnOK;
810         }
811         else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
812         {
813                 AMn = CREG;
814                 AnREG = (*tok++) - KW_SFC;
815                 goto AnOK;
816         }
817         else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
818         {
819                 AMn = FREG;
820                 AnREG = (*tok++ & 7);
821         }
822         else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
823         {
824                 AMn = FPSCR;
825                 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
826         }
827         // expr
828         // expr.w
829         // expr.l
830         // d16(An)
831         // d8(An,Xn[.siz])
832         // d16(PC)
833         // d8(PC,Xn[.siz])
834         else
835         {
836                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
837                         return ERROR;
838
839 CHK_FOR_DISPn:
840                 if (*tok == DOTW)
841                 {
842                         // expr.W
843                         tok++;
844                         AMn = ABSW;
845
846                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
847                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
848
849                         goto AnOK;
850                 }
851                 else if (*tok != '(')
852                 {
853                         // expr[.L]
854                         AMn = ABSL;
855
856                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
857                         // to absolute short
858                         if (optim_flags[OPT_ABS_SHORT]
859                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
860                                 && ((AnEXVAL + 0x8000) < 0x10000))
861                         {
862                                 AMn = ABSW;
863
864                                 if (sbra_flag)
865                                         warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
866                         }
867
868                         // Is .L forced here?
869                         if (*tok == DOTL)
870                         {
871                                 tok++;
872                                 AMn = ABSL;
873                         }
874
875                         goto AnOK;
876                 }
877
878                 tok++;
879
880                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
881                 {
882                         AnREG = *tok++ & 7;
883
884                         if (*tok == ')')
885                         {
886                                 AMn = ADISP;
887                                 tok++;
888                                 goto AnOK;
889                         }
890
891                         AMn = AINDEXED;
892                         goto AMn_IXN;
893                 }
894                 else if (*tok == KW_PC)
895                 {
896                         if (*++tok == ')')
897                         {
898                                 AMn = PCDISP;
899                                 tok++;
900                                 goto AnOK;
901                         }
902
903                         AMn = PCINDEXED;
904                         goto AMn_IXN;
905                 }
906                 goto badmode;
907         }
908
909         // Addressing mode OK
910 AnOK:
911         ;
912 }
913
914 // Clean up dirty little macros
915 #undef AnOK
916 #undef AMn
917 #undef AnREG
918 #undef AnIXREG
919 #undef AnIXSIZ
920 #undef AnEXPR
921 #undef AnEXVAL
922 #undef AnEXATTR
923 #undef AnOEXPR
924 #undef AnOEXVAL
925 #undef AnOEXATTR
926 #undef AnESYM
927 #undef AMn_IX0
928 #undef AMn_IXN
929 #undef CHK_FOR_DISPn
930 #undef AnBEXPR
931 #undef AnBEXVAL
932 #undef AnBEXATTR
933 #undef AnBZISE
934 #undef AnEXTEN
935 #undef AMn_030
936 #undef IS_SUPPRESSEDn
937 #undef CHECKODn