Various small fixes including:
[rmac] / parmode.h
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 // This file is included (twice) to parse two addressing modes, into slightly
10 // different var names
11 {
12         uint64_t scaleval;                      // Expression's value
13         TOKEN scaleexpr[EXPRSIZE];      // Expression
14         WORD scaleattr;                         // Expression's attribute
15         SYM * scaleesym;                        // External symbol involved in expr
16
17         // Dn
18         // An
19         // # expression
20         if ((*tok >= KW_D0) && (*tok <= KW_D7))
21         {
22                 AMn = DREG;
23                 AnREG = *tok++ & 7;
24         }
25         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
26         {
27                 AMn = AREG;
28                 AnREG = *tok++ & 7;
29         }
30         else if (*tok == '#')
31         {
32                 tok++;
33
34                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
35                         return ERROR;
36
37                 AMn = IMMED;
38         }
39
40         // Small problem with this is that the opening parentheses might be an
41         // expression that's part of a displacement; this code will falsely flag
42         // that as an error.
43
44         // (An)
45         // (An)+
46         // (An,Xn[.siz][*scale])
47         // (PC,Xn[.siz][*scale])
48         // (d16,An)
49         // (d8,An,Xn[.siz][*scale])
50         // (d16,PC)
51         // (d8,PC,Xn[.siz][*scale])
52         // ([bd,An],Xn[.siz][*scale],od)
53         // ([bd,An,Xn[.siz][*scale]],od)
54         // ([bd,PC],Xn[.siz][*scale],od)
55         // ([bd,PC,Xn[.siz][*scale]],od)
56         else if (*tok == '(')
57         {
58                 tok++;
59
60                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
61                 {
62                         AnREG = *tok++ & 7;
63
64                         if (*tok == ')')
65                         {
66                                 tok++;
67
68                                 if (*tok == '+')
69                                 {
70                                         tok++;
71                                         AMn = APOSTINC;
72                                 }
73                                 else
74                                         AMn = AIND;
75
76                                 goto AnOK;
77                         }
78
79                         AMn = AINDEXED;
80                         goto AMn_IX0;            // Handle ",Xn[.siz][*scale])"
81                 }
82                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
83                 {
84                         //Since index register isn't used here, store register number in this field
85                         AnIXREG = *tok++ & 7;                                // (Dn)
86
87                         if (*tok == ')')
88                         {
89                                 tok++;
90                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
91                                 AnEXTEN |= EXT_BS;          // Base register suppressed
92                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
93                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
94                                 AMn = MEMPOST;
95                                 AnREG = 6 << 3;         // stuff 110 to mode field
96                                 goto AnOK;
97                         }
98                         else if (*tok == 'L')
99                         {
100                                 AMn = DINDL;                                                                     // (Dn.l)
101                                 AnEXTEN = 1 << 11;   // Long index size
102                                 tok++;
103                         }
104                         else if (*tok == 'W')                                // (Dn.w)
105                         {
106                                 AMn = DINDW;
107                                 AnEXTEN = 0 << 11;   // Word index size
108                                 tok++;
109                         }
110                         else if (*tok == ',')
111                         {
112                                 // ([bd,An],Xn..) without bd, An
113                                 // Base displacement is suppressed
114                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
115                                 AnEXTEN |= EXT_BS;          // Base register suppressed
116                                 AnEXTEN |= EXT_BDSIZE0;
117                                 AnREG = 6 << 3;         // stuff 110 to mode field
118                                 tok++;
119                                 goto CHECKODn;
120                         }
121                         else
122                         {
123                                 return error("(Dn) error");
124                         }
125
126                         if (*tok == '*')
127                         {                        // scale: *1, *2, *4, *8
128                                 tok++;
129
130                                 if (*tok == SYMBOL)
131                                 {
132                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
133                                                 return error("scale factor expression must evaluate");
134
135                                         switch (scaleval)
136                                         {
137                                         case 1:
138                                                 break;
139                                         case 2:
140                                                 AnIXSIZ |= TIMES2;
141                                                 AnEXTEN |= 1 << 9;
142                                                 break;
143                                         case 4:
144                                                 AnIXSIZ |= TIMES4;
145                                                 AnEXTEN |= 2 << 9;
146                                                 break;
147                                         case 8:
148                                                 AnIXSIZ |= TIMES8;
149                                                 AnEXTEN |= 3 << 9;
150                                                 break;
151                                         default:
152                                                 goto badmode;
153                                         }
154                                 }
155                                 else if (*tok++ != CONST)
156                                         goto badmode;
157                                 else
158                                 {
159                                         switch ((int)*tok++)
160                                         {
161                                         case 1:
162                                                 break;
163                                         case 2:
164                                                 AnIXSIZ |= TIMES2;
165                                                 AnEXTEN |= 1 << 9;
166                                                 break;
167                                         case 4:
168                                                 AnIXSIZ |= TIMES4;
169                                                 AnEXTEN |= 2 << 9;
170                                                 break;
171                                         case 8:
172                                                 AnIXSIZ |= TIMES8;
173                                                 AnEXTEN |= 3 << 9;
174                                                 break;
175                                         default:
176                                                 goto badmode;
177                                         }
178
179                                         tok++;  // Take into account that constants are 64-bit
180                                 }
181                         }
182
183                         if (*tok == ')')
184                         {
185                                 tok++;
186                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
187                                 AnEXTEN |= EXT_BS;          // Base register suppressed
188                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
189                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
190                                 AnREG = 6 << 3;         // stuff 110 to mode field
191                                 AMn = MEMPOST;
192                                 goto AnOK;
193                         }
194                         else if (*tok == ',')
195                         {
196                                 tok++;  // eat the comma
197                                 // It might be (Dn[.wl][*scale],od)
198                                 // Maybe this is wrong and we have to write some code here
199                                 // instead of reusing that path...
200                                 AnEXTEN |= EXT_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                                         switch (scaleval)
255                                         {
256                                         case 1:
257                                                 break;
258                                         case 2:
259                                                 AnIXSIZ |= TIMES2;
260                                                 break;
261                                         case 4:
262                                                 AnIXSIZ |= TIMES4;
263                                                 break;
264                                         case 8:
265                                                 AnIXSIZ |= TIMES8;
266                                                 break;
267                                         default:
268                                                 goto badmode;
269                                         }
270                                 }
271                                 else if (*tok++ != CONST)
272                                         goto badmode;
273                                 else
274                                 {
275                                         switch ((int)*tok++)
276                                         {
277                                         case 1:
278                                                 break;
279                                         case 2:
280                                                 AnIXSIZ |= TIMES2;
281                                                 break;
282                                         case 4:
283                                                 AnIXSIZ |= TIMES4;
284                                                 break;
285                                         case 8:
286                                                 AnIXSIZ |= TIMES8;
287                                                 break;
288                                         default:
289                                                 goto badmode;
290                                         }
291
292                                         tok++;  // Take into account that constants are 64-bit
293                                 }
294                         }
295
296                         if (*tok == ',')
297                         {
298                                 // If we got here we didn't get any [] stuff
299                                 // so let's suppress base displacement before
300                                 // branching off
301                                 tok++;
302                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null - suppressed
303                                 goto CHECKODn;
304                         }
305                         if (*tok++ != ')')         // final ")"
306                                 goto badmode;
307
308                         goto AnOK;
309                 }
310                 else if (*tok == '[')
311                 {                              // ([...
312                         tok++;
313                         AnEXTEN |= EXT_FULLWORD;     // Definitely using full extension format, so set bit 8
314
315                         // Check to see if base displacement is present
316                         if (*tok != CONST && *tok != SYMBOL)
317                         {
318                                 AnEXTEN |= EXT_BDSIZE0;
319                         }
320                         else
321                         {
322                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
323                                 if (CHECK_OPTS(OPT_BASE_DISP) && AnBEXVAL == 0 && AnEXATTR != 0)
324                                 {
325                                         // bd=0 so let's optimise it out
326                                         AnEXTEN|=EXT_BDSIZE0;
327                                 }
328                                 else if (*tok == DOTL)
329                                 {                                               // ([bd.l,...
330                                                 AnEXTEN |= EXT_BDSIZEL;
331                                                 tok++;
332                                 }
333                                 else
334                                 {                                               // ([bd[.w],... or ([bd,...
335                                         // Is .W forced here?
336                                         if (*tok == DOTW)
337                                         {
338                                                 AnEXTEN |= EXT_BDSIZEW;
339                                                 tok++;
340                                         }
341                                         else
342                                         {
343                                                 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
344                                                 // to absolute short
345                                                 if (CHECK_OPTS(OPT_ABS_SHORT)
346                                                         && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
347                                                         && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
348                                                 {
349                                                         AnEXTEN |= EXT_BDSIZEW;
350                                                         warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
351                                                 }
352                                                 else
353                                                 {
354                                                         AnEXTEN |= EXT_BDSIZEL;
355                                                 }
356                                         }
357                                 }
358
359                                 if (*tok == ',')
360                                         tok++;
361                                 //else
362                                 //      return error("Comma expected after base displacement");
363                         }
364
365                         // Check for address register or PC, suppress base register
366                         // otherwise
367
368                         if (*tok == KW_PC)
369                         {                                       // ([bd,PC,...
370                                 AnREG = (7 << 3) | 3;   // PC is special case - stuff 011 to register field and 111 to the mode field
371                                 tok++;
372                         }
373                         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
374                         {                                       // ([bd,An,...
375                                 AnREG = (6 << 3) | (*tok & 7);
376                                 tok++;
377                         }
378                         else if ((*tok >= KW_D0) && (*tok <= KW_D7))
379                         {
380                                 // ([bd,Dn,...
381                                 AnREG = (6 << 3);
382                                 AnEXTEN |= ((*tok & 7) << 12);
383                                 AnEXTEN |= EXT_D;
384                                 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
385                                 tok++;
386
387                                 // Check for size
388                                 {
389                                         // ([bd,An/PC],Xn.W/L...)
390                                         switch ((int)*tok)
391                                 {
392                                         // Index reg size: <empty> | .W | .L
393                                         case DOTW:
394                                                 tok++;
395                                                 break;
396                                         default:
397                                                 break;
398                                         case DOTL:
399                                                 AnEXTEN |= EXT_L;
400                                                 tok++;
401                                                 break;
402                                         case DOTB:
403                                                 // .B not allowed here...
404                                                 goto badmode;
405                                         }
406                                 }
407
408                                 // Check for scale
409                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
410                                 {                           // scale: *1, *2, *4, *8
411                                         tok++;
412
413                                         if (*tok == SYMBOL)
414                                         {
415                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
416                                                         return error("scale factor expression must evaluate");
417
418                                                 switch (scaleval)
419                                                 {
420                                                 case 1:
421                                                         break;
422                                                 case 2:
423                                                         AnIXSIZ |= TIMES2;
424                                                         break;
425                                                 case 4:
426                                                         AnIXSIZ |= TIMES4;
427                                                         break;
428                                                 case 8:
429                                                         AnIXSIZ |= TIMES8;
430                                                         break;
431                                                 default:
432                                                         goto badmode;
433                                 }
434                                         }
435                                         else if (*tok++ != CONST)
436                                                 goto badmode;
437                                         else
438                                         {
439                                                 switch ((int)*tok++)
440                                                 {
441                                                 case 1:
442                                                         break;
443                                                 case 2:
444                                                         AnIXSIZ |= TIMES2;
445                                                         break;
446                                                 case 4:
447                                                         AnIXSIZ |= TIMES4;
448                                                         break;
449                                                 case 8:
450                                                         AnIXSIZ |= TIMES8;
451                                                         break;
452                                                 default:
453                                                         goto badmode;
454                                                 }
455
456                                                 tok++;  // Take into account that constants are 64-bit
457                                         }
458                                 }
459                                 if (*tok == ']')  // ([bd,Dn]...
460                                 {
461                                         tok++;
462                                         goto IS_SUPPRESSEDn;
463                                 }
464                         }
465                         else if (*tok == ']')
466                         {
467                                 // PC and Xn is suppressed
468                                 AnREG = 6 << 3;         // stuff 110 to mode field
469                                 //AnEXTEN|=EXT_BS|EXT_IS;
470                                 AnEXTEN |= EXT_BS;
471                         }
472                         else
473                         {
474                                 goto badmode;
475                         }
476
477                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
478                         if (*tok == ']')
479                         {
480                                 //([bd,An/PC],Xn,od)
481                                 // Check for Xn
482                                 tok++;
483
484                                 if (*tok == ')')
485                                 {
486                                         //Xn and od are non existent, get out of jail free card
487                                         tok++;
488                                         AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
489                                         AnEXTEN |= EXT_IS | EXT_IISPREN;        //Suppress Xn and od
490                                         goto AnOK;
491                                 }
492                                 else if (*tok != ',')
493                                         return error("comma expected after ]");
494                                 else
495                                         tok++;                          // eat the comma
496
497                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
498                                 {
499                                         AnIXREG = ((*tok & 7) << 12);
500                                         AnEXTEN |= EXT_A;
501                                         tok++;
502                                 }
503                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
504                                 {
505                                         AnEXTEN |= ((*tok & 7) << 12);
506                                         AnEXTEN |= EXT_D;
507                                         tok++;
508                                 }
509                                 else
510                                 {
511                                         //No index found, suppress it
512                                         AnEXTEN |= EXT_IS;
513                                         tok--;                                  // Rewind tok to point to the comma
514                                         goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
515                                 }
516
517                                 // Check for size
518                                 {
519                                         // ([bd,An/PC],Xn.W/L...)
520                                         switch ((int)*tok)
521                                         {
522                                         // Index reg size: <empty> | .W | .L
523                                         case DOTW:
524                                                 tok++;
525                                                 break;
526                                         default:
527                                                 break;
528                                         case DOTL:
529                                                 AnEXTEN |= EXT_L;
530                                                 tok++;
531                                                 break;
532                                         case DOTB:
533                                                 // .B not allowed here...
534                                                 goto badmode;
535                                         }
536                                 }
537
538                                 // Check for scale
539                                 if (*tok == '*')                   // ([bd,An/PC],Xn*...)
540                                 {                                  // scale: *1, *2, *4, *8
541                                         tok++;
542
543                                         if (*tok == SYMBOL)
544                                         {
545                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
546                                                         return error("scale factor expression must evaluate");
547
548                                                 switch (scaleval)
549                                                 {
550                                                 case 1:
551                                                         break;
552                                                 case 2:
553                                                         AnIXSIZ |= TIMES2;
554                                                         break;
555                                                 case 4:
556                                                         AnIXSIZ |= TIMES4;
557                                                         break;
558                                                 case 8:
559                                                         AnIXSIZ |= TIMES8;
560                                                         break;
561                                                 default:
562                                                         goto badmode;
563                                                 }
564                                         }
565                                         else if (*tok++ != CONST)
566                                                 goto badmode;
567                                         else
568                                         {
569                                                 switch ((int)*tok++)
570                                                 {
571                                                 case 1:
572                                                         break;
573                                                 case 2:
574                                                         AnIXSIZ |= TIMES2;
575                                                         break;
576                                                 case 4:
577                                                         AnIXSIZ |= TIMES4;
578                                                         break;
579                                                 case 8:
580                                                         AnIXSIZ |= TIMES8;
581                                                         break;
582                                                 default:
583                                                         goto badmode;
584                                                 }
585
586                                                 tok++;  // Take into account that constants are 64-bit
587                                         }
588                                 }
589
590                                 // Check for od
591                                 if (*tok == ')')        // ([bd,An/PC],Xn)
592                                 {
593                                         // od is non existent, get out of jail free card
594                                         AMn = MEMPOST;          // let's say it's ([bd,An],Xn,od) with od=0 then
595                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
596                                         tok++;
597                                         goto AnOK;
598                                 }
599                                 else if (*tok != ',')
600                                         return error("comma expected");
601                                 else
602                                         tok++;  // eat the comma
603
604                                 CHECKODn:
605                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
606                                         goto badmode;
607
608                                 if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
609                                 {
610                                         // od=0 so optimise it out
611                                         AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
612                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
613                                         tok++;
614                                         goto AnOK;
615                                 }
616
617                                 // ([bd,An/PC],Xn,od)
618                                 if (*tok == DOTL)
619                                 {
620                                         // expr.L
621                                         if (!(AnEXTEN & EXT_BS))
622                                                 AnEXTEN |= EXT_IISPOSL; // Long outer displacement
623                                         else
624                                         {
625                                                 // bd is suppressed, so sticking the od size in bd
626                                                 AnEXTEN |= EXT_BDSIZEL;
627                                                 // And of course the expression has to be copied to
628                                                 // AnBEXPR instead of AnEXPR. Yay. :-/
629                                                 int i = 0;
630
631                                                 do
632                                                 {
633                                                         AnBEXPR[i] = AnEXPR[i];
634                                                         i++;
635                                                 }
636                                                 while (AnEXPR[i] != 'E');
637
638                                                 AnBEXPR[i] = 'E';
639                                         }
640
641                                         AMn = MEMPOST;
642                                         tok++;
643
644                                         // Defined, absolute values from $FFFF8000..$00007FFF get
645                                         // optimized to absolute short
646                                         if (CHECK_OPTS(OPT_ABS_SHORT)
647                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
648                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
649                                         {
650                                                 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
651                                                 AMn = MEMPOST;
652                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
653                                         }
654
655                                 }
656                                 else
657                                 {
658                                         // expr[.W]
659                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
660                                         AMn = MEMPOST;
661
662                                         // Is .W forced here?
663                                         if (*tok == DOTW)
664                                         {
665                                                 tok++;
666                                         }
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_BASE_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_BASE_DISP)
731                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
732                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
733                                         {
734                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
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                                 {
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
787                                 // Check for scale
788                                 if (*tok == '*')                                // ([bd,An/PC],Xn*...)
789                                 {                                                               // scale: *1, *2, *4, *8 
790                                         tok++;
791
792                                         if (*tok == SYMBOL)
793                                         {
794                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
795                                                         return error("scale factor expression must evaluate");
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_BASE_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_BASE_DISP)
896                                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
897                                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
898                                                 {
899                                                         expr_size = EXT_IISPREW;
900                                                         warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
901                                                 }
902                                         }
903
904                                         AnEXTEN |= expr_size; // Assume we have a .w value
905
906                                         // Is .W forced here?
907                                         if (*tok == DOTW)
908                                         {
909                                                 tok++;
910
911                                                 if (expr_size == EXT_IISPREL)
912                                                         return error("outer displacement value does not fit in .w size");
913                                         }
914                                 }
915
916                                 // Check for final closing parenthesis
917                                 if (*tok == ')')
918                                 {
919                                         tok++;
920                                         goto AnOK;
921                                 }
922                                 else
923                                         return error("Closing parenthesis missing on addressing mode");
924                         }
925                         else
926                                 goto badmode;
927                 }
928                 else
929                 {
930                         // (expr...
931                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
932                                 return ERROR;
933
934                         // It could be that this is really just an expression prefixing a
935                         // register as a displacement...
936                         if (*tok == ')')
937                         {
938                                 tok++;
939                                 goto CHK_FOR_DISPn;
940                         }
941
942                         // Otherwise, check for PC & etc displacements...
943                         if (*tok++ != ',')
944                                 goto badmode;
945
946                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
947                         {
948                                 AnREG = *tok & 7;
949                                 tok++;
950
951                                 if (*tok == ',')
952                                 {
953                                         // Check if we're actually doing d8(An,Dn) or (d16,An,Dn[.size][*scale])
954                                         // TODO: not a very clear cut case from what I can think. The only way
955                                         // to distinguish between the two is to check AnEXVAL and see if it's
956                                         // >127 or <-128. But this doesn't work if AnEXVAL isn't defined yet.
957                                         // For now we fall through to d8(An,Dn) but this might bite us in the
958                                         // arse during fixups...
959                                         if ((AnEXATTR & DEFINED) && (AnEXVAL + 0x80 > 0x100))
960                                         {
961                                                 // We're going to treat it as a full extension format with no
962                                                 // indirect access and no base displacement/index register suppression
963                                                 AnEXTEN |= EXT_FULLWORD;        // Definitely using full extension format, so set bit 8
964                                                 AnEXTEN |= EXT_IISPRE0;         // No Memory Indirect Action
965                                                 AnEXTEN |= EXT_BDSIZEL;         // Base Displacement Size Long
966                                                 tok++;                                          // Get past the comma
967
968                                                 // Our expression is techically a base displacement
969                                                 // so let's copy it to the relevant variables so
970                                                 // eagen0.c can pick it up properly
971                                                 //AnBEXPR = AnEXPR;
972                                                 AnBEXVAL = AnEXVAL;
973                                                 AnBEXATTR = AnEXATTR;
974
975                                                 if ((*tok >= KW_D0) && (*tok <= KW_D7))
976                                                 {
977                                                         AnEXTEN |= ((*tok++) & 7) << 12;
978                                                         // Check for size
979                                                         {
980                                                                 switch ((int)*tok)
981                                                                 {
982                                                                 // Index reg size: <empty> | .W | .L
983                                                                 case DOTW:
984                                                                         tok++;
985                                                                         break;
986                                                                 default:
987                                                                         break;
988                                                                 case DOTL:
989                                                                         tok++;
990                                                                         AnEXTEN |= EXT_L;
991                                                                         break;
992                                                                 case DOTB:
993                                                                         // .B not allowed here...
994                                                                         goto badmode;
995                                                                 }
996                                                         }
997                                                         // Check for scale
998                                                         if (*tok == '*')                // ([bd,An/PC],Xn*...)
999                                                         {                                               // scale: *1, *2, *4, *8 
1000                                                                 tok++;
1001
1002                                                                 if (*tok == SYMBOL)
1003                                                                 {
1004                                                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
1005                                                                                 return error("scale factor expression must evaluate");
1006                                                                         switch (scaleval)
1007                                                                         {
1008                                                                         case 1:
1009                                                                                 break;
1010                                                                         case 2:
1011                                                                                 AnIXSIZ |= TIMES2;
1012                                                                                 break;
1013                                                                         case 4:
1014                                                                                 AnIXSIZ |= TIMES4;
1015                                                                                 break;
1016                                                                         case 8:
1017                                                                                 AnIXSIZ |= TIMES8;
1018                                                                                 break;
1019                                                                         default:
1020                                                                                 goto badmode;
1021                                                                         }
1022                                                                 }
1023                                                                 else if (*tok++ != CONST)
1024                                                                         goto badmode;
1025                                                                 else
1026                                                                 {
1027                                                                         switch ((int)*tok++)
1028                                                                         {
1029                                                                         case 1:
1030                                                                                 break;
1031                                                                         case 2:
1032                                                                                 AnIXSIZ |= TIMES2;
1033                                                                                 break;
1034                                                                         case 4:
1035                                                                                 AnIXSIZ |= TIMES4;
1036                                                                                 break;
1037                                                                         case 8:
1038                                                                                 AnIXSIZ |= TIMES8;
1039                                                                                 break;
1040                                                                         default:
1041                                                                                 goto badmode;
1042                                                                         }
1043
1044                                                                         tok++;  // Take into account that constants are 64-bit
1045                                                                 }
1046                                                         }
1047
1048                                                         if (*tok++ != ')')
1049                                                                 return error("Closing parenthesis missing on addressing mode");
1050
1051                                                         // Let's say that this is the closest to our case
1052                                                         AMn = MEMPOST;
1053                                                         goto AnOK;
1054                                                 }
1055                                                 else
1056                                                         goto badmode;
1057                                         }
1058                                                 
1059                                         AMn = AINDEXED;
1060                                         goto AMn_IXN;
1061                                 }
1062                                 else if (*tok == ')')
1063                                 {
1064                                         AMn = ADISP;
1065                                         tok++;
1066                                         goto AnOK;
1067                                 }
1068                                 else
1069                                         goto badmode;
1070                         }
1071                         else if (*tok == KW_PC)
1072                         {
1073                                 if (*++tok == ',')
1074                                 {                             // expr(PC,Xn...)
1075                                         AMn = PCINDEXED;
1076                                         goto AMn_IXN;
1077                                 }
1078                                 else if (*tok == ')')
1079                                 {
1080                                         AMn = PCDISP;             // expr(PC)
1081                                         tok++;
1082                                         goto AnOK;
1083                                 }
1084                                 else
1085                                         goto badmode;
1086                         }
1087                         else
1088                                 goto badmode;
1089                 }
1090         }
1091         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
1092         {
1093                 AMn = APREDEC;
1094                 AnREG = tok[2] & 7;
1095                 tok += 4;
1096         }
1097         else if (*tok == KW_CCR)
1098         {
1099                 AMn = AM_CCR;
1100                 tok++;
1101                 goto AnOK;
1102         }
1103         else if (*tok == KW_SR)
1104         {
1105                 AMn = AM_SR;
1106                 tok++;
1107                 goto AnOK;
1108         }
1109         else if (*tok == KW_USP)
1110         {
1111                 AMn = AM_USP;
1112                 tok++;
1113                 AnREG = 2;      // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
1114                 goto AnOK;
1115         }
1116         else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
1117         {
1118                 AMn = CACHES;
1119                 AnREG = *tok++ - KW_IC40;
1120
1121                 // After a cache keyword only a comma or EOL is allowed
1122                 if ((*tok != ',') && (*tok != EOL))
1123                         return ERROR;
1124                 goto AnOK;
1125         }
1126         else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
1127         {
1128                 AMn = CREG;
1129                 AnREG = (*tok++) - KW_SFC;
1130                 goto AnOK;
1131         }
1132         else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
1133         {
1134                 AMn = FREG;
1135                 AnREG = (*tok++ & 7);
1136         }
1137         else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
1138         {
1139                 AMn = FPSCR;
1140                 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
1141         }
1142         // expr
1143         // expr.w
1144         // expr.l
1145         // d16(An)
1146         // d8(An,Xn[.siz])
1147         // d16(PC)
1148         // d8(PC,Xn[.siz])
1149         else
1150         {
1151                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
1152                         return ERROR;
1153
1154 CHK_FOR_DISPn:
1155                 if (*tok == DOTW)
1156                 {
1157                         // expr.W
1158                         tok++;
1159                         AMn = ABSW;
1160
1161                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
1162                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
1163
1164                         goto AnOK;
1165                 }
1166                 else if (*tok != '(')
1167                 {
1168                         // expr[.L]
1169                         AMn = ABSL;
1170
1171                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
1172                         // to absolute short
1173                         if (CHECK_OPTS(OPT_ABS_SHORT)
1174                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1175                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
1176                         {
1177                                 AMn = ABSW;
1178
1179                                 if (sbra_flag)
1180                                         warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1181                         }
1182
1183                         // Is .L forced here?
1184                         if (*tok == DOTL)
1185                         {
1186                                 tok++;
1187                                 AMn = ABSL;
1188                         }
1189
1190                         goto AnOK;
1191                 }
1192
1193                 tok++;
1194
1195                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
1196                 {
1197                         AnREG = *tok++ & 7;
1198
1199                         if (*tok == ')')
1200                         {
1201                                 AMn = ADISP;
1202                                 tok++;
1203                                 goto AnOK;
1204                         }
1205
1206                         AMn = AINDEXED;
1207                         goto AMn_IXN;
1208                 }
1209                 else if (*tok == KW_PC)
1210                 {
1211                         if (*++tok == ')')
1212                         {
1213                                 AMn = PCDISP;
1214                                 tok++;
1215                                 goto AnOK;
1216                         }
1217
1218                         AMn = PCINDEXED;
1219                         goto AMn_IXN;
1220                 }
1221
1222                 goto badmode;
1223         }
1224
1225         // Addressing mode OK
1226 AnOK:
1227         ;
1228 }
1229
1230 // Clean up dirty little macros
1231 #undef AnOK
1232 #undef AMn
1233 #undef AnREG
1234 #undef AnIXREG
1235 #undef AnIXSIZ
1236 #undef AnEXPR
1237 #undef AnEXVAL
1238 #undef AnEXATTR
1239 #undef AnOEXPR
1240 #undef AnOEXVAL
1241 #undef AnOEXATTR
1242 #undef AnESYM
1243 #undef AMn_IX0
1244 #undef AMn_IXN
1245 #undef CHK_FOR_DISPn
1246 #undef AnBEXPR
1247 #undef AnBEXVAL
1248 #undef AnBEXATTR
1249 #undef AnBZISE
1250 #undef AnEXTEN
1251 #undef AMn_030
1252 #undef IS_SUPPRESSEDn
1253 #undef CHECKODn