549f131ea42630df7869042f42bcb3fbd72f8df8
[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-2020 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_FULLWORD;        // Definitely using full extension format, so set bit 8
201                                 AnEXTEN |= EXT_BS;       // Base displacement null - suppressed
202                                 AnEXTEN |= AnIXREG << 12;
203                                 goto CHECKODn;
204                         }
205                         else
206                                 return error("unhandled so far");
207                 }
208                 else if (*tok == KW_PC)
209                 {                            // (PC,Xn[.siz][*scale])
210                         tok++;
211                         AMn = PCINDEXED;
212
213                         // Common index handler; enter here with 'tok' pointing at the
214                         // comma.
215
216 AMn_IX0:                 // Handle indexed with missing expr
217
218                         AnEXVAL = 0;
219                         AnEXATTR = ABS | DEFINED;
220
221 AMn_IXN:                 // Handle any indexed (tok -> a comma)
222
223                         if (*tok++ != ',')
224                                 goto badmode;
225
226                         if (*tok < KW_D0 || *tok > KW_A7)
227                                 goto badmode;
228
229                         AnIXREG = *tok++ & 15;
230
231                         switch ((int)*tok)
232                         {                        // Index reg size: <empty> | .W | .L
233                         case DOTW:
234                                 tok++;
235                         default:
236                                 AnIXSIZ = 0;
237                                 break;
238                         case DOTL:
239                                 AnIXSIZ = 0x0800;
240                                 tok++;
241                                 break;
242                         case DOTB:               // .B not allowed here...
243                                 goto badmode;
244                         }
245
246                         if (*tok == '*')
247                         {                        // scale: *1, *2, *4, *8
248                                 tok++;
249
250                                 if (*tok == SYMBOL)
251                                 {
252                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
253                                                 return error("scale factor expression must evaluate");
254
255                                         switch (scaleval)
256                                         {
257                                         case 1:
258                                                 break;
259                                         case 2:
260                                                 AnIXSIZ |= TIMES2;
261                                                 break;
262                                         case 4:
263                                                 AnIXSIZ |= TIMES4;
264                                                 break;
265                                         case 8:
266                                                 AnIXSIZ |= TIMES8;
267                                                 break;
268                                         default:
269                                                 goto badmode;
270                                         }
271                                 }
272                                 else if (*tok++ != CONST)
273                                         goto badmode;
274                                 else
275                                 {
276                                         switch ((int)*tok++)
277                                         {
278                                         case 1:
279                                                 break;
280                                         case 2:
281                                                 AnIXSIZ |= TIMES2;
282                                                 break;
283                                         case 4:
284                                                 AnIXSIZ |= TIMES4;
285                                                 break;
286                                         case 8:
287                                                 AnIXSIZ |= TIMES8;
288                                                 break;
289                                         default:
290                                                 goto badmode;
291                                         }
292
293                                         tok++;  // Take into account that constants are 64-bit
294                                 }
295                         }
296
297                         if (*tok == ',')
298                         {
299                                 // If we got here we didn't get any [] stuff
300                                 // so let's suppress base displacement before
301                                 // branching off
302                                 tok++;
303                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null - suppressed
304                                 goto CHECKODn;
305                         }
306                         if (*tok++ != ')')         // final ")"
307                                 goto badmode;
308
309                         goto AnOK;
310                 }
311                 else if (*tok == '[')
312                 {                              // ([...
313                         tok++;
314                         AnEXTEN |= EXT_FULLWORD;     // Definitely using full extension format, so set bit 8
315
316                         // Check to see if base displacement is present
317                         if (*tok != CONST && *tok != SYMBOL)
318                         {
319                                 AnEXTEN |= EXT_BDSIZE0;
320                         }
321                         else
322                         {
323                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
324
325                                 if (CHECK_OPTS(OPT_020_DISP) && (AnBEXVAL == 0) && (AnEXATTR != 0))
326                                 {
327                                         // bd = 0 so let's optimise it out
328                                         AnEXTEN |= EXT_BDSIZE0;
329                                 }
330                                 else if (*tok == DOTL)
331                                 {
332                                         // ([bd.l,...
333                                         AnEXTEN |= EXT_BDSIZEL;
334                                         tok++;
335                                 }
336                                 else
337                                 {
338                                         // ([bd[.w],... or ([bd,...
339                                         // Is .W forced here?
340                                         if (*tok == DOTW)
341                                         {
342                                                 AnEXTEN |= EXT_BDSIZEW;
343                                                 tok++;
344                                         }
345                                         else
346                                         {
347                                                 // Defined, absolute values from $FFFF8000..$00007FFF
348                                                 // get optimized to absolute short
349                                                 if (CHECK_OPTS(OPT_020_DISP)
350                                                         && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
351                                                         && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
352                                                 {
353                                                         AnEXTEN |= EXT_BDSIZEW;
354
355                                                         if (optim_warn_flag)
356                                                                 warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
357                                                 }
358                                                 else
359                                                 {
360                                                         AnEXTEN |= EXT_BDSIZEL;
361                                                 }
362                                         }
363                                 }
364
365                                 if (*tok == ',')
366                                         tok++;
367                                 //else
368                                 //      return error("Comma expected after base displacement");
369                         }
370
371                         // Check for address register or PC, suppress base register
372                         // otherwise
373
374                         if (*tok == KW_PC)
375                         {                                       // ([bd,PC,...
376                                 AnREG = (7 << 3) | 3;   // PC is special case - stuff 011 to register field and 111 to the mode field
377                                 tok++;
378                         }
379                         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
380                         {                                       // ([bd,An,...
381                                 AnREG = (6 << 3) | (*tok & 7);
382                                 tok++;
383                         }
384                         else if ((*tok >= KW_D0) && (*tok <= KW_D7))
385                         {
386                                 // ([bd,Dn,...
387                                 AnREG = (6 << 3);
388                                 AnEXTEN |= ((*tok & 7) << 12);
389                                 AnEXTEN |= EXT_D;
390                                 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
391                                 tok++;
392
393                                 // Check for size
394                                 // ([bd,An/PC],Xn.W/L...)
395                                 switch ((int)*tok)
396                                 {
397                                 // Index reg size: <empty> | .W | .L
398                                 case DOTW:
399                                         tok++;
400                                         break;
401                                 default:
402                                         break;
403                                 case DOTL:
404                                         AnEXTEN |= EXT_L;
405                                         tok++;
406                                         break;
407                                 case DOTB:
408                                         // .B not allowed here...
409                                         goto badmode;
410                                 }
411
412                                 // Check for scale
413                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
414                                 {                           // scale: *1, *2, *4, *8
415                                         tok++;
416
417                                         if (*tok == SYMBOL)
418                                         {
419                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
420                                                         return error("scale factor expression must evaluate");
421
422                                                 switch (scaleval)
423                                                 {
424                                                 case 1:
425                                                         break;
426                                                 case 2:
427                                                         AnIXSIZ |= TIMES2;
428                                                         break;
429                                                 case 4:
430                                                         AnIXSIZ |= TIMES4;
431                                                         break;
432                                                 case 8:
433                                                         AnIXSIZ |= TIMES8;
434                                                         break;
435                                                 default:
436                                                         goto badmode;
437                                 }
438                                         }
439                                         else if (*tok++ != CONST)
440                                                 goto badmode;
441                                         else
442                                         {
443                                                 switch ((int)*tok++)
444                                                 {
445                                                 case 1:
446                                                         break;
447                                                 case 2:
448                                                         AnIXSIZ |= TIMES2;
449                                                         break;
450                                                 case 4:
451                                                         AnIXSIZ |= TIMES4;
452                                                         break;
453                                                 case 8:
454                                                         AnIXSIZ |= TIMES8;
455                                                         break;
456                                                 default:
457                                                         goto badmode;
458                                                 }
459
460                                                 tok++;  // Take into account that constants are 64-bit
461                                         }
462                                 }
463                                 if (*tok == ']')  // ([bd,Dn]...
464                                 {
465                                         tok++;
466                                         goto IS_SUPPRESSEDn;
467                                 }
468                         }
469                         else if (*tok == ']')
470                         {
471                                 // PC and Xn is suppressed
472                                 AnREG = 6 << 3;         // stuff 110b to mode field
473                                 AnEXTEN |= EXT_BS;
474                         }
475                         else
476                         {
477                                 goto badmode;
478                         }
479
480                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
481                         if (*tok == ']')
482                         {
483                                 // ([bd,An/PC],Xn,od)
484                                 // Check for Xn
485                                 tok++;
486
487                                 if (*tok == ')')
488                                 {
489                                         // Xn and od are non existent, get out of jail free card
490                                         tok++;
491                                         AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
492                                         AnEXTEN |= EXT_IS | EXT_IISPREN;        // Suppress Xn and od
493                                         goto AnOK;
494                                 }
495                                 else if (*tok != ',')
496                                         return error("comma expected after ]");
497                                 else
498                                         tok++;                          // eat the comma
499
500                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
501                                 {
502                                         AnIXREG = ((*tok & 7) << 12);
503                                         AnEXTEN |= EXT_A;
504                                         tok++;
505                                 }
506                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
507                                 {
508                                         AnEXTEN |= ((*tok & 7) << 12);
509                                         AnEXTEN |= EXT_D;
510                                         tok++;
511                                 }
512                                 else
513                                 {
514                                         // No index found, suppress it
515                                         AnEXTEN |= EXT_IS;
516                                         tok--;                                  // Rewind tok to point to the comma
517                                         goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
518                                 }
519
520                                 // Check for size
521                                 // ([bd,An/PC],Xn.W/L...)
522                                 switch ((int)*tok)
523                                 {
524                                 // Index reg size: <empty> | .W | .L
525                                 case DOTW:
526                                         tok++;
527                                         break;
528                                 default:
529                                         break;
530                                 case DOTL:
531                                         AnEXTEN |= EXT_L;
532                                         tok++;
533                                         break;
534                                 case DOTB:
535                                         // .B not allowed here...
536                                         goto badmode;
537                                 }
538
539                                 // Check for scale
540                                 if (*tok == '*')                   // ([bd,An/PC],Xn*...)
541                                 {                                  // scale: *1, *2, *4, *8
542                                         tok++;
543
544                                         if (*tok == SYMBOL)
545                                         {
546                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
547                                                         return error("scale factor expression must evaluate");
548
549                                                 switch (scaleval)
550                                                 {
551                                                 case 1:
552                                                         break;
553                                                 case 2:
554                                                         AnIXSIZ |= TIMES2;
555                                                         break;
556                                                 case 4:
557                                                         AnIXSIZ |= TIMES4;
558                                                         break;
559                                                 case 8:
560                                                         AnIXSIZ |= TIMES8;
561                                                         break;
562                                                 default:
563                                                         goto badmode;
564                                                 }
565                                         }
566                                         else if (*tok++ != CONST)
567                                                 goto badmode;
568                                         else
569                                         {
570                                                 switch ((int)*tok++)
571                                                 {
572                                                 case 1:
573                                                         break;
574                                                 case 2:
575                                                         AnIXSIZ |= TIMES2;
576                                                         break;
577                                                 case 4:
578                                                         AnIXSIZ |= TIMES4;
579                                                         break;
580                                                 case 8:
581                                                         AnIXSIZ |= TIMES8;
582                                                         break;
583                                                 default:
584                                                         goto badmode;
585                                                 }
586
587                                                 tok++;  // Take into account that constants are 64-bit
588                                         }
589                                 }
590
591                                 // Check for od
592                                 if (*tok == ')')        // ([bd,An/PC],Xn)
593                                 {
594                                         // od is non existent, get out of jail free card
595                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
596                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
597                                         tok++;
598                                         goto AnOK;
599                                 }
600                                 else if (*tok != ',')
601                                         return error("comma expected");
602                                 else
603                                         tok++;  // eat the comma
604
605 CHECKODn:
606                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
607                                         goto badmode;
608
609                                 if (CHECK_OPTS(OPT_020_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
610                                 {
611                                         // od = 0 so optimise it out
612                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
613                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
614                                         tok++;
615                                         goto AnOK;
616                                 }
617
618                                 // ([bd,An/PC],Xn,od)
619                                         // Is .W forced here?
620                                 if (*tok == DOTW)
621                                 {
622                                         tok++;
623                                         // od[.W]
624                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
625                                         AMn = MEMPOST;
626                                 }
627                                 else
628                                 {
629                                         // Is .L forced here?
630                                         if (*tok == DOTL)
631                                                 tok++;                          // Doesn't matter, we're going for .L anyway
632
633                                         // od.L
634                                         if (!(AnEXTEN & EXT_BS))
635                                                 AnEXTEN |= EXT_IISPOSL; // Long outer displacement
636                                         else
637                                         {
638                                                 // bd is suppressed, so sticking the od size in bd
639                                                 AnEXTEN |= EXT_BDSIZEL;
640                                                 // And of course the expression has to be copied to
641                                                 // AnBEXPR instead of AnEXPR. Yay. :-/
642                                                 int i = 0;
643
644                                                 do
645                                                 {
646                                                         AnBEXPR[i] = AnEXPR[i];
647                                                         i++;
648                                                 } while (AnEXPR[i] != 'E');
649
650                                                 AnBEXPR[i] = 'E';
651                                         }
652
653                                         AMn = MEMPOST;
654
655                                         // Defined, absolute values from $FFFF8000..$00007FFF get
656                                         // optimized to absolute short
657                                         if (CHECK_OPTS(OPT_020_DISP)
658                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
659                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
660                                         {
661                                                 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
662                                                 AMn = MEMPOST;
663                                                 if (optim_warn_flag)
664                                                         warn("absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
665                                         }
666                                 }
667
668                                 // Check for final closing parenthesis
669                                 if (*tok == ')')
670                                 {
671                                         tok++;
672                                         goto AnOK;
673                                 }
674                                 else
675                                         return error("Closing parenthesis missing on addressing mode");
676
677 IS_SUPPRESSEDn:
678
679                                 // Check for od
680                                 if (*tok == ')')        // ([bd,An/PC],Xn)
681                                 {
682                                         // od is non existent, get out of jail free card
683                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
684                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
685                                         tok++;
686                                         goto AnOK;
687                                 }
688                                 else if (*tok!=',')
689                                         return error("comma expected");
690                                 else
691                                         tok++;  // eat the comma
692
693                                 if ((*tok != CONST) && (*tok != SYMBOL))
694                                         goto badmode;
695
696                                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
697
698                                 if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0))
699                                 {
700                                         // od=0 so optimise it out
701                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
702                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
703                                         tok++;
704                                         goto AnOK;
705                                 }
706
707                                 // ([bd,An/PC],Xn,od)
708                                 if (*tok == DOTL)
709                                 {
710                                         // expr.L
711                                         tok++;
712                                         AMn = MEMPOST;
713                                         AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
714                                 }
715                                 else
716                                 {
717                                         // expr[.W][]
718                                         AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
719                                         AMn = MEMPRE;
720
721                                         if (*tok == DOTW)
722                                         {
723                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
724                                                 AMn = MEMPOST;
725                                                 tok++;
726                                         }
727                                         // Defined, absolute values from $FFFF8000..$00007FFF get
728                                         // optimized to absolute short
729                                         else if (CHECK_OPTS(OPT_020_DISP)
730                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
731                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
732                                         {
733                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
734                                                 if (optim_warn_flag)
735                                                         warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
736                                         }
737                                 }
738
739                                 // Check for final closing parenthesis
740                                 if (*tok == ')')
741                                 {
742                                         tok++;
743                                         goto AnOK;
744                                 }
745                                 else
746                                         return error("Closing parenthesis missing on addressing mode");
747                         }
748                         else if (*tok == ',')
749                         {
750                                 tok++;                  // ([bd,An,Xn.size*scale],od)
751
752                                 // Check for Xn
753                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
754                                 {
755                                         AnEXTEN |= ((*tok & 7) << 12);
756                                         AnEXTEN |= EXT_A;
757                                         tok++;
758                                 }
759                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
760                                 {
761                                         AnEXTEN |= ((*tok & 7) << 12);
762                                         AnEXTEN |= EXT_D;
763                                         tok++;
764                                 }
765
766                                 // Check for size
767                                 // ([bd,An/PC],Xn.W/L...)
768                                 switch ((int)*tok)
769                                 {
770                                 // Index reg size: <empty> | .W | .L
771                                 case DOTW:
772                                         tok++;
773                                         break;
774                                 default:
775                                         break;
776                                 case DOTL:
777                                         tok++;
778                                         AnEXTEN |= EXT_L;
779                                         break;
780                                 case DOTB:
781                                 // .B not allowed here...
782                                 goto badmode;
783                                 }
784
785                                 // Check for scale
786                                 if (*tok == '*')                                // ([bd,An/PC],Xn*...)
787                                 {                                                               // scale: *1, *2, *4, *8
788                                         tok++;
789
790                                         if (*tok == SYMBOL)
791                                         {
792                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
793                                                         return error("scale factor expression must evaluate");
794
795                                                 switch (scaleval)
796                                                 {
797                                                 case 1:
798                                                         break;
799                                                 case 2:
800                                                         AnIXSIZ |= TIMES2;
801                                                         break;
802                                                 case 4:
803                                                         AnIXSIZ |= TIMES4;
804                                                         break;
805                                                 case 8:
806                                                         AnIXSIZ |= TIMES8;
807                                                         break;
808                                                 default:
809                                                         goto badmode;
810                                                 }
811                                         }
812                                         else if (*tok++ != CONST)
813                                                 goto badmode;
814                                         else
815                                         {
816                                                 switch ((int)*tok++)
817                                                 {
818                                                 case 1:
819                                                         break;
820                                                 case 2:
821                                                         AnIXSIZ |= TIMES2;
822                                                         AnEXTEN |= 1 << 9;
823                                                         break;
824                                                 case 4:
825                                                         AnIXSIZ |= TIMES4;
826                                                         AnEXTEN |= 2 << 9;
827                                                         break;
828                                                 case 8:
829                                                         AnIXSIZ |= TIMES8;
830                                                         AnEXTEN |= 3 << 9;
831                                                         break;
832                                                 default:
833                                                         goto badmode;
834                                                 }
835
836                                                 tok++;  // Take into account that constants are 64-bit
837                                         }
838                                 }
839
840                                 // Check for ]
841                                 if (*tok != ']')
842                                         return error("Expected closing bracket ]");
843                                 tok++;                  // Eat the bracket
844
845                                 // Check for od
846                                 if (*tok == ')')        // ([bd,An/PC,Xn]...
847                                 {
848                                         // od is non existent, get out of jail free card
849                                         //AnEXVAL=0;            // zero outer displacement
850                                         AMn = MEMPRE;                   // let's say it's ([bd,An,Xn],od) with od suppressed then
851                                         AnEXTEN |= EXT_IISPREN; // No outer displacement
852                                         tok++;
853                                         goto AnOK;
854                                 }
855                                 else if (*tok++ != ',')
856                                         return error("comma expected after ]");
857
858                                 if (*tok == SYMBOL || *tok == CONST)
859                                 {
860                                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
861                                                 goto badmode;
862
863                                         if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
864                                         {
865                                                 // od=0 so optimise it out
866                                                 AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
867                                                 AnEXTEN |= EXT_IISPRE0; // No outer displacement
868                                                 tok++;
869                                                 goto AnOK;
870                                         }
871                                 }
872
873                                 // ([bd,An/PC,Xn],od)
874                                 if (*tok == DOTL)
875                                 {
876                                         // expr.L
877                                         AMn = MEMPRE;
878                                         tok++;
879                                         AnEXTEN |= EXT_IISPREL;
880                                 }
881                                 else
882                                 {
883                                         // expr.[W]
884                                         AMn = MEMPRE;
885                                         int expr_size = EXT_IISPREW; // Assume we have a .w value
886
887                                         if ((AnEXVAL + 0x8000) > 0x10000)
888                                         {
889                                                 // Long value, so mark it as such for now
890                                                 expr_size = EXT_IISPREL;
891
892                                                 // Defined, absolute values from $FFFF8000..$00007FFF
893                                                 // get optimized to absolute short
894                                                 if (CHECK_OPTS(OPT_020_DISP)
895                                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
896                                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
897                                                 {
898                                                         expr_size = EXT_IISPREW;
899
900                                                         if (optim_warn_flag)
901                                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
902                                                 }
903                                         }
904
905                                         AnEXTEN |= expr_size; // Assume we have a .w value
906
907                                         // Is .W forced here?
908                                         if (*tok == DOTW)
909                                         {
910                                                 tok++;
911
912                                                 if (expr_size == EXT_IISPREL)
913                                                         return error("outer displacement value does not fit in .w size");
914                                         }
915                                 }
916
917                                 // Check for final closing parenthesis
918                                 if (*tok == ')')
919                                 {
920                                         tok++;
921                                         goto AnOK;
922                                 }
923                                 else
924                                         return error("Closing parenthesis missing on addressing mode");
925                         }
926                         else
927                                 goto badmode;
928                 }
929                 else
930                 {
931                         // (expr...
932                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
933                                 return ERROR;
934
935                         // It could be that this is really just an expression prefixing a
936                         // register as a displacement...
937                         if (*tok == ')')
938                         {
939                                 tok++;
940                                 goto CHK_FOR_DISPn;
941                         }
942
943                         // Otherwise, check for PC & etc displacements...
944                         if (*tok++ != ',')
945                                 goto badmode;
946
947                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
948                         {
949                                 AnREG = *tok & 7;
950                                 tok++;
951
952                                 if (*tok == ',')
953                                 {
954                                         // Check if we're actually doing d8(An,Dn) or
955                                         // (d16,An,Dn[.size][*scale])
956                                         // TODO: not a very clear cut case from what I can think.
957                                         // The only way to distinguish between the two is to check
958                                         // AnEXVAL and see if it's >127 or <-128. But this doesn't
959                                         // work if AnEXVAL isn't defined yet. For now we fall
960                                         // through to d8(An,Dn) but this might bite us in the arse
961                                         // during fixups...
962                                         if ((AnEXATTR & DEFINED) && (AnEXVAL + 0x80 > 0x100))
963                                         {
964                                                 // We're going to treat it as a full extension format
965                                                 // with no indirect access and no base displacement/
966                                                 // index register suppression
967                                                 AnEXTEN |= EXT_FULLWORD;        // Definitely using full extension format, so set bit 8
968                                                 AnEXTEN |= EXT_IISPRE0;         // No Memory Indirect Action
969                                                 AnEXTEN |= EXT_BDSIZEL;         // Base Displacement Size Long
970                                                 tok++;                                          // Get past the comma
971
972                                                 // Our expression is techically a base displacement,
973                                                 // so let's copy it to the relevant variables so
974                                                 // eagen0.c can pick it up properly
975                                                 //AnBEXPR = AnEXPR;
976                                                 AnBEXVAL = AnEXVAL;
977                                                 AnBEXATTR = AnEXATTR;
978
979                                                 if ((*tok >= KW_D0) && (*tok <= KW_D7))
980                                                 {
981                                                         AnEXTEN |= ((*tok++) & 7) << 12;
982                                                         // Check for size
983                                                         {
984                                                                 switch ((int)*tok)
985                                                                 {
986                                                                 // Index reg size: <empty> | .W | .L
987                                                                 case DOTW:
988                                                                         tok++;
989                                                                         break;
990                                                                 default:
991                                                                         break;
992                                                                 case DOTL:
993                                                                         tok++;
994                                                                         AnEXTEN |= EXT_L;
995                                                                         break;
996                                                                 case DOTB:
997                                                                         // .B not allowed here...
998                                                                         goto badmode;
999                                                                 }
1000                                                         }
1001                                                         // Check for scale
1002                                                         if (*tok == '*')                // ([bd,An/PC],Xn*...)
1003                                                         {                                               // scale: *1, *2, *4, *8
1004                                                                 tok++;
1005
1006                                                                 if (*tok == SYMBOL)
1007                                                                 {
1008                                                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
1009                                                                                 return error("scale factor expression must evaluate");
1010
1011                                                                         switch (scaleval)
1012                                                                         {
1013                                                                         case 1:
1014                                                                                 break;
1015                                                                         case 2:
1016                                                                                 AnIXSIZ |= TIMES2;
1017                                                                                 break;
1018                                                                         case 4:
1019                                                                                 AnIXSIZ |= TIMES4;
1020                                                                                 break;
1021                                                                         case 8:
1022                                                                                 AnIXSIZ |= TIMES8;
1023                                                                                 break;
1024                                                                         default:
1025                                                                                 goto badmode;
1026                                                                         }
1027                                                                 }
1028                                                                 else if (*tok++ != CONST)
1029                                                                         goto badmode;
1030                                                                 else
1031                                                                 {
1032                                                                         switch ((int)*tok++)
1033                                                                         {
1034                                                                         case 1:
1035                                                                                 break;
1036                                                                         case 2:
1037                                                                                 AnIXSIZ |= TIMES2;
1038                                                                                 break;
1039                                                                         case 4:
1040                                                                                 AnIXSIZ |= TIMES4;
1041                                                                                 break;
1042                                                                         case 8:
1043                                                                                 AnIXSIZ |= TIMES8;
1044                                                                                 break;
1045                                                                         default:
1046                                                                                 goto badmode;
1047                                                                         }
1048
1049                                                                         tok++;  // Take into account that constants are 64-bit
1050                                                                 }
1051                                                         }
1052
1053                                                         if (*tok++ != ')')
1054                                                                 return error("Closing parenthesis missing on addressing mode");
1055
1056                                                         // Let's say that this is the closest to our case
1057                                                         AMn = MEMPOST;
1058                                                         goto AnOK;
1059                                                 }
1060                                                 else
1061                                                         goto badmode;
1062                                         }
1063
1064                                         AMn = AINDEXED;
1065                                         goto AMn_IXN;
1066                                 }
1067                                 else if (*tok == ')')
1068                                 {
1069                                         AMn = ADISP;
1070                                         tok++;
1071                                         goto AnOK;
1072                                 }
1073                                 else
1074                                         goto badmode;
1075                         }
1076                         else if (*tok == KW_PC)
1077                         {
1078                                 if (*++tok == ',')
1079                                 {                             // expr(PC,Xn...)
1080                                         AMn = PCINDEXED;
1081                                         goto AMn_IXN;
1082                                 }
1083                                 else if (*tok == ')')
1084                                 {
1085                                         AMn = PCDISP;             // expr(PC)
1086                                         tok++;
1087                                         goto AnOK;
1088                                 }
1089                                 else
1090                                         goto badmode;
1091                         }
1092                         else
1093                                 goto badmode;
1094                 }
1095         }
1096         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
1097         {
1098                 AMn = APREDEC;
1099                 AnREG = tok[2] & 7;
1100                 tok += 4;
1101         }
1102         else if (*tok == KW_CCR)
1103         {
1104                 AMn = AM_CCR;
1105                 tok++;
1106                 goto AnOK;
1107         }
1108         else if (*tok == KW_SR)
1109         {
1110                 AMn = AM_SR;
1111                 tok++;
1112                 goto AnOK;
1113         }
1114         else if (*tok == KW_USP)
1115         {
1116                 AMn = AM_USP;
1117                 tok++;
1118                 AnREG = 2;      // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
1119                 goto AnOK;
1120         }
1121         else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
1122         {
1123                 AMn = CACHES;
1124                 AnREG = *tok++ - KW_IC40;
1125
1126                 // After a cache keyword only a comma or EOL is allowed
1127                 if ((*tok != ',') && (*tok != EOL))
1128                         return ERROR;
1129                 goto AnOK;
1130         }
1131         else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
1132         {
1133                 AMn = CREG;
1134                 AnREG = (*tok++) - KW_SFC;
1135                 goto AnOK;
1136         }
1137         else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
1138         {
1139                 AMn = FREG;
1140                 AnREG = (*tok++ & 7);
1141         }
1142         else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
1143         {
1144                 AMn = FPSCR;
1145                 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
1146         }
1147         // expr
1148         // expr.w
1149         // expr.l
1150         // d16(An)
1151         // d8(An,Xn[.siz])
1152         // d16(PC)
1153         // d8(PC,Xn[.siz])
1154         else
1155         {
1156                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
1157                         return ERROR;
1158
1159 CHK_FOR_DISPn:
1160                 if (*tok == DOTW)
1161                 {
1162                         // expr.W
1163                         tok++;
1164                         AMn = ABSW;
1165
1166                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
1167                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
1168
1169                         goto AnOK;
1170                 }
1171                 else if (*tok != '(')
1172                 {
1173                         // expr[.L]
1174                         AMn = ABSL;
1175
1176                         // When PC relative is enforced, check for any symbols that aren't
1177                         // EQU'd, in this case it's an illegal mode
1178                         if ((CHECK_OPTS(OPT_PC_RELATIVE)) && (AnEXATTR & REFERENCED) && (AnEXATTR & DEFINED) && (!(AnEXATTR & EQUATED)))
1179                                 return error("relocation not allowed");
1180
1181                         // .L is forced here
1182                         if (*tok == DOTL)
1183                         {
1184                                 tok++;
1185                                 AMn = ABSL;
1186                         }
1187                         else
1188                         {
1189                                 // Defined, absolute values from $FFFF8000..$00007FFF get
1190                                 // optimized to absolute short
1191                                 if (CHECK_OPTS(OPT_ABS_SHORT)
1192                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1193                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
1194                                 {
1195                                         AMn = ABSW;
1196
1197                                         if (optim_warn_flag)
1198                                                 warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1199                                 }
1200                         }
1201
1202                         goto AnOK;
1203                 }
1204
1205                 tok++;
1206
1207                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
1208                 {
1209                         AnREG = *tok++ & 7;
1210
1211                         if (*tok == ')')
1212                         {
1213                                 AMn = ADISP;
1214                                 tok++;
1215                                 goto AnOK;
1216                         }
1217
1218                         AMn = AINDEXED;
1219                         goto AMn_IXN;
1220                 }
1221                 else if (*tok == KW_PC)
1222                 {
1223                         if (*++tok == ')')
1224                         {
1225                                 AMn = PCDISP;
1226                                 tok++;
1227                                 goto AnOK;
1228                         }
1229
1230                         AMn = PCINDEXED;
1231                         goto AMn_IXN;
1232                 }
1233
1234                 goto badmode;
1235         }
1236
1237         // Addressing mode OK
1238 AnOK:
1239         ;
1240 }
1241
1242 // Clean up dirty little macros
1243 #undef AnOK
1244 #undef AMn
1245 #undef AnREG
1246 #undef AnIXREG
1247 #undef AnIXSIZ
1248 #undef AnEXPR
1249 #undef AnEXVAL
1250 #undef AnEXATTR
1251 #undef AnOEXPR
1252 #undef AnOEXVAL
1253 #undef AnOEXATTR
1254 #undef AnESYM
1255 #undef AMn_IX0
1256 #undef AMn_IXN
1257 #undef CHK_FOR_DISPn
1258 #undef AnBEXPR
1259 #undef AnBEXVAL
1260 #undef AnBEXATTR
1261 #undef AnBZISE
1262 #undef AnEXTEN
1263 #undef AMn_030
1264 #undef IS_SUPPRESSEDn
1265 #undef CHECKODn