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