]> Shamusworld >> Repos - rmac/blob - parmode.h
Fix for addressing mode base value getting clobbered by scale value
[rmac] / parmode.h
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011-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         uint64_t scaleval;                      // Expression's value
13         TOKEN scaleexpr[EXPRSIZE];      // Expression
14         WORD scaleattr;                         // Expression's attribute
15         SYM * scaleesym;                        // External symbol involved in expr
16
17         // Dn
18         // An
19         // # expression
20         if ((*tok >= KW_D0) && (*tok <= KW_D7))
21         {
22                 AMn = DREG;
23                 AnREG = *tok++ & 7;
24         }
25         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
26         {
27                 AMn = AREG;
28                 AnREG = *tok++ & 7;
29         }
30         else if (*tok == '#')
31         {
32                 tok++;
33
34                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
35                         return ERROR;
36
37                 AMn = IMMED;
38         }
39
40         // Small problem with this is that the opening parentheses might be an
41         // expression that's part of a displacement; this code will falsely flag
42         // that as an error.
43
44         // (An)
45         // (An)+
46         // (An,Xn[.siz][*scale])
47         // (PC,Xn[.siz][*scale])
48         // (d16,An)
49         // (d8,An,Xn[.siz][*scale])
50         // (d16,PC)
51         // (d8,PC,Xn[.siz][*scale])
52         // ([bd,An],Xn[.siz][*scale],od)
53         // ([bd,An,Xn[.siz][*scale]],od)
54         // ([bd,PC],Xn[.siz][*scale],od)
55         // ([bd,PC,Xn[.siz][*scale]],od)
56         else if (*tok == '(')
57         {
58                 tok++;
59
60                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
61                 {
62                         AnREG = *tok++ & 7;
63
64                         if (*tok == ')')
65                         {
66                                 tok++;
67
68                                 if (*tok == '+')
69                                 {
70                                         tok++;
71                                         AMn = APOSTINC;
72                                 }
73                                 else
74                                         AMn = AIND;
75
76                                 goto AnOK;
77                         }
78
79                         AMn = AINDEXED;
80                         goto AMn_IX0;            // Handle ",Xn[.siz][*scale])"
81                 }
82                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
83                 {
84                         //Since index register isn't used here, store register number in this field
85                         AnIXREG = *tok++ & 7;                                // (Dn)
86
87                         if (*tok == ')')
88                         {
89                                 tok++;
90                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
91                                 AnEXTEN |= EXT_BS;          // Base register suppressed
92                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
93                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
94                                 AMn = MEMPOST;
95                                 AnREG = 6 << 3;         // stuff 110 to mode field
96                                 goto AnOK;
97                         }
98                         else if (*tok == 'L')
99                         {
100                                 AMn = DINDL;                                                                     // (Dn.l)
101                                 AnEXTEN = 1 << 11;   // Long index size
102                                 tok++;
103                         }
104                         else if (*tok == 'W')                                // (Dn.w)
105                         {
106                                 AMn = DINDW;
107                                 AnEXTEN = 0 << 11;   // Word index size
108                                 tok++;
109                         }
110                         else if (*tok == ',')
111                         {
112                                 // ([bd,An],Xn..) without bd, An
113                                 // Base displacement is suppressed
114                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
115                                 AnEXTEN |= EXT_BS;          // Base register suppressed
116                                 AnEXTEN |= EXT_BDSIZE0;
117                                 AnREG = 6 << 3;         // stuff 110 to mode field
118                                 tok++;
119                                 goto CHECKODn;
120                         }
121                         else
122                         {
123                                 return error("(Dn) error");
124                         }
125
126                         if (*tok == '*')
127                         {                        // scale: *1, *2, *4, *8
128                                 tok++;
129
130                                 if (*tok == SYMBOL)
131                                 {
132                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
133                                                 return error("scale factor expression must evaluate");
134
135                                         switch (scaleval)
136                                         {
137                                         case 1:
138                                                 break;
139                                         case 2:
140                                                 AnIXSIZ |= TIMES2;
141                                                 AnEXTEN |= 1 << 9;
142                                                 break;
143                                         case 4:
144                                                 AnIXSIZ |= TIMES4;
145                                                 AnEXTEN |= 2 << 9;
146                                                 break;
147                                         case 8:
148                                                 AnIXSIZ |= TIMES8;
149                                                 AnEXTEN |= 3 << 9;
150                                                 break;
151                                         default:
152                                                 goto badmode;
153                                         }
154                                 }
155                                 else if (*tok++ != CONST)
156                                         goto badmode;
157                                 else
158                                 {
159                                         switch ((int)*tok++)
160                                         {
161                                         case 1:
162                                                 break;
163                                         case 2:
164                                                 AnIXSIZ |= TIMES2;
165                                                 AnEXTEN |= 1 << 9;
166                                                 break;
167                                         case 4:
168                                                 AnIXSIZ |= TIMES4;
169                                                 AnEXTEN |= 2 << 9;
170                                                 break;
171                                         case 8:
172                                                 AnIXSIZ |= TIMES8;
173                                                 AnEXTEN |= 3 << 9;
174                                                 break;
175                                         default:
176                                                 goto badmode;
177                                         }
178
179                                         tok++;  // Take into account that constants are 64-bit
180                                 }
181                         }
182
183                         if (*tok == ')')
184                         {
185                                 tok++;
186                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
187                                 AnEXTEN |= EXT_BS;          // Base register suppressed
188                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
189                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
190                                 AnREG = 6 << 3;         // stuff 110 to mode field
191                                 AMn = MEMPOST;
192                                 goto AnOK;
193                         }
194                         else if (*tok == ',')
195                         {
196                                 tok++;  // eat the comma
197                                 // It might be (Dn[.wl][*scale],od)
198                                 // Maybe this is wrong and we have to write some code here
199                                 // instead of reusing that path...
200                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null - suppressed
201                                 goto CHECKODn;
202                         }
203                         else
204                                 return error("unhandled so far");
205                 }
206                 else if (*tok == KW_PC)
207                 {                            // (PC,Xn[.siz][*scale])
208                         tok++;
209                         AMn = PCINDEXED;
210
211                         // Common index handler; enter here with 'tok' pointing at the
212                         // comma.
213
214                         AMn_IX0:                 // Handle indexed with missing expr
215
216                         AnEXVAL = 0;
217                         AnEXATTR = ABS | DEFINED;
218
219                         AMn_IXN:                 // Handle any indexed (tok -> a comma)
220
221                         if (*tok++ != ',')
222                                 goto badmode;
223
224                         if (*tok < KW_D0 || *tok > KW_A7)
225                                 goto badmode;
226
227                         AnIXREG = *tok++ & 15;
228
229                         switch ((int)*tok)
230                         {                        // Index reg size: <empty> | .W | .L
231                         case DOTW:
232                                 tok++;
233                         default:
234                                 AnIXSIZ = 0;
235                                 break;
236                         case DOTL:
237                                 AnIXSIZ = 0x0800;
238                                 tok++;
239                                 break;
240                         case DOTB:               // .B not allowed here...
241                                 goto badmode;
242                         }
243
244                         if (*tok == '*')
245                         {                        // scale: *1, *2, *4, *8
246                                 tok++;
247
248                                 if (*tok == SYMBOL)
249                                 {
250                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
251                                                 return error("scale factor expression must evaluate");
252                                         switch (scaleval)
253                                         {
254                                         case 1:
255                                                 break;
256                                         case 2:
257                                                 AnIXSIZ |= TIMES2;
258                                                 break;
259                                         case 4:
260                                                 AnIXSIZ |= TIMES4;
261                                                 break;
262                                         case 8:
263                                                 AnIXSIZ |= TIMES8;
264                                                 break;
265                                         default:
266                                                 goto badmode;
267                                         }
268                                 }
269                                 else if (*tok++ != CONST)
270                                         goto badmode;
271                                 else
272                                 {
273                                         switch ((int)*tok++)
274                                         {
275                                         case 1:
276                                                 break;
277                                         case 2:
278                                                 AnIXSIZ |= TIMES2;
279                                                 break;
280                                         case 4:
281                                                 AnIXSIZ |= TIMES4;
282                                                 break;
283                                         case 8:
284                                                 AnIXSIZ |= TIMES8;
285                                                 break;
286                                         default:
287                                                 goto badmode;
288                                         }
289
290                                         tok++;  // Take into account that constants are 64-bit
291                                 }
292                         }
293
294                         if (*tok == ',')
295                         {
296                                 // If we got here we didn't get any [] stuff
297                                 // so let's suppress base displacement before
298                                 // branching off
299                                 tok++;
300                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null - suppressed
301                                 goto CHECKODn;
302                         }
303                         if (*tok++ != ')')         // final ")"
304                                 goto badmode;
305
306                         goto AnOK;
307                 }
308                 else if (*tok == '[')
309                 {                              // ([...
310                         tok++;
311                         AnEXTEN |= EXT_FULLWORD;     // Definitely using full extension format, so set bit 8
312
313                         // Check to see if base displacement is present
314                         if (*tok != CONST && *tok != SYMBOL)
315                         {
316                                 AnEXTEN |= EXT_BDSIZE0;
317                         }
318                         else
319                         {
320                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
321                                 if (CHECK_OPTS(OPT_BASE_DISP) && AnBEXVAL == 0 && AnEXATTR != 0)
322                                 {
323                                         // bd=0 so let's optimise it out
324                                         AnEXTEN|=EXT_BDSIZE0;
325                                 }
326                                 else if (*tok == DOTL)
327                                 {                                               // ([bd.l,...
328                                                 AnEXTEN |= EXT_BDSIZEL;
329                                                 tok++;
330                                 }
331                                 else
332                                 {                                               // ([bd[.w],... or ([bd,...
333                                         // Is .W forced here?
334                                         if (*tok == DOTW)
335                                         {
336                                                 AnEXTEN |= EXT_BDSIZEW;
337                                                 tok++;
338                                         }
339                                         else
340                                         {
341                                                 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
342                                                 // to absolute short
343                                                 if (CHECK_OPTS(OPT_ABS_SHORT)
344                                                         && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
345                                                         && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
346                                                 {
347                                                         AnEXTEN |= EXT_BDSIZEW;
348                                                         warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
349                                                 }
350                                                 else
351                                                 {
352                                                         AnEXTEN |= EXT_BDSIZEL;
353                                                 }
354                                         }
355                                 }
356
357                                 if (*tok == ',')
358                                         tok++;
359                                 //else
360                                 //      return error("Comma expected after base displacement");
361                         }
362
363                         // Check for address register or PC, suppress base register
364                         // otherwise
365
366                         if (*tok == KW_PC)
367                         {                                       // ([bd,PC,...
368                                 AnREG = (7 << 3) | 3;   // PC is special case - stuff 011 to register field and 111 to the mode field
369                                 tok++;
370                         }
371                         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
372                         {                                       // ([bd,An,...
373                                 AnREG = (6 << 3) | *tok & 7;
374                                 tok++;
375                         }
376                         else if ((*tok >= KW_D0) && (*tok <= KW_D7))
377                         {
378                                 // ([bd,Dn,...
379                                 AnREG = (6 << 3);
380                                 AnEXTEN |= ((*tok & 7) << 12);
381                                 AnEXTEN |= EXT_D;
382                                 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
383                                 tok++;
384
385                                 // Check for size
386                                 {
387                                         // ([bd,An/PC],Xn.W/L...)
388                                         switch ((int)*tok)
389                                 {
390                                         // Index reg size: <empty> | .W | .L
391                                         case DOTW:
392                                                 tok++;
393                                                 break;
394                                         default:
395                                                 break;
396                                         case DOTL:
397                                                 AnEXTEN |= EXT_L;
398                                                 tok++;
399                                                 break;
400                                         case DOTB:
401                                                 // .B not allowed here...
402                                                 goto badmode;
403                                         }
404                                 }
405
406                                 // Check for scale
407                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
408                                 {                           // scale: *1, *2, *4, *8
409                                         tok++;
410
411                                         if (*tok == SYMBOL)
412                                         {
413                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
414                                                         return error("scale factor expression must evaluate");
415
416                                                 switch (scaleval)
417                                                 {
418                                                 case 1:
419                                                         break;
420                                                 case 2:
421                                                         AnIXSIZ |= TIMES2;
422                                                         break;
423                                                 case 4:
424                                                         AnIXSIZ |= TIMES4;
425                                                         break;
426                                                 case 8:
427                                                         AnIXSIZ |= TIMES8;
428                                                         break;
429                                                 default:
430                                                         goto badmode;
431                                 }
432                                         }
433                                         else if (*tok++ != CONST)
434                                                 goto badmode;
435                                         else
436                                         {
437                                                 switch ((int)*tok++)
438                                                 {
439                                                 case 1:
440                                                         break;
441                                                 case 2:
442                                                         AnIXSIZ |= TIMES2;
443                                                         break;
444                                                 case 4:
445                                                         AnIXSIZ |= TIMES4;
446                                                         break;
447                                                 case 8:
448                                                         AnIXSIZ |= TIMES8;
449                                                         break;
450                                                 default:
451                                                         goto badmode;
452                                                 }
453
454                                                 tok++;  // Take into account that constants are 64-bit
455                                         }
456                                 }
457                                 if (*tok == ']')  // ([bd,Dn]...
458                                 {
459                                         tok++;
460                                         goto IS_SUPPRESSEDn;
461                                 }
462                         }
463                         else if (*tok == ']')
464                         {
465                                 // PC and Xn is suppressed
466                                 AnREG = 6 << 3;         // stuff 110 to mode field
467                                 //AnEXTEN|=EXT_BS|EXT_IS;
468                                 AnEXTEN |= EXT_BS;
469                         }
470                         else
471                         {
472                                 goto badmode;
473                         }
474
475                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
476                         if (*tok == ']')
477                         {
478                                 //([bd,An/PC],Xn,od)
479                                 // Check for Xn
480                                 tok++;
481
482                                 if (*tok == ')')
483                                 {
484                                         //Xn and od are non existent, get out of jail free card
485                                         tok++;
486                                         AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
487                                         AnEXTEN |= EXT_IS | EXT_IISPREN;        //Suppress Xn and od
488                                         goto AnOK;
489                                 }
490                                 else if (*tok != ',')
491                                         return error("comma expected after ]");
492                                 else
493                                         tok++;                          // eat the comma
494
495                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
496                                 {
497                                         AnIXREG = ((*tok & 7) << 12);
498                                         AnEXTEN |= EXT_A;
499                                         tok++;
500                                 }
501                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
502                                 {
503                                         AnEXTEN |= ((*tok & 7) << 12);
504                                         AnEXTEN |= EXT_D;
505                                         tok++;
506                                 }
507                                 else
508                                 {
509                                         //No index found, suppress it
510                                         AnEXTEN |= EXT_IS;
511                                         tok--;                                  // Rewind tok to point to the comma
512                                         goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
513                                 }
514
515                                 // Check for size
516                                 {
517                                         // ([bd,An/PC],Xn.W/L...)
518                                         switch ((int)*tok)
519                                         {
520                                         // Index reg size: <empty> | .W | .L
521                                         case DOTW:
522                                                 tok++;
523                                                 break;
524                                         default:
525                                                 break;
526                                         case DOTL:
527                                                 AnEXTEN |= EXT_L;
528                                                 tok++;
529                                                 break;
530                                         case DOTB:
531                                                 // .B not allowed here...
532                                                 goto badmode;
533                                         }
534                                 }
535
536                                 // Check for scale
537                                 if (*tok == '*')                   // ([bd,An/PC],Xn*...)
538                                 {                                  // scale: *1, *2, *4, *8
539                                         tok++;
540
541                                         if (*tok == SYMBOL)
542                                         {
543                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
544                                                         return error("scale factor expression must evaluate");
545
546                                                 switch (scaleval)
547                                                 {
548                                                 case 1:
549                                                         break;
550                                                 case 2:
551                                                         AnIXSIZ |= TIMES2;
552                                                         break;
553                                                 case 4:
554                                                         AnIXSIZ |= TIMES4;
555                                                         break;
556                                                 case 8:
557                                                         AnIXSIZ |= TIMES8;
558                                                         break;
559                                                 default:
560                                                         goto badmode;
561                                                 }
562                                         }
563                                         else if (*tok++ != CONST)
564                                                 goto badmode;
565                                         else
566                                         {
567                                                 switch ((int)*tok++)
568                                                 {
569                                                 case 1:
570                                                         break;
571                                                 case 2:
572                                                         AnIXSIZ |= TIMES2;
573                                                         break;
574                                                 case 4:
575                                                         AnIXSIZ |= TIMES4;
576                                                         break;
577                                                 case 8:
578                                                         AnIXSIZ |= TIMES8;
579                                                         break;
580                                                 default:
581                                                         goto badmode;
582                                                 }
583
584                                                 tok++;  // Take into account that constants are 64-bit
585                                         }
586                                 }
587
588                                 // Check for od
589                                 if (*tok == ')')        // ([bd,An/PC],Xn)
590                                 {
591                                         // od is non existent, get out of jail free card
592                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
593                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
594                                         tok++;
595                                         goto AnOK;
596                                 }
597                                 else if (*tok != ',')
598                                         return error("comma expected");
599                                 else
600                                         tok++;  // eat the comma
601
602                                 CHECKODn:
603                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
604                                         goto badmode;
605
606                                 if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
607                                 {
608                                         // od=0 so optimise it out
609                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
610                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
611                                         tok++;
612                                         goto AnOK;
613                                 }
614
615                                 // ([bd,An/PC],Xn,od)
616                                 if (*tok == DOTL)
617                                 {
618                                         // expr.L
619                                         AnEXTEN |= EXT_IISPOSL; // Long outer displacement
620                                         AMn = MEMPOST;
621                                         tok++;
622
623                                         // Defined, absolute values from $FFFF8000..$00007FFF get
624                                         // optimized to absolute short
625                                         if (CHECK_OPTS(OPT_ABS_SHORT)
626                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
627                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
628                                         {
629                                                 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
630                                                 AMn = MEMPOST;
631                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
632                                         }
633
634                                 }
635                                 else
636                                 {
637                                         // expr[.W]
638                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
639                                         AMn = MEMPOST;
640
641                                         // Is .W forced here?
642                                         if (*tok == DOTW)
643                                         {
644                                                 tok++;
645                                         }
646                                 }
647
648                                 // Check for final closing parenthesis
649                                 if (*tok == ')')
650                                 {
651                                         tok++;
652                                         goto AnOK;
653                                 }
654                                 else
655                                         return error("Closing parenthesis missing on addressing mode");
656
657 IS_SUPPRESSEDn:
658
659                                 // Check for od
660                                 if (*tok == ')')        // ([bd,An/PC],Xn)
661                                 {
662                                         // od is non existent, get out of jail free card
663                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
664                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
665                                         tok++;
666                                         goto AnOK;
667                                 }
668                                 else if (*tok!=',')
669                                         return error("comma expected");
670                                 else
671                                         tok++;  // eat the comma
672
673                                 if ((*tok != CONST) && (*tok != SYMBOL))
674                                         goto badmode;
675
676                                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
677
678                                 if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
679                                 {
680                                         // od=0 so optimise it out
681                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
682                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
683                                         tok++;
684                                         goto AnOK;
685                                 }
686
687                                 // ([bd,An/PC],Xn,od)
688                                 if (*tok == DOTL)
689                                 {
690                                         // expr.L
691                                         tok++;
692                                         AMn = MEMPOST;
693                                         AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
694                                 }
695                                 else
696                                 {
697                                         // expr[.W][]
698                                         AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
699                                         AMn = MEMPRE;
700
701                                         if (*tok == DOTW)
702                                         {
703                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
704                                                 AMn = MEMPOST;
705                                                 tok++;
706                                         }
707                                         // Defined, absolute values from $FFFF8000..$00007FFF get
708                                         // optimized to absolute short
709                                         else if (CHECK_OPTS(OPT_BASE_DISP)
710                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
711                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
712                                         {
713                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
714                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
715                                         }
716                                 }
717
718                                 // Check for final closing parenthesis
719                                 if (*tok == ')')
720                                 {
721                                         tok++;
722                                         goto AnOK;
723                                 }
724                                 else
725                                         return error("Closing parenthesis missing on addressing mode");
726                         }
727                         else if (*tok == ',')
728                         {
729                                 *tok++;                 // ([bd,An,Xn.size*scale],od)
730
731                                 //Check for Xn
732                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
733                                 {
734                                         AnEXTEN |= ((*tok & 7) << 12);
735                                         AnEXTEN |= EXT_A;
736                                         tok++;
737                                 }
738                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
739                                 {
740                                         AnEXTEN |= ((*tok & 7) << 12);
741                                         AnEXTEN |= EXT_D;
742                                         tok++;
743                                 }
744
745                                 // Check for size
746                                 {
747                                 // ([bd,An/PC],Xn.W/L...)
748                                 switch ((int)*tok)
749                                         {
750                                         // Index reg size: <empty> | .W | .L
751                                         case DOTW:
752                                                 tok++;
753                                                 break;
754                                         default:
755                                                 break;
756                                         case DOTL:
757                                                 tok++;
758                                                 AnEXTEN |= EXT_L;
759                                                 break;
760                                         case DOTB:
761                                         // .B not allowed here...
762                                         goto badmode;
763                                         }
764                                 }
765
766                                 // Check for scale
767                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
768                                 {                           // scale: *1, *2, *4, *8
769                                         tok++;
770
771                                         if (*tok == SYMBOL)
772                                         {
773                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
774                                                         return error("scale factor expression must evaluate");
775                                                 switch (scaleval)
776                                                 {
777                                                 case 1:
778                                                         break;
779                                                 case 2:
780                                                         AnIXSIZ |= TIMES2;
781                                                         break;
782                                                 case 4:
783                                                         AnIXSIZ |= TIMES4;
784                                                         break;
785                                                 case 8:
786                                                         AnIXSIZ |= TIMES8;
787                                                         break;
788                                                 default:
789                                                         goto badmode;
790                                                 }
791                                         }
792                                         else if (*tok++ != CONST)
793                                                 goto badmode;
794                                         else
795                                         {
796                                                 switch ((int)*tok++)
797                                                 {
798                                                 case 1:
799                                                         break;
800                                                 case 2:
801                                                         AnIXSIZ |= TIMES2;
802                                                         AnEXTEN |= 1 << 9;
803                                                         break;
804                                                 case 4:
805                                                         AnIXSIZ |= TIMES4;
806                                                         AnEXTEN |= 2 << 9;
807                                                         break;
808                                                 case 8:
809                                                         AnIXSIZ |= TIMES8;
810                                                         AnEXTEN |= 3 << 9;
811                                                         break;
812                                                 default:
813                                                         goto badmode;
814                                                 }
815
816                                                 tok++;  // Take into account that constants are 64-bit
817                                         }
818                                 }
819
820                                 // Check for ]
821                                 if (*tok != ']')
822                                         return error("Expected closing bracket ]");
823                                 tok++;                  // Eat the bracket
824
825                                 // Check for od
826                                 if (*tok == ')')        // ([bd,An/PC,Xn]...
827                                 {
828                                         // od is non existent, get out of jail free card
829                                         //AnEXVAL=0;            // zero outer displacement
830                                         AMn = MEMPRE;                   // let's say it's ([bd,An,Xn],od) with od suppressed then
831                                         AnEXTEN |= EXT_IISPREN; // No outer displacement
832                                         tok++;
833                                         goto AnOK;
834                                 }
835                                 else if (*tok++ != ',')
836                                         return error("comma expected after ]");
837
838                                 if (*tok == SYMBOL || *tok == CONST)
839                                 {
840                                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
841                                                 goto badmode;
842
843                                         if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
844                                         {
845                                                 // od=0 so optimise it out
846                                                 AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
847                                                 AnEXTEN |= EXT_IISPRE0; // No outer displacement
848                                                 tok++;
849                                                 goto AnOK;
850                                         }
851                                 }
852
853                                 // ([bd,An/PC,Xn],od)
854                                 if (*tok == DOTL)
855                                 {
856                                         // expr.L
857                                         AMn = MEMPRE;
858                                         tok++;
859                                         AnEXTEN |= EXT_IISPREL;
860                                 }
861                                 else
862                                 {
863                                         // expr.[W]
864                                         AMn = MEMPRE;
865                                         int expr_size = EXT_IISPREW; // Assume we have a .w value
866
867                                         if ((AnEXVAL + 0x8000) > 0x10000)
868                                         {
869                                                 // Long value, so mark it as such for now
870                                                 expr_size = EXT_IISPREL;
871
872                                                 // Defined, absolute values from $FFFF8000..$00007FFF
873                                                 // get optimized to absolute short
874                                                 if (CHECK_OPTS(OPT_BASE_DISP)
875                                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
876                                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
877                                                 {
878                                                         expr_size = EXT_IISPREW;
879                                                         warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
880                                                 }
881                                         }
882
883                                         AnEXTEN |= expr_size; // Assume we have a .w value
884
885                                         // Is .W forced here?
886                                         if (*tok == DOTW)
887                                         {
888                                                 tok++;
889
890                                                 if (expr_size == EXT_IISPREL)
891                                                         return error("outer displacement value does not fit in .w size");
892                                         }
893                                 }
894
895                                 // Check for final closing parenthesis
896                                 if (*tok == ')')
897                                 {
898                                         tok++;
899                                         goto AnOK;
900                                 }
901                                 else
902                                         return error("Closing parenthesis missing on addressing mode");
903                         }
904                         else
905                                 goto badmode;
906                 }
907                 else
908                 {
909                         // (expr...
910                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
911                                 return ERROR;
912
913                         // It could be that this is really just an expression prefixing a
914                         // register as a displacement...
915                         if (*tok == ')')
916                         {
917                                 tok++;
918                                 goto CHK_FOR_DISPn;
919                         }
920
921                         // Otherwise, check for PC & etc displacements...
922                         if (*tok++ != ',')
923                                 goto badmode;
924
925                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
926                         {
927                                 AnREG = *tok & 7;
928                                 tok++;
929
930                                 if (*tok == ',')
931                                 {
932                                         AMn = AINDEXED;
933                                         goto AMn_IXN;
934                                 }
935                                 else if (*tok == ')')
936                                 {
937                                         AMn = ADISP;
938                                         tok++;
939                                         goto AnOK;
940                                 }
941                                 else
942                                         goto badmode;
943                         }
944                         else if (*tok == KW_PC)
945                         {
946                                 if (*++tok == ',')
947                                 {                             // expr(PC,Xn...)
948                                         AMn = PCINDEXED;
949                                         goto AMn_IXN;
950                                 }
951                                 else if (*tok == ')')
952                                 {
953                                         AMn = PCDISP;             // expr(PC)
954                                         tok++;
955                                         goto AnOK;
956                                 }
957                                 else
958                                         goto badmode;
959                         }
960                         else
961                                 goto badmode;
962                 }
963         }
964         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
965         {
966                 AMn = APREDEC;
967                 AnREG = tok[2] & 7;
968                 tok += 4;
969         }
970         else if (*tok == KW_CCR)
971         {
972                 AMn = AM_CCR;
973                 tok++;
974                 goto AnOK;
975         }
976         else if (*tok == KW_SR)
977         {
978                 AMn = AM_SR;
979                 tok++;
980                 goto AnOK;
981         }
982         else if (*tok == KW_USP)
983         {
984                 AMn = AM_USP;
985                 tok++;
986                 AnREG = 2;      // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
987                 goto AnOK;
988         }
989         else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
990         {
991                 AMn = CACHES;
992                 AnREG = *tok++ - KW_IC40;
993
994                 // After a cache keyword only a comma or EOL is allowed
995                 if ((*tok != ',') && (*tok != EOL))
996                         return ERROR;
997                 goto AnOK;
998         }
999         else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
1000         {
1001                 AMn = CREG;
1002                 AnREG = (*tok++) - KW_SFC;
1003                 goto AnOK;
1004         }
1005         else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
1006         {
1007                 AMn = FREG;
1008                 AnREG = (*tok++ & 7);
1009         }
1010         else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
1011         {
1012                 AMn = FPSCR;
1013                 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
1014         }
1015         // expr
1016         // expr.w
1017         // expr.l
1018         // d16(An)
1019         // d8(An,Xn[.siz])
1020         // d16(PC)
1021         // d8(PC,Xn[.siz])
1022         else
1023         {
1024                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
1025                         return ERROR;
1026
1027 CHK_FOR_DISPn:
1028                 if (*tok == DOTW)
1029                 {
1030                         // expr.W
1031                         tok++;
1032                         AMn = ABSW;
1033
1034                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
1035                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
1036
1037                         goto AnOK;
1038                 }
1039                 else if (*tok != '(')
1040                 {
1041                         // expr[.L]
1042                         AMn = ABSL;
1043
1044                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
1045                         // to absolute short
1046                         if (CHECK_OPTS(OPT_ABS_SHORT)
1047                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1048                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
1049                         {
1050                                 AMn = ABSW;
1051
1052                                 if (sbra_flag)
1053                                         warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1054                         }
1055
1056                         // Is .L forced here?
1057                         if (*tok == DOTL)
1058                         {
1059                                 tok++;
1060                                 AMn = ABSL;
1061                         }
1062
1063                         goto AnOK;
1064                 }
1065
1066                 tok++;
1067
1068                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
1069                 {
1070                         AnREG = *tok++ & 7;
1071
1072                         if (*tok == ')')
1073                         {
1074                                 AMn = ADISP;
1075                                 tok++;
1076                                 goto AnOK;
1077                         }
1078
1079                         AMn = AINDEXED;
1080                         goto AMn_IXN;
1081                 }
1082                 else if (*tok == KW_PC)
1083                 {
1084                         if (*++tok == ')')
1085                         {
1086                                 AMn = PCDISP;
1087                                 tok++;
1088                                 goto AnOK;
1089                         }
1090
1091                         AMn = PCINDEXED;
1092                         goto AMn_IXN;
1093                 }
1094
1095                 goto badmode;
1096         }
1097
1098         // Addressing mode OK
1099 AnOK:
1100         ;
1101 }
1102
1103 // Clean up dirty little macros
1104 #undef AnOK
1105 #undef AMn
1106 #undef AnREG
1107 #undef AnIXREG
1108 #undef AnIXSIZ
1109 #undef AnEXPR
1110 #undef AnEXVAL
1111 #undef AnEXATTR
1112 #undef AnOEXPR
1113 #undef AnOEXVAL
1114 #undef AnOEXATTR
1115 #undef AnESYM
1116 #undef AMn_IX0
1117 #undef AMn_IXN
1118 #undef CHK_FOR_DISPn
1119 #undef AnBEXPR
1120 #undef AnBEXVAL
1121 #undef AnBEXATTR
1122 #undef AnBZISE
1123 #undef AnEXTEN
1124 #undef AMn_030
1125 #undef IS_SUPPRESSEDn
1126 #undef CHECKODn