]> Shamusworld >> Repos - rmac/blob - parmode.h
Reign in internal help back to 80 columns. :-P
[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                                 if (*tok == DOTL)
620                                 {
621                                         // expr.L
622                                         if (!(AnEXTEN & EXT_BS))
623                                                 AnEXTEN |= EXT_IISPOSL; // Long outer displacement
624                                         else
625                                         {
626                                                 // bd is suppressed, so sticking the od size in bd
627                                                 AnEXTEN |= EXT_BDSIZEL;
628                                                 // And of course the expression has to be copied to
629                                                 // AnBEXPR instead of AnEXPR. Yay. :-/
630                                                 int i = 0;
631
632                                                 do
633                                                 {
634                                                         AnBEXPR[i] = AnEXPR[i];
635                                                         i++;
636                                                 }
637                                                 while (AnEXPR[i] != 'E');
638
639                                                 AnBEXPR[i] = 'E';
640                                         }
641
642                                         AMn = MEMPOST;
643                                         tok++;
644
645                                         // Defined, absolute values from $FFFF8000..$00007FFF get
646                                         // optimized to absolute short
647                                         if (CHECK_OPTS(OPT_020_DISP)
648                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
649                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
650                                         {
651                                                 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
652                                                 AMn = MEMPOST;
653                                                 if (optim_warn_flag)
654                                                         warn("absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
655                                         }
656
657                                 }
658                                 else
659                                 {
660                                         // expr[.W]
661                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
662                                         AMn = MEMPOST;
663
664                                         // Is .W forced here?
665                                         if (*tok == DOTW)
666                                                 tok++;
667                                 }
668
669                                 // Check for final closing parenthesis
670                                 if (*tok == ')')
671                                 {
672                                         tok++;
673                                         goto AnOK;
674                                 }
675                                 else
676                                         return error("Closing parenthesis missing on addressing mode");
677
678 IS_SUPPRESSEDn:
679
680                                 // Check for od
681                                 if (*tok == ')')        // ([bd,An/PC],Xn)
682                                 {
683                                         // od is non existent, get out of jail free card
684                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
685                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
686                                         tok++;
687                                         goto AnOK;
688                                 }
689                                 else if (*tok!=',')
690                                         return error("comma expected");
691                                 else
692                                         tok++;  // eat the comma
693
694                                 if ((*tok != CONST) && (*tok != SYMBOL))
695                                         goto badmode;
696
697                                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
698
699                                 if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0))
700                                 {
701                                         // od=0 so optimise it out
702                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
703                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
704                                         tok++;
705                                         goto AnOK;
706                                 }
707
708                                 // ([bd,An/PC],Xn,od)
709                                 if (*tok == DOTL)
710                                 {
711                                         // expr.L
712                                         tok++;
713                                         AMn = MEMPOST;
714                                         AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
715                                 }
716                                 else
717                                 {
718                                         // expr[.W][]
719                                         AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
720                                         AMn = MEMPRE;
721
722                                         if (*tok == DOTW)
723                                         {
724                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
725                                                 AMn = MEMPOST;
726                                                 tok++;
727                                         }
728                                         // Defined, absolute values from $FFFF8000..$00007FFF get
729                                         // optimized to absolute short
730                                         else if (CHECK_OPTS(OPT_020_DISP)
731                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
732                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
733                                         {
734                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
735                                                 if (optim_warn_flag)
736                                                         warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
737                                         }
738                                 }
739
740                                 // Check for final closing parenthesis
741                                 if (*tok == ')')
742                                 {
743                                         tok++;
744                                         goto AnOK;
745                                 }
746                                 else
747                                         return error("Closing parenthesis missing on addressing mode");
748                         }
749                         else if (*tok == ',')
750                         {
751                                 tok++;                  // ([bd,An,Xn.size*scale],od)
752
753                                 // Check for Xn
754                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
755                                 {
756                                         AnEXTEN |= ((*tok & 7) << 12);
757                                         AnEXTEN |= EXT_A;
758                                         tok++;
759                                 }
760                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
761                                 {
762                                         AnEXTEN |= ((*tok & 7) << 12);
763                                         AnEXTEN |= EXT_D;
764                                         tok++;
765                                 }
766
767                                 // Check for size
768                                 // ([bd,An/PC],Xn.W/L...)
769                                 switch ((int)*tok)
770                                 {
771                                 // Index reg size: <empty> | .W | .L
772                                 case DOTW:
773                                         tok++;
774                                         break;
775                                 default:
776                                         break;
777                                 case DOTL:
778                                         tok++;
779                                         AnEXTEN |= EXT_L;
780                                         break;
781                                 case DOTB:
782                                 // .B not allowed here...
783                                 goto badmode;
784                                 }
785
786                                 // Check for scale
787                                 if (*tok == '*')                                // ([bd,An/PC],Xn*...)
788                                 {                                                               // scale: *1, *2, *4, *8
789                                         tok++;
790
791                                         if (*tok == SYMBOL)
792                                         {
793                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
794                                                         return error("scale factor expression must evaluate");
795
796                                                 switch (scaleval)
797                                                 {
798                                                 case 1:
799                                                         break;
800                                                 case 2:
801                                                         AnIXSIZ |= TIMES2;
802                                                         break;
803                                                 case 4:
804                                                         AnIXSIZ |= TIMES4;
805                                                         break;
806                                                 case 8:
807                                                         AnIXSIZ |= TIMES8;
808                                                         break;
809                                                 default:
810                                                         goto badmode;
811                                                 }
812                                         }
813                                         else if (*tok++ != CONST)
814                                                 goto badmode;
815                                         else
816                                         {
817                                                 switch ((int)*tok++)
818                                                 {
819                                                 case 1:
820                                                         break;
821                                                 case 2:
822                                                         AnIXSIZ |= TIMES2;
823                                                         AnEXTEN |= 1 << 9;
824                                                         break;
825                                                 case 4:
826                                                         AnIXSIZ |= TIMES4;
827                                                         AnEXTEN |= 2 << 9;
828                                                         break;
829                                                 case 8:
830                                                         AnIXSIZ |= TIMES8;
831                                                         AnEXTEN |= 3 << 9;
832                                                         break;
833                                                 default:
834                                                         goto badmode;
835                                                 }
836
837                                                 tok++;  // Take into account that constants are 64-bit
838                                         }
839                                 }
840
841                                 // Check for ]
842                                 if (*tok != ']')
843                                         return error("Expected closing bracket ]");
844                                 tok++;                  // Eat the bracket
845
846                                 // Check for od
847                                 if (*tok == ')')        // ([bd,An/PC,Xn]...
848                                 {
849                                         // od is non existent, get out of jail free card
850                                         //AnEXVAL=0;            // zero outer displacement
851                                         AMn = MEMPRE;                   // let's say it's ([bd,An,Xn],od) with od suppressed then
852                                         AnEXTEN |= EXT_IISPREN; // No outer displacement
853                                         tok++;
854                                         goto AnOK;
855                                 }
856                                 else if (*tok++ != ',')
857                                         return error("comma expected after ]");
858
859                                 if (*tok == SYMBOL || *tok == CONST)
860                                 {
861                                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
862                                                 goto badmode;
863
864                                         if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
865                                         {
866                                                 // od=0 so optimise it out
867                                                 AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
868                                                 AnEXTEN |= EXT_IISPRE0; // No outer displacement
869                                                 tok++;
870                                                 goto AnOK;
871                                         }
872                                 }
873
874                                 // ([bd,An/PC,Xn],od)
875                                 if (*tok == DOTL)
876                                 {
877                                         // expr.L
878                                         AMn = MEMPRE;
879                                         tok++;
880                                         AnEXTEN |= EXT_IISPREL;
881                                 }
882                                 else
883                                 {
884                                         // expr.[W]
885                                         AMn = MEMPRE;
886                                         int expr_size = EXT_IISPREW; // Assume we have a .w value
887
888                                         if ((AnEXVAL + 0x8000) > 0x10000)
889                                         {
890                                                 // Long value, so mark it as such for now
891                                                 expr_size = EXT_IISPREL;
892
893                                                 // Defined, absolute values from $FFFF8000..$00007FFF
894                                                 // get optimized to absolute short
895                                                 if (CHECK_OPTS(OPT_020_DISP)
896                                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
897                                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
898                                                 {
899                                                         expr_size = EXT_IISPREW;
900
901                                                         if (optim_warn_flag)
902                                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
903                                                 }
904                                         }
905
906                                         AnEXTEN |= expr_size; // Assume we have a .w value
907
908                                         // Is .W forced here?
909                                         if (*tok == DOTW)
910                                         {
911                                                 tok++;
912
913                                                 if (expr_size == EXT_IISPREL)
914                                                         return error("outer displacement value does not fit in .w size");
915                                         }
916                                 }
917
918                                 // Check for final closing parenthesis
919                                 if (*tok == ')')
920                                 {
921                                         tok++;
922                                         goto AnOK;
923                                 }
924                                 else
925                                         return error("Closing parenthesis missing on addressing mode");
926                         }
927                         else
928                                 goto badmode;
929                 }
930                 else
931                 {
932                         // (expr...
933                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
934                                 return ERROR;
935
936                         // It could be that this is really just an expression prefixing a
937                         // register as a displacement...
938                         if (*tok == ')')
939                         {
940                                 tok++;
941                                 goto CHK_FOR_DISPn;
942                         }
943
944                         // Otherwise, check for PC & etc displacements...
945                         if (*tok++ != ',')
946                                 goto badmode;
947
948                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
949                         {
950                                 AnREG = *tok & 7;
951                                 tok++;
952
953                                 if (*tok == ',')
954                                 {
955                                         // Check if we're actually doing d8(An,Dn) or
956                                         // (d16,An,Dn[.size][*scale])
957                                         // TODO: not a very clear cut case from what I can think.
958                                         // The only way to distinguish between the two is to check
959                                         // AnEXVAL and see if it's >127 or <-128. But this doesn't
960                                         // work if AnEXVAL isn't defined yet. For now we fall
961                                         // through to d8(An,Dn) but this might bite us in the arse
962                                         // during fixups...
963                                         if ((AnEXATTR & DEFINED) && (AnEXVAL + 0x80 > 0x100))
964                                         {
965                                                 // We're going to treat it as a full extension format
966                                                 // with no indirect access and no base displacement/
967                                                 // index register suppression
968                                                 AnEXTEN |= EXT_FULLWORD;        // Definitely using full extension format, so set bit 8
969                                                 AnEXTEN |= EXT_IISPRE0;         // No Memory Indirect Action
970                                                 AnEXTEN |= EXT_BDSIZEL;         // Base Displacement Size Long
971                                                 tok++;                                          // Get past the comma
972
973                                                 // Our expression is techically a base displacement,
974                                                 // so let's copy it to the relevant variables so
975                                                 // eagen0.c can pick it up properly
976                                                 //AnBEXPR = AnEXPR;
977                                                 AnBEXVAL = AnEXVAL;
978                                                 AnBEXATTR = AnEXATTR;
979
980                                                 if ((*tok >= KW_D0) && (*tok <= KW_D7))
981                                                 {
982                                                         AnEXTEN |= ((*tok++) & 7) << 12;
983                                                         // Check for size
984                                                         {
985                                                                 switch ((int)*tok)
986                                                                 {
987                                                                 // Index reg size: <empty> | .W | .L
988                                                                 case DOTW:
989                                                                         tok++;
990                                                                         break;
991                                                                 default:
992                                                                         break;
993                                                                 case DOTL:
994                                                                         tok++;
995                                                                         AnEXTEN |= EXT_L;
996                                                                         break;
997                                                                 case DOTB:
998                                                                         // .B not allowed here...
999                                                                         goto badmode;
1000                                                                 }
1001                                                         }
1002                                                         // Check for scale
1003                                                         if (*tok == '*')                // ([bd,An/PC],Xn*...)
1004                                                         {                                               // scale: *1, *2, *4, *8
1005                                                                 tok++;
1006
1007                                                                 if (*tok == SYMBOL)
1008                                                                 {
1009                                                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
1010                                                                                 return error("scale factor expression must evaluate");
1011
1012                                                                         switch (scaleval)
1013                                                                         {
1014                                                                         case 1:
1015                                                                                 break;
1016                                                                         case 2:
1017                                                                                 AnIXSIZ |= TIMES2;
1018                                                                                 break;
1019                                                                         case 4:
1020                                                                                 AnIXSIZ |= TIMES4;
1021                                                                                 break;
1022                                                                         case 8:
1023                                                                                 AnIXSIZ |= TIMES8;
1024                                                                                 break;
1025                                                                         default:
1026                                                                                 goto badmode;
1027                                                                         }
1028                                                                 }
1029                                                                 else if (*tok++ != CONST)
1030                                                                         goto badmode;
1031                                                                 else
1032                                                                 {
1033                                                                         switch ((int)*tok++)
1034                                                                         {
1035                                                                         case 1:
1036                                                                                 break;
1037                                                                         case 2:
1038                                                                                 AnIXSIZ |= TIMES2;
1039                                                                                 break;
1040                                                                         case 4:
1041                                                                                 AnIXSIZ |= TIMES4;
1042                                                                                 break;
1043                                                                         case 8:
1044                                                                                 AnIXSIZ |= TIMES8;
1045                                                                                 break;
1046                                                                         default:
1047                                                                                 goto badmode;
1048                                                                         }
1049
1050                                                                         tok++;  // Take into account that constants are 64-bit
1051                                                                 }
1052                                                         }
1053
1054                                                         if (*tok++ != ')')
1055                                                                 return error("Closing parenthesis missing on addressing mode");
1056
1057                                                         // Let's say that this is the closest to our case
1058                                                         AMn = MEMPOST;
1059                                                         goto AnOK;
1060                                                 }
1061                                                 else
1062                                                         goto badmode;
1063                                         }
1064
1065                                         AMn = AINDEXED;
1066                                         goto AMn_IXN;
1067                                 }
1068                                 else if (*tok == ')')
1069                                 {
1070                                         AMn = ADISP;
1071                                         tok++;
1072                                         goto AnOK;
1073                                 }
1074                                 else
1075                                         goto badmode;
1076                         }
1077                         else if (*tok == KW_PC)
1078                         {
1079                                 if (*++tok == ',')
1080                                 {                             // expr(PC,Xn...)
1081                                         AMn = PCINDEXED;
1082                                         goto AMn_IXN;
1083                                 }
1084                                 else if (*tok == ')')
1085                                 {
1086                                         AMn = PCDISP;             // expr(PC)
1087                                         tok++;
1088                                         goto AnOK;
1089                                 }
1090                                 else
1091                                         goto badmode;
1092                         }
1093                         else
1094                                 goto badmode;
1095                 }
1096         }
1097         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
1098         {
1099                 AMn = APREDEC;
1100                 AnREG = tok[2] & 7;
1101                 tok += 4;
1102         }
1103         else if (*tok == KW_CCR)
1104         {
1105                 AMn = AM_CCR;
1106                 tok++;
1107                 goto AnOK;
1108         }
1109         else if (*tok == KW_SR)
1110         {
1111                 AMn = AM_SR;
1112                 tok++;
1113                 goto AnOK;
1114         }
1115         else if (*tok == KW_USP)
1116         {
1117                 AMn = AM_USP;
1118                 tok++;
1119                 AnREG = 2;      // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
1120                 goto AnOK;
1121         }
1122         else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
1123         {
1124                 AMn = CACHES;
1125                 AnREG = *tok++ - KW_IC40;
1126
1127                 // After a cache keyword only a comma or EOL is allowed
1128                 if ((*tok != ',') && (*tok != EOL))
1129                         return ERROR;
1130                 goto AnOK;
1131         }
1132         else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
1133         {
1134                 AMn = CREG;
1135                 AnREG = (*tok++) - KW_SFC;
1136                 goto AnOK;
1137         }
1138         else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
1139         {
1140                 AMn = FREG;
1141                 AnREG = (*tok++ & 7);
1142         }
1143         else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
1144         {
1145                 AMn = FPSCR;
1146                 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
1147         }
1148         // expr
1149         // expr.w
1150         // expr.l
1151         // d16(An)
1152         // d8(An,Xn[.siz])
1153         // d16(PC)
1154         // d8(PC,Xn[.siz])
1155         else
1156         {
1157                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
1158                         return ERROR;
1159
1160 CHK_FOR_DISPn:
1161                 if (*tok == DOTW)
1162                 {
1163                         // expr.W
1164                         tok++;
1165                         AMn = ABSW;
1166
1167                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
1168                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
1169
1170                         goto AnOK;
1171                 }
1172                 else if (*tok != '(')
1173                 {
1174                         // expr[.L]
1175                         AMn = ABSL;
1176
1177                         // When PC relative is enforced, check for any symbols that aren't
1178                         // EQU'd, in this case it's an illegal mode
1179                         if ((CHECK_OPTS(OPT_PC_RELATIVE)) && (AnEXATTR & REFERENCED) && (AnEXATTR & DEFINED) && (!(AnEXATTR & EQUATED)))
1180                                 return error("relocation not allowed");
1181
1182                         // .L is forced here
1183                         if (*tok == DOTL)
1184                         {
1185                                 tok++;
1186                                 AMn = ABSL;
1187                         }
1188                         else
1189                         {
1190                                 // Defined, absolute values from $FFFF8000..$00007FFF get
1191                                 // optimized to absolute short
1192                                 if (CHECK_OPTS(OPT_ABS_SHORT)
1193                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1194                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
1195                                 {
1196                                         AMn = ABSW;
1197
1198                                         if (optim_warn_flag)
1199                                                 warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1200                                 }
1201                         }
1202
1203                         goto AnOK;
1204                 }
1205
1206                 tok++;
1207
1208                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
1209                 {
1210                         AnREG = *tok++ & 7;
1211
1212                         if (*tok == ')')
1213                         {
1214                                 AMn = ADISP;
1215                                 tok++;
1216                                 goto AnOK;
1217                         }
1218
1219                         AMn = AINDEXED;
1220                         goto AMn_IXN;
1221                 }
1222                 else if (*tok == KW_PC)
1223                 {
1224                         if (*++tok == ')')
1225                         {
1226                                 AMn = PCDISP;
1227                                 tok++;
1228                                 goto AnOK;
1229                         }
1230
1231                         AMn = PCINDEXED;
1232                         goto AMn_IXN;
1233                 }
1234
1235                 goto badmode;
1236         }
1237
1238         // Addressing mode OK
1239 AnOK:
1240         ;
1241 }
1242
1243 // Clean up dirty little macros
1244 #undef AnOK
1245 #undef AMn
1246 #undef AnREG
1247 #undef AnIXREG
1248 #undef AnIXSIZ
1249 #undef AnEXPR
1250 #undef AnEXVAL
1251 #undef AnEXATTR
1252 #undef AnOEXPR
1253 #undef AnOEXVAL
1254 #undef AnOEXATTR
1255 #undef AnESYM
1256 #undef AMn_IX0
1257 #undef AMn_IXN
1258 #undef CHK_FOR_DISPn
1259 #undef AnBEXPR
1260 #undef AnBEXVAL
1261 #undef AnBEXATTR
1262 #undef AnBZISE
1263 #undef AnEXTEN
1264 #undef AMn_030
1265 #undef IS_SUPPRESSEDn
1266 #undef CHECKODn