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