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