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