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