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