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