]> Shamusworld >> Repos - rmac/blob - parmode.h
Version bump for last commit. :-)
[rmac] / parmode.h
1 //
2 // RMAC - Renamed Macro Assembler for all Atari computers
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011-2021 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 >= REG68_D0) && (*tok <= REG68_D7))
21         {
22                 AMn = DREG;
23                 AnREG = *tok++ & 7;
24         }
25         else if ((*tok >= REG68_A0) && (*tok <= REG68_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         // (An)
41         // (An)+
42         // (An,Xn[.siz][*scale])
43         // (PC,Xn[.siz][*scale])
44         // (d16,An)
45         // (d8,An,Xn[.siz][*scale])
46         // (d16,PC)
47         // (d8,PC,Xn[.siz][*scale])
48         // ([bd,An],Xn[.siz][*scale],od)
49         // ([bd,An,Xn[.siz][*scale]],od)
50         // ([bd,PC],Xn[.siz][*scale],od)
51         // ([bd,PC,Xn[.siz][*scale]],od)
52         else if (*tok == '(')
53         {
54                 int ea_PC = 0;                          // Flag that let us know if we have PC or An relative ea
55                 tok++;
56
57                 if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
58                 {
59                         AnREG = *tok++ & 7;
60
61                         if (*tok == ')')
62                         {
63                                 tok++;
64
65                                 if (*tok == '+')
66                                 {
67                                         tok++;
68                                         AMn = APOSTINC;
69                                 }
70                                 else
71                                         AMn = AIND;
72
73                                 goto AnOK;
74                         }
75
76                         AMn = AINDEXED;
77                         goto AMn_IX0;            // Handle ",Xn[.siz][*scale])"
78                 }
79                 else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
80                 {
81                         // Since index register isn't used here, store register number in this field
82                         AnIXREG = *tok++ & 7;                                // (Dn)
83
84                         if (*tok == ')')
85                         {
86                                 tok++;
87                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
88                                 AnEXTEN |= EXT_BS;          // Base register suppressed
89                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
90                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
91                                 AMn = MEMPOST;
92                                 AnREG = 6 << 3;         // stuff 110 to mode field
93                                 goto AnOK;
94                         }
95                         else if (*tok == 'L')
96                         {
97                                 AMn = DINDL;                                                                     // (Dn.l)
98                                 AnEXTEN = 1 << 11;   // Long index size
99                                 tok++;
100                         }
101                         else if (*tok == 'W')                                // (Dn.w)
102                         {
103                                 AMn = DINDW;
104                                 AnEXTEN = 0 << 11;   // Word index size
105                                 tok++;
106                         }
107                         else if (*tok == ',')
108                         {
109                                 // ([bd,An],Xn..) without bd, An
110                                 // Base displacement is suppressed
111                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
112                                 AnEXTEN |= EXT_BS;          // Base register suppressed
113                                 AnEXTEN |= EXT_BDSIZE0;
114                                 AnREG = 6 << 3;         // stuff 110 to mode field
115                                 tok++;
116                                 goto CHECKODn;
117                         }
118                         else
119                         {
120                                 return error("(Dn) error");
121                         }
122
123                         if (*tok == '*')
124                         {                        // scale: *1, *2, *4, *8
125                                 tok++;
126
127                                 if (*tok == SYMBOL)
128                                 {
129                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
130                                                 return error("scale factor expression must evaluate");
131
132                                         switch (scaleval)
133                                         {
134                                         case 1:
135                                                 break;
136                                         case 2:
137                                                 AnIXSIZ |= TIMES2;
138                                                 AnEXTEN |= 1 << 9;
139                                                 break;
140                                         case 4:
141                                                 AnIXSIZ |= TIMES4;
142                                                 AnEXTEN |= 2 << 9;
143                                                 break;
144                                         case 8:
145                                                 AnIXSIZ |= TIMES8;
146                                                 AnEXTEN |= 3 << 9;
147                                                 break;
148                                         default:
149                                                 goto badmode;
150                                         }
151                                 }
152                                 else if (*tok++ != CONST)
153                                         goto badmode;
154                                 else
155                                 {
156                                         switch ((int)*tok++)
157                                         {
158                                         case 1:
159                                                 break;
160                                         case 2:
161                                                 AnIXSIZ |= TIMES2;
162                                                 AnEXTEN |= 1 << 9;
163                                                 break;
164                                         case 4:
165                                                 AnIXSIZ |= TIMES4;
166                                                 AnEXTEN |= 2 << 9;
167                                                 break;
168                                         case 8:
169                                                 AnIXSIZ |= TIMES8;
170                                                 AnEXTEN |= 3 << 9;
171                                                 break;
172                                         default:
173                                                 goto badmode;
174                                         }
175
176                                         tok++;  // Take into account that constants are 64-bit
177                                 }
178                         }
179
180                         if (*tok == ')')
181                         {
182                                 tok++;
183                                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
184                                 AnEXTEN |= EXT_BS;          // Base register suppressed
185                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
186                                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
187                                 AnREG = 6 << 3;         // stuff 110 to mode field
188                                 AMn = MEMPOST;
189                                 goto AnOK;
190                         }
191                         else if (*tok == ',')
192                         {
193                                 tok++;  // eat the comma
194                                 // It might be (Dn[.wl][*scale],od)
195                                 // Maybe this is wrong and we have to write some code here
196                                 // instead of reusing that path...
197                                 AnEXTEN |= EXT_FULLWORD;        // Definitely using full extension format, so set bit 8
198                                 AnEXTEN |= EXT_BS;       // Base displacement null - suppressed
199                                 AnEXTEN |= AnIXREG << 12;
200                                 goto CHECKODn;
201                         }
202                         else
203                                 return error("unhandled so far");
204                 }
205                 else if (*tok == REG68_PC)
206                 {                            // (PC,Xn[.siz][*scale])
207                         tok++;
208                         AMn = PCINDEXED;
209
210                         // Common index handler; enter here with 'tok' pointing at the
211                         // comma.
212
213 AMn_IX0:                 // Handle indexed with missing expr
214
215                         AnEXVAL = 0;
216                         AnEXATTR = ABS | DEFINED;
217
218 AMn_IXN:                 // Handle any indexed (tok -> a comma)
219
220                         if (*tok++ != ',')
221                                 goto badmode;
222
223                         if (*tok < REG68_D0 || *tok > REG68_A7)
224                                 goto badmode;
225
226                         AnIXREG = *tok++ & 15;
227
228                         switch ((int)*tok)
229                         {                        // Index reg size: <empty> | .W | .L
230                         case DOTW:
231                                 tok++;
232                         default:
233                                 AnIXSIZ = 0;
234                                 break;
235                         case DOTL:
236                                 AnIXSIZ = 0x0800;
237                                 tok++;
238                                 break;
239                         case DOTB:               // .B not allowed here...
240                                 goto badmode;
241                         }
242
243                         if (*tok == '*')
244                         {                        // scale: *1, *2, *4, *8
245                                 tok++;
246
247                                 if (*tok == SYMBOL)
248                                 {
249                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
250                                                 return error("scale factor expression must evaluate");
251
252                                         switch (scaleval)
253                                         {
254                                         case 1:
255                                                 break;
256                                         case 2:
257                                                 AnIXSIZ |= TIMES2;
258                                                 break;
259                                         case 4:
260                                                 AnIXSIZ |= TIMES4;
261                                                 break;
262                                         case 8:
263                                                 AnIXSIZ |= TIMES8;
264                                                 break;
265                                         default:
266                                                 goto badmode;
267                                         }
268                                 }
269                                 else if (*tok++ != CONST)
270                                         goto badmode;
271                                 else
272                                 {
273                                         switch ((int)*tok++)
274                                         {
275                                         case 1:
276                                                 break;
277                                         case 2:
278                                                 AnIXSIZ |= TIMES2;
279                                                 break;
280                                         case 4:
281                                                 AnIXSIZ |= TIMES4;
282                                                 break;
283                                         case 8:
284                                                 AnIXSIZ |= TIMES8;
285                                                 break;
286                                         default:
287                                                 goto badmode;
288                                         }
289
290                                         tok++;  // Take into account that constants are 64-bit
291                                 }
292                         }
293
294                         if (*tok == ',')
295                         {
296                                 // If we got here we didn't get any [] stuff
297                                 // so let's suppress base displacement before
298                                 // branching off
299                                 tok++;
300                                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null - suppressed
301                                 goto CHECKODn;
302                         }
303                         if (*tok++ != ')')         // final ")"
304                                 goto badmode;
305
306                         goto AnOK;
307                 }
308                 else if (*tok == '[')
309                 {                              // ([...
310                         tok++;
311                         AnEXTEN |= EXT_FULLWORD;     // Definitely using full extension format, so set bit 8
312
313                         // Check to see if base displacement is present
314                         if (*tok != CONST && *tok != SYMBOL)
315                         {
316                                 AnEXTEN |= EXT_BDSIZE0;
317                         }
318                         else
319                         {
320                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
321
322                                 if (CHECK_OPTS(OPT_020_DISP) && (AnBEXVAL == 0) && (AnEXATTR != 0))
323                                 {
324                                         // bd = 0 so let's optimise it out
325                                         AnEXTEN |= EXT_BDSIZE0;
326                                 }
327                                 else if (*tok == DOTL)
328                                 {
329                                         // ([bd.l,...
330                                         AnEXTEN |= EXT_BDSIZEL;
331                                         tok++;
332                                 }
333                                 else
334                                 {
335                                         // ([bd[.w],... or ([bd,...
336                                         // Is .W forced here?
337                                         if (*tok == DOTW)
338                                         {
339                                                 AnEXTEN |= EXT_BDSIZEW;
340                                                 tok++;
341                                         }
342                                         else
343                                         {
344                                                 // Defined, absolute values from $FFFF8000..$00007FFF
345                                                 // get optimized to absolute short
346                                                 if (CHECK_OPTS(OPT_020_DISP)
347                                                         && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
348                                                         && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
349                                                 {
350                                                         AnEXTEN |= EXT_BDSIZEW;
351
352                                                         if (optim_warn_flag)
353                                                                 warn("o5: absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
354                                                 }
355                                                 else
356                                                 {
357                                                         AnEXTEN |= EXT_BDSIZEL;
358                                                 }
359                                         }
360                                 }
361
362                                 if (*tok == ',')
363                                         tok++;
364                         }
365
366                         // Check for address register or PC, suppress base register
367                         // otherwise
368
369                         if (*tok == REG68_PC)
370                         {                                       // ([bd,PC,...
371                                 ea_PC = 3;                              // Set flag in order to set proper value to AMn below when we can make a decision on ea
372                                                                                 // (why "3"? Well, MEMPOST is 3 away from PCMPOST, etc. Have a look at amode.h)
373                                 AnREG = (7 << 3) | 3;   // PC is special case - stuff 011 to register field and 111 to the mode field
374                                 tok++;
375                         }
376                         else if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
377                         {                                       // ([bd,An,...
378                                 AnREG = (6 << 3) | (*tok & 7);
379                                 tok++;
380                         }
381                         else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
382                         {
383                                 // ([bd,Dn,...
384                                 AnREG = (6 << 3);
385                                 AnEXTEN |= ((*tok & 7) << 12);
386                                 AnEXTEN |= EXT_D;
387                                 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
388                                 tok++;
389
390                                 // Check for size
391                                 // ([bd,An/PC],Xn.W/L...)
392                                 switch ((int)*tok)
393                                 {
394                                 // Index reg size: <empty> | .W | .L
395                                 case DOTW:
396                                         tok++;
397                                         break;
398                                 default:
399                                         break;
400                                 case DOTL:
401                                         AnEXTEN |= EXT_L;
402                                         tok++;
403                                         break;
404                                 case DOTB:
405                                         // .B not allowed here...
406                                         goto badmode;
407                                 }
408
409                                 // Check for scale
410                                 if (*tok == '*')                        // ([bd,An/PC],Xn*...)
411                                 {                           // scale: *1, *2, *4, *8
412                                         tok++;
413
414                                         if (*tok == SYMBOL)
415                                         {
416                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
417                                                         return error("scale factor expression must evaluate");
418
419                                                 switch (scaleval)
420                                                 {
421                                                 case 1:
422                                                         break;
423                                                 case 2:
424                                                         AnIXSIZ |= TIMES2;
425                                                         break;
426                                                 case 4:
427                                                         AnIXSIZ |= TIMES4;
428                                                         break;
429                                                 case 8:
430                                                         AnIXSIZ |= TIMES8;
431                                                         break;
432                                                 default:
433                                                         goto badmode;
434                                 }
435                                         }
436                                         else if (*tok++ != CONST)
437                                                 goto badmode;
438                                         else
439                                         {
440                                                 switch ((int)*tok++)
441                                                 {
442                                                 case 1:
443                                                         break;
444                                                 case 2:
445                                                         AnIXSIZ |= TIMES2;
446                                                         break;
447                                                 case 4:
448                                                         AnIXSIZ |= TIMES4;
449                                                         break;
450                                                 case 8:
451                                                         AnIXSIZ |= TIMES8;
452                                                         break;
453                                                 default:
454                                                         goto badmode;
455                                                 }
456
457                                                 tok++;  // Take into account that constants are 64-bit
458                                         }
459                                 }
460                                 if (*tok == ']')  // ([bd,Dn]...
461                                 {
462                                         tok++;
463                                         goto IS_SUPPRESSEDn;
464                                 }
465                         }
466                         else if (*tok == ']')
467                         {
468                                 // PC and Xn is suppressed
469                                 AnREG = 6 << 3;         // stuff 110b to mode field
470                                 AnEXTEN |= EXT_BS;
471                         }
472                         else
473                         {
474                                 goto badmode;
475                         }
476
477                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
478                         if (*tok == ']')
479                         {
480                                 // ([bd,An/PC],Xn,od)
481                                 // Check for Xn
482                                 tok++;
483
484                                 if (*tok == ')')
485                                 {
486                                         // Xn and od are non existent, get out of jail free card
487                                         tok++;
488                                         AMn = MEMPRE + ea_PC;                           // ([bc,An,Xn],od) with no Xn and od
489                                         AnEXTEN |= EXT_IS | EXT_IISPREN;        // Suppress Xn and od
490                                         goto AnOK;
491                                 }
492                                 else if (*tok != ',')
493                                         return error("comma expected after ]");
494                                 else
495                                         tok++;                          // eat the comma
496
497                                 if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
498                                 {
499                                         AnIXREG = ((*tok & 7) << 12);
500                                         AnEXTEN |= EXT_A;
501                                         tok++;
502                                 }
503                                 else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
504                                 {
505                                         AnEXTEN |= ((*tok & 7) << 12);
506                                         AnEXTEN |= EXT_D;
507                                         tok++;
508                                 }
509                                 else
510                                 {
511                                         // No index found, suppress it
512                                         AnEXTEN |= EXT_IS;
513                                         tok--;                                  // Rewind tok to point to the comma
514                                         goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
515                                 }
516
517                                 // Check for Xn size
518                                 // ([bd,An/PC],Xn.W/L...)
519                                 switch ((int)*tok)
520                                 {
521                                 // Index reg size: <empty> | .W | .L
522                                 case DOTW:
523                                         tok++;
524                                         break;
525                                 case DOTL:
526                                         AnEXTEN |= EXT_L;
527                                         tok++;
528                                         break;
529                                 case DOTB:
530                                         // .B not allowed here...
531                                         goto badmode;
532                                 default:
533                                         break;
534                                 }
535
536                                 // Check for Xn scale
537                                 if (*tok == '*')                   // ([bd,An/PC],Xn*...)
538                                 {                                  // scale: *1, *2, *4, *8
539                                         tok++;
540
541                                         if (*tok == SYMBOL)
542                                         {
543                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
544                                                         return error("scale factor expression must evaluate");
545                                         }
546                                         else if (*tok == CONST)
547                                         {
548                                                 scaleval = (int)*tok++;
549                                                 tok++;  // Take into account that constants are 64-bit
550                                         }
551                                         else
552                                                 goto badmode;
553
554                                         switch (scaleval)
555                                         {
556                                         case 1:
557                                                 break;
558                                         case 2:
559                                                 AnIXSIZ |= TIMES2;
560                                                 break;
561                                         case 4:
562                                                 AnIXSIZ |= TIMES4;
563                                                 break;
564                                         case 8:
565                                                 AnIXSIZ |= TIMES8;
566                                                 break;
567                                         default:
568                                                 goto badmode;
569                                         }
570
571                                 }
572
573                                 // Check for od
574                                 if (*tok == ')')        // ([bd,An/PC],Xn)
575                                 {
576                                         // od is non existent, get out of jail free card
577                                         AMn = MEMPOST + ea_PC;  // let's say it's ([bd,An],Xn,od) with od=0 then
578                                         AnEXTEN |= EXT_IISPOSN; // No outer displacement
579                                         tok++;
580                                         goto AnOK;
581                                 }
582                                 else if (*tok != ',')
583                                         return error("comma expected");
584                                 else
585                                         tok++;  // eat the comma
586
587 CHECKODn:
588                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
589                                         goto badmode;
590
591                                 if (CHECK_OPTS(OPT_020_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
592                                 {
593                                         // od = 0 so optimise it out
594                                         AMn = MEMPOST + ea_PC;          // let's say it's ([bd,An],Xn,od) with od=0 then
595                                         AnEXTEN |= EXT_IISPOSN;         // No outer displacement
596                                         tok++;
597                                         goto AnOK;
598                                 }
599
600                                 // ([bd,An/PC],Xn,od)
601                                 // Is .W forced here?
602                                 if (*tok == DOTW)
603                                 {
604                                         tok++;
605                                         // od[.W]
606                                         AnEXTEN |= EXT_IISPOSW; // Word outer displacement
607                                         AMn = MEMPOST + ea_PC;
608                                 }
609                                 else
610                                 {
611                                         // Is .L forced here?
612                                         if (*tok == DOTL)
613                                                 tok++;                          // Doesn't matter, we're going for .L anyway
614
615                                         WORD od_ea = 0;
616
617                                         // od.L
618                                         if (!(AnEXTEN & EXT_BS))
619                                                 od_ea = EXT_IISPOSL; // Long outer displacement
620                                         else
621                                         {
622                                                 // bd is suppressed, so sticking the od size in bd
623                                                 od_ea = EXT_BDSIZEL;
624                                                 // And of course the expression has to be copied to
625                                                 // AnBEXPR instead of AnEXPR. Yay. :-/
626                                                 int i = 0;
627
628                                                 do
629                                                 {
630                                                         AnBEXPR[i] = AnEXPR[i];
631                                                         i++;
632                                                 }
633                                                 while (AnEXPR[i] != 'E');
634
635                                                 AnBEXPR[i] = 'E';
636                                         }
637
638                                         AMn = MEMPOST + ea_PC;
639
640                                         // Defined, absolute values from $FFFF8000..$00007FFF get
641                                         // optimized to absolute short
642                                         if (CHECK_OPTS(OPT_020_DISP)
643                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
644                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
645                                         {
646                                                 od_ea = EXT_IISPOSW; // Word outer displacement
647                                                 AMn = MEMPOST + ea_PC;
648
649                                                 if (optim_warn_flag)
650                                                         warn("o5: absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
651                                         }
652                                         AnEXTEN |= od_ea;
653                                 }
654
655                                 // Check for final closing parenthesis
656                                 if (*tok == ')')
657                                 {
658                                         tok++;
659                                         goto AnOK;
660                                 }
661                                 else
662                                         return error("Closing parenthesis missing on addressing mode");
663
664 IS_SUPPRESSEDn:
665
666                                 // Check for od
667                                 if (*tok == ')')        // ([bd,An/PC],Xn)
668                                 {
669                                         // od is non existent, get out of jail free card
670                                         AMn = MEMPOST + ea_PC;          // let's say it's ([bd,An],Xn,od) with od=0 then
671                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
672                                         tok++;
673                                         goto AnOK;
674                                 }
675                                 else if (*tok!=',')
676                                         return error("comma expected");
677                                 else
678                                         tok++;  // eat the comma
679
680                                 if ((*tok != CONST) && (*tok != SYMBOL))
681                                         goto badmode;
682
683                                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
684
685                                 if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0))
686                                 {
687                                         // od=0 so optimise it out
688                                         AMn = MEMPOST + ea_PC;           // let's say it's ([bd,An],Xn,od) with od=0 then
689                                         AnEXTEN |= EXT_IISNOIN; // No outer displacement
690                                         tok++;
691                                         goto AnOK;
692                                 }
693
694                                 // ([bd,An/PC],Xn,od)
695                                 if (*tok == DOTL)
696                                 {
697                                         // expr.L
698                                         tok++;
699                                         AMn = MEMPOST + ea_PC;
700                                         AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
701                                 }
702                                 else
703                                 {
704                                         // expr[.W][]
705                                         AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
706                                         AMn = MEMPRE + ea_PC;;
707
708                                         if (*tok == DOTW)
709                                         {
710                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
711                                                 AMn = MEMPOST + ea_PC;
712                                                 tok++;
713                                         }
714                                         // Defined, absolute values from $FFFF8000..$00007FFF get
715                                         // optimized to absolute short
716                                         else if (CHECK_OPTS(OPT_020_DISP)
717                                                 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
718                                                 && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
719                                         {
720                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
721                                                 if (optim_warn_flag)
722                                                         warn("o5: outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
723                                         }
724                                 }
725
726                                 // Check for final closing parenthesis
727                                 if (*tok == ')')
728                                 {
729                                         tok++;
730                                         goto AnOK;
731                                 }
732                                 else
733                                         return error("Closing parenthesis missing on addressing mode");
734                         }
735                         else if (*tok == ',')
736                         {
737                                 tok++;                  // ([bd,An,Xn.size*scale],od)
738
739                                 // Check for Xn
740                                 if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
741                                 {
742                                         AnEXTEN |= ((*tok & 7) << 12);
743                                         AnEXTEN |= EXT_A;
744                                         tok++;
745                                 }
746                                 else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
747                                 {
748                                         AnEXTEN |= ((*tok & 7) << 12);
749                                         AnEXTEN |= EXT_D;
750                                         tok++;
751                                 }
752
753                                 // Check for size
754                                 // ([bd,An/PC],Xn.W/L...)
755                                 switch ((int)*tok)
756                                 {
757                                 // Index reg size: <empty> | .W | .L
758                                 case DOTW:
759                                         tok++;
760                                         break;
761                                 default:
762                                         break;
763                                 case DOTL:
764                                         tok++;
765                                         AnEXTEN |= EXT_L;
766                                         break;
767                                 case DOTB:
768                                 // .B not allowed here...
769                                 goto badmode;
770                                 }
771
772                                 // Check for scale
773                                 if (*tok == '*')                                // ([bd,An/PC],Xn*...)
774                                 {                                                               // scale: *1, *2, *4, *8
775                                         tok++;
776
777                                         if (*tok == SYMBOL)
778                                         {
779                                                 if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
780                                                         return error("scale factor expression must evaluate");
781
782                                                 switch (scaleval)
783                                                 {
784                                                 case 1:
785                                                         break;
786                                                 case 2:
787                                                         AnIXSIZ |= TIMES2;
788                                                         break;
789                                                 case 4:
790                                                         AnIXSIZ |= TIMES4;
791                                                         break;
792                                                 case 8:
793                                                         AnIXSIZ |= TIMES8;
794                                                         break;
795                                                 default:
796                                                         goto badmode;
797                                                 }
798                                         }
799                                         else if (*tok++ != CONST)
800                                                 goto badmode;
801                                         else
802                                         {
803                                                 switch ((int)*tok++)
804                                                 {
805                                                 case 1:
806                                                         break;
807                                                 case 2:
808                                                         AnIXSIZ |= TIMES2;
809                                                         AnEXTEN |= 1 << 9;
810                                                         break;
811                                                 case 4:
812                                                         AnIXSIZ |= TIMES4;
813                                                         AnEXTEN |= 2 << 9;
814                                                         break;
815                                                 case 8:
816                                                         AnIXSIZ |= TIMES8;
817                                                         AnEXTEN |= 3 << 9;
818                                                         break;
819                                                 default:
820                                                         goto badmode;
821                                                 }
822
823                                                 tok++;  // Take into account that constants are 64-bit
824                                         }
825                                 }
826
827                                 // Check for ]
828                                 if (*tok != ']')
829                                         return error("Expected closing bracket ]");
830                                 tok++;                  // Eat the bracket
831
832                                 // Check for od
833                                 if (*tok == ')')        // ([bd,An/PC,Xn]...
834                                 {
835                                         // od is non existent, get out of jail free card
836                                         AMn = MEMPRE + ea_PC;                   // let's say it's ([bd,An,Xn],od) with od suppressed then
837                                         AnEXTEN |= EXT_IISPREN; // No outer displacement
838                                         tok++;
839                                         goto AnOK;
840                                 }
841                                 else if (*tok++ != ',')
842                                         return error("comma expected after ]");
843
844                                 if (*tok == SYMBOL || *tok == CONST)
845                                 {
846                                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
847                                                 goto badmode;
848
849                                         if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
850                                         {
851                                                 // od=0 so optimise it out
852                                                 AMn = MEMPRE + ea_PC;            // let's say it's ([bd,An],Xn,od) with od=0 then
853                                                 AnEXTEN |= EXT_IISPRE0; // No outer displacement
854                                                 tok++;
855                                                 goto AnOK;
856                                         }
857                                 }
858
859                                 // ([bd,An/PC,Xn],od)
860                                 if (*tok == DOTL)
861                                 {
862                                         // expr.L
863                                         AMn = MEMPRE + ea_PC;
864                                         tok++;
865                                         AnEXTEN |= EXT_IISPREL;
866                                 }
867                                 else
868                                 {
869                                         // expr.[W]
870                                         AMn = MEMPRE + ea_PC;
871                                         int expr_size = EXT_IISPREW; // Assume we have a .w value
872
873                                         if ((AnEXVAL + 0x8000) > 0x10000)
874                                         {
875                                                 // Long value, so mark it as such for now
876                                                 expr_size = EXT_IISPREL;
877
878                                                 // Defined, absolute values from $FFFF8000..$00007FFF
879                                                 // get optimized to absolute short
880                                                 if (CHECK_OPTS(OPT_020_DISP)
881                                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
882                                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
883                                                 {
884                                                         expr_size = EXT_IISPREW;
885
886                                                         if (optim_warn_flag)
887                                                                 warn("o5: outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
888                                                 }
889                                         }
890
891                                         AnEXTEN |= expr_size; // Assume we have a .w value
892
893                                         // Is .W forced here?
894                                         if (*tok == DOTW)
895                                         {
896                                                 tok++;
897
898                                                 if (expr_size == EXT_IISPREL)
899                                                         return error("outer displacement value does not fit in .w size");
900                                         }
901                                 }
902
903                                 // Check for final closing parenthesis
904                                 if (*tok == ')')
905                                 {
906                                         tok++;
907                                         goto AnOK;
908                                 }
909                                 else
910                                         return error("Closing parenthesis missing on addressing mode");
911                         }
912                         else
913                                 goto badmode;
914                 }
915                 else
916                 {
917                         // (expr...
918                         // We have an aliasing problem here, because a couple of differenct cases end up here:
919                         // (a0), 0(a0,d0), (-288,a0,d0.l) can be easily detected and parsed.
920                         // But what about (160*150)+4(A1)? With the old scheme, i.e. skip past the left parenthesis and try to parse the inside
921                         // tokens will only parse (160*150) and everything else is assumed that it's part of the ea, i.e. +4(a1). This would produce
922                         // an error since the parser would expect (a1). The way to work around this used to be to wrap all the displacement in
923                         // parenthesis, ((160*150)+4)(a1). But that's something the user really doesn't want to think about.
924                         // What we can do is to peek ahead in the token stream and see if we have something that reminds of an expression
925                         // (i.e. no register tokens or commas) until we hit an open parenthesis plus a register (parenthesis balance during the scan
926                         // has to be maintained of course, otherwise we might be led into false conclusions).
927                         TOKEN *look_ahead = tok;
928                         int parenthesis_level = 1;      // We count the opening parenthesis so we're not at level 0
929                         int this_is_an_expression = 0;
930                         while (1)
931                         {
932                                 if (*look_ahead == EOL)
933                                 {
934                                         // Something really bad happened, abort
935                                         return error("reached end of line while parsing expression");
936                                 }
937                                 if (*look_ahead == '(')
938                                 {
939                                         if (parenthesis_level == 0)
940                                         {
941                                                 if (look_ahead[1] == EOL)
942                                                 {
943                                                         return error("reached end of line while parsing expression");
944                                                 }
945                                                 if ((look_ahead[1] >= REG68_A0 && look_ahead[1] <= REG68_A7) || look_ahead[1] == REG68_PC)
946                                                 {
947                                                         tok--;                                          // Rewind token pointer to start of parenthesis
948                                                         this_is_an_expression = 1;
949                                                         break;
950                                                 }
951                                         }
952                                         parenthesis_level++;
953                                         look_ahead++;
954                                         continue;
955                                 }
956                                 if (*look_ahead == ',' || (*look_ahead >= REG68_A0 && *look_ahead <= REG68_A7))
957                                 {
958                                         // Nope, this is a different case, abort
959                                         break;
960                                 }
961                                 if (*look_ahead == ')')
962                                 {
963                                         parenthesis_level--;
964                                         if (parenthesis_level < 0) return error("unbalanced parenthesis in expression");
965                                         look_ahead++;
966                                         continue;
967                                 }
968                                 if (*look_ahead == ACONST||*look_ahead==FCONST)
969                                 {
970                                         look_ahead += 3;        // Skip all the data associated with ACONST
971                                         continue;
972                                 }
973
974                                 look_ahead++;
975                         }
976
977                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
978                                 return ERROR;
979
980                         // It could be that this is really just an expression prefixing a
981                         // register as a displacement...
982                         if (*tok == '(')
983                         {
984                                 goto CHK_FOR_DISPn;
985                         }
986
987                         // Otherwise, check for PC & etc displacements...
988                         if (*tok++ != ',')
989                                 goto badmode;
990
991                         if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
992                         {
993                                 AnREG = *tok & 7;
994                                 tok++;
995
996                                 if (*tok == ',')
997                                 {
998                                         // Check if we're actually doing d8(An,Dn) or
999                                         // (d16,An,Dn[.size][*scale])
1000                                         // TODO: not a very clear cut case from what I can think.
1001                                         // The only way to distinguish between the two is to check
1002                                         // AnEXVAL and see if it's >127 or <-128. But this doesn't
1003                                         // work if AnEXVAL isn't defined yet. For now we fall
1004                                         // through to d8(An,Dn) but this might bite us in the arse
1005                                         // during fixups...
1006                                         if ((AnEXATTR & DEFINED) && (AnEXVAL + 0x80 > 0x100))
1007                                         {
1008                                                 // We're going to treat it as a full extension format
1009                                                 // with no indirect access and no base displacement/
1010                                                 // index register suppression
1011                                                 AnEXTEN |= EXT_FULLWORD;        // Definitely using full extension format, so set bit 8
1012                                                 AnEXTEN |= EXT_IISPRE0;         // No Memory Indirect Action
1013                                                 AnEXTEN |= EXT_BDSIZEL;         // Base Displacement Size Long
1014                                                 tok++;                                          // Get past the comma
1015
1016                                                 // Our expression is techically a base displacement,
1017                                                 // so let's copy it to the relevant variables so
1018                                                 // eagen0.c can pick it up properly
1019                                                 AnBEXVAL = AnEXVAL;
1020                                                 AnBEXATTR = AnEXATTR;
1021
1022                                                 if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
1023                                                 {
1024                                                         AnEXTEN |= ((*tok++) & 7) << 12;
1025                                                         // Check for size
1026                                                         {
1027                                                                 switch ((int)*tok)
1028                                                                 {
1029                                                                 // Index reg size: <empty> | .W | .L
1030                                                                 case DOTW:
1031                                                                         tok++;
1032                                                                         break;
1033                                                                 default:
1034                                                                         break;
1035                                                                 case DOTL:
1036                                                                         tok++;
1037                                                                         AnEXTEN |= EXT_L;
1038                                                                         break;
1039                                                                 case DOTB:
1040                                                                         // .B not allowed here...
1041                                                                         goto badmode;
1042                                                                 }
1043                                                         }
1044                                                         // Check for scale
1045                                                         if (*tok == '*')                // (d16,An,Dn[.size][*scale])
1046                                                         {                                               // scale: *1, *2, *4, *8
1047                                                                 tok++;
1048
1049                                                                 if (*tok == SYMBOL)
1050                                                                 {
1051                                                                         if (expr(scaleexpr, &scaleval, &scaleattr, &scaleesym) != OK)
1052                                                                                 return error("scale factor expression must evaluate");
1053
1054                                                                         switch (scaleval)
1055                                                                         {
1056                                                                         case 1:
1057                                                                                 break;
1058                                                                         case 2:
1059                                                                                 AnIXSIZ |= TIMES2;
1060                                                                                 break;
1061                                                                         case 4:
1062                                                                                 AnIXSIZ |= TIMES4;
1063                                                                                 break;
1064                                                                         case 8:
1065                                                                                 AnIXSIZ |= TIMES8;
1066                                                                                 break;
1067                                                                         default:
1068                                                                                 goto badmode;
1069                                                                         }
1070                                                                 }
1071                                                                 else if (*tok++ != CONST)
1072                                                                         goto badmode;
1073                                                                 else
1074                                                                 {
1075                                                                         switch ((int)*tok++)
1076                                                                         {
1077                                                                         case 1:
1078                                                                                 break;
1079                                                                         case 2:
1080                                                                                 AnIXSIZ |= TIMES2;
1081                                                                                 break;
1082                                                                         case 4:
1083                                                                                 AnIXSIZ |= TIMES4;
1084                                                                                 break;
1085                                                                         case 8:
1086                                                                                 AnIXSIZ |= TIMES8;
1087                                                                                 break;
1088                                                                         default:
1089                                                                                 goto badmode;
1090                                                                         }
1091
1092                                                                         tok++;  // Take into account that constants are 64-bit
1093                                                                 }
1094                                                         }
1095
1096                                                         if (*tok++ != ')')
1097                                                                 return error("Closing parenthesis missing on addressing mode");
1098
1099                                                         // Let's say that this is the closest to our case
1100                                                         AMn = MEMPOST;
1101                                                         goto AnOK;
1102                                                 }
1103                                                 else
1104                                                         goto badmode;
1105                                         }
1106
1107                                         AMn = AINDEXED;
1108                                         goto AMn_IXN;
1109                                 }
1110                                 else if (*tok == ')')
1111                                 {
1112                                         AMn = ADISP;
1113                                         tok++;
1114                                         goto AnOK;
1115                                 }
1116                                 else
1117                                         goto badmode;
1118                         }
1119                         else if (*tok == REG68_PC)
1120                         {
1121                                 if (*++tok == ',')
1122                                 {                             // expr(PC,Xn...)
1123                                         AMn = PCINDEXED;
1124                                         goto AMn_IXN;
1125                                 }
1126                                 else if (*tok == ')')
1127                                 {
1128                                         AMn = PCDISP;             // expr(PC)
1129                                         tok++;
1130                                         goto AnOK;
1131                                 }
1132                                 else
1133                                         goto badmode;
1134                         }
1135                         else
1136                                 goto badmode;
1137                 }
1138         }
1139         else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= REG68_A0) && (tok[2] <= REG68_A7)) && tok[3] == ')')
1140         {
1141                 AMn = APREDEC;
1142                 AnREG = tok[2] & 7;
1143                 tok += 4;
1144         }
1145         else if (*tok == REG68_CCR)
1146         {
1147                 AMn = AM_CCR;
1148                 tok++;
1149                 goto AnOK;
1150         }
1151         else if (*tok == REG68_SR)
1152         {
1153                 AMn = AM_SR;
1154                 tok++;
1155                 goto AnOK;
1156         }
1157         else if (*tok == REG68_USP)
1158         {
1159                 AMn = AM_USP;
1160                 tok++;
1161                 AnREG = 2;      // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
1162                 goto AnOK;
1163         }
1164         else if ((*tok >= REG68_IC40) && (*tok <= REG68_BC40))
1165         {
1166                 AMn = CACHES;
1167                 AnREG = *tok++ - REG68_IC40;
1168
1169                 // After a cache keyword only a comma or EOL is allowed
1170                 if ((*tok != ',') && (*tok != EOL))
1171                         return ERROR;
1172                 goto AnOK;
1173         }
1174         else if ((*tok >= REG68_SFC) && (*tok <= REG68_CRP))
1175         {
1176                 AMn = CREG;
1177                 AnREG = (*tok++) - REG68_SFC;
1178                 goto AnOK;
1179         }
1180         else if ((*tok >= REG68_FP0) && (*tok <= REG68_FP7))
1181         {
1182                 AMn = FREG;
1183                 AnREG = (*tok++ & 7);
1184         }
1185         else if ((*tok >= REG68_FPIAR) && (*tok <= REG68_FPCR))
1186         {
1187                 AMn = FPSCR;
1188                 AnREG = (1 << ((*tok++) - REG68_FPIAR + 10));
1189         }
1190         // expr
1191         // expr.w
1192         // expr.l
1193         // d16(An)
1194         // d8(An,Xn[.siz])
1195         // d16(PC)
1196         // d8(PC,Xn[.siz])
1197         else
1198         {
1199                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
1200                         return ERROR;
1201
1202 CHK_FOR_DISPn:
1203                 if (*tok == DOTW)
1204                 {
1205                         // expr.W
1206                         tok++;
1207                         AMn = ABSW;
1208
1209                         if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
1210                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
1211
1212                         goto AnOK;
1213                 }
1214                 else if (*tok != '(')
1215                 {
1216                         // expr[.L]
1217                         AMn = ABSL;
1218
1219                         // .L is forced here
1220                         if (*tok == DOTL)
1221                         {
1222                                 // When PC relative is enforced, check for any symbols that aren't
1223                                 // EQU'd, in this case it's an illegal mode
1224                                 if ((CHECK_OPTS(OPT_PC_RELATIVE)) && ((AnEXATTR & (DEFINED | REFERENCED | EQUATED)) == (DEFINED | REFERENCED)))
1225                                         return error("relocation not allowed when o30 is enabled");
1226
1227                                 tok++;
1228                         }
1229                         else
1230                         {
1231                                 // Defined, absolute values from $FFFF8000..$00007FFF get
1232                                 // optimized to absolute short
1233                                 if (CHECK_OPTS(OPT_ABS_SHORT)
1234                                         && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1235                                         && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
1236                                 {
1237                                         AMn = ABSW;
1238
1239                                         if (optim_warn_flag)
1240                                                 warn("o0: absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1241                                 }
1242                         }
1243
1244                         goto AnOK;
1245                 }
1246
1247                 tok++;
1248
1249                 if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
1250                 {
1251                         AnREG = *tok++ & 7;
1252
1253                         if (*tok == ')')
1254                         {
1255                                 AMn = ADISP;
1256                                 tok++;
1257                                 goto AnOK;
1258                         }
1259
1260                         AMn = AINDEXED;
1261                         goto AMn_IXN;
1262                 }
1263                 else if (*tok == REG68_PC)
1264                 {
1265                         if (*++tok == ')')
1266                         {
1267                                 AMn = PCDISP;
1268                                 tok++;
1269                                 goto AnOK;
1270                         }
1271
1272                         AMn = PCINDEXED;
1273                         goto AMn_IXN;
1274                 }
1275
1276                 goto badmode;
1277         }
1278
1279         // Addressing mode OK
1280 AnOK:
1281         ;
1282 }
1283
1284 // Clean up dirty little macros
1285 #undef AnOK
1286 #undef AMn
1287 #undef AnREG
1288 #undef AnIXREG
1289 #undef AnIXSIZ
1290 #undef AnEXPR
1291 #undef AnEXVAL
1292 #undef AnEXATTR
1293 #undef AnOEXPR
1294 #undef AnOEXVAL
1295 #undef AnOEXATTR
1296 #undef AnESYM
1297 #undef AMn_IX0
1298 #undef AMn_IXN
1299 #undef CHK_FOR_DISPn
1300 #undef AnBEXPR
1301 #undef AnBEXVAL
1302 #undef AnBEXATTR
1303 #undef AnBZISE
1304 #undef AnEXTEN
1305 #undef AMn_030
1306 #undef IS_SUPPRESSEDn
1307 #undef CHECKODn