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