Initial commit for 68020/30/40/60/68881/68882/68851 support.
[rmac] / parmode.h
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 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                         if (*tok==')')
82                         {
83                 tok++;
84                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
85                 AnEXTEN |= EXT_BS;          // Base register suppressed
86                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
87                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
88                 AMn= MEMPOST;
89                 AnREG = 6 << 3;         // stuff 110 to mode field
90                 goto AnOK;
91                         }
92                         else if (*tok=='L')                                
93                         {
94                 // TODO: does DINDL gets used at all?
95                                 //AMn=DINDL;                                     // (Dn.l)
96                 //AnEXTEN = 1 << 1;   // Long index size
97                                 //tok++;
98                         }
99                         else if (*tok=='W')                                 // (Dn.w)
100                         {
101                 // TODO: does DINDW gets used at all?
102                 //AMn=DINDW;
103                 //AnEXTEN = 1 << 1;   // Word index size
104                 //tok++;
105                         }
106             else if (*tok == ',')
107             {
108                 // ([bd,An],Xn..) without bd, An
109                 // Base displacement is suppressed
110                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
111                 AnEXTEN |= EXT_BS;          // Base register suppressed
112                 AnEXTEN |= EXT_BDSIZE0;
113                 AnREG = 6 << 3;         // stuff 110 to mode field
114                 tok++;
115                 goto CHECKODn;
116             }
117                         else
118                                 return error("(Dn) error");
119
120             if (*tok == ')')
121             {
122                 tok++;
123                 AnEXTEN |= EXT_FULLWORD;    // Definitely using full extension format, so set bit 8
124                 AnEXTEN |= EXT_BS;          // Base register suppressed
125                 AnEXTEN |= EXT_BDSIZE0;     // Base displacement null
126                 AnEXTEN |= EXT_IISPOSN;     // Indirect Postindexed with Null Outer Displacement
127                 AnREG = 6 << 3;         // stuff 110 to mode field
128                 AMn = MEMPOST;
129                 goto AnOK;
130             }
131             else
132                 return error("unhandled so far");
133                 }
134                 else if (*tok == KW_PC)
135                 {                            // (PC,Xn[.siz][*scale])
136                         tok++;
137                         AMn = PCINDEXED;
138
139                         // Common index handler; enter here with 'tok' pointing at the
140                         // comma.
141
142                         AMn_IX0:                 // Handle indexed with missing expr
143
144                         AnEXVAL = 0;
145                         AnEXATTR = ABS | DEFINED;
146
147                         AMn_IXN:                 // Handle any indexed (tok -> a comma)
148
149                         if (*tok++ != ',')
150                                 goto badmode;
151
152                         if (*tok < KW_D0 || *tok > KW_A7)
153                                 goto badmode;
154
155                         AnIXREG = *tok++ & 15;
156
157                         switch ((int)*tok)
158                         {                        // Index reg size: <empty> | .W | .L
159                         case DOTW:
160                                 tok++;
161                         default:
162                                 AnIXSIZ = 0;
163                                 break;
164                         case DOTL:
165                                 AnIXSIZ = 0x0800;
166                                 tok++;
167                                 break;
168                         case DOTB:               // .B not allowed here...
169                                 goto badmode;
170                         }
171
172                         if (*tok == '*')
173                         {                        // scale: *1, *2, *4, *8
174                                 tok++;
175
176                                 if (*tok++ != CONST || *tok > 8)
177                                         goto badmode;
178
179                                 switch ((int)*tok++)
180                                 {
181                                 case 1:
182                                         break;
183                                 case 2:
184                                         AnIXSIZ |= TIMES2;
185                                         break;
186                                 case 4:
187                                         AnIXSIZ |= TIMES4;
188                                         break;
189                                 case 8:
190                                         AnIXSIZ |= TIMES8;
191                                         break;
192                                 default:
193                                         goto badmode;
194                                 }
195                         }
196
197                         if (*tok++ != ')')         // final ")"
198                                 goto badmode;
199
200                         goto AnOK;
201                 }
202                 else if (*tok == '[')
203                 {                              // ([...
204                         tok++;
205                         AnEXTEN|=EXT_FULLWORD;     //Definitely using full extension format, so set bit 8
206                         // Check to see if base displacement is present
207                         //WARNING("expr will return a bad expression error here but this is expected, it needs to be silenced!");
208                         if (*tok!=CONST && *tok !=SYMBOL)
209                         //if (expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM) != OK)
210                         {
211                                 AnEXTEN|=EXT_BDSIZE0;
212                                 //tok++;
213                                 //tok--;                 //Rewind tok since expr advances it forward
214                         }
215                         else
216                         {
217                                 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
218                                 if (optim_flags[OPT_BASE_DISP] && AnBEXVAL==0 && AnEXATTR!=0)
219                                 {
220                                         // bd=0 so let's optimise it out
221                                         AnEXTEN|=EXT_BDSIZE0;
222                                 }
223                                 else if (*tok==DOTL)
224                                 {                                                  // ([bd.l,...
225                                                 AnEXTEN|=EXT_BDSIZEL;
226                                                 tok++;
227                                 }
228                                 else
229                                 {                                                  // ([bd[.w],... or ([bd,...
230                                         // Is .W forced here?
231                                         if (*tok == DOTW)
232                                         {
233                                         AnEXTEN|=EXT_BDSIZEW;
234                                                 tok++;
235                                         }
236                     else
237                     {
238                                             // Defined, absolute values from $FFFF8000..$00007FFF get optimized
239                                             // to absolute short
240                                             if (optim_flags[OPT_ABS_SHORT] && (AnBEXATTR & (TDB|DEFINED)) == DEFINED && (AnBEXVAL + 0x8000) < 0x10000)
241                                             {
242                                                     AnEXTEN|=EXT_BDSIZEW;
243                                                         warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
244                                             }
245                                         else
246                                         {
247                                                     AnEXTEN|=EXT_BDSIZEL;
248                         }
249                     }
250                                 }
251                                 if (*tok==',')
252                                         tok++;
253                                 //else
254                                 //      return error("Comma expected after base displacement");
255                         }
256
257
258                         // Check for address register or PC, suppress base register otherwise
259
260                         if (*tok==KW_PC)
261                         {                                       // ([bd,PC,...
262                                 AnREG=(7<<3)|3; // PC is special case - stuff 011 to register field and 111 to the mode field
263                                 tok++;
264                         }
265                         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
266                         {                                       // ([bd,An,...
267                                 AnREG = (6<<3)|*tok & 7;
268                                 tok++;
269                         }
270                         else if ((*tok >= KW_D0) && (*tok <= KW_D7))
271                         {                                       // ([bd,Dn,...
272                                 AnREG = (6<<3);
273                                 AnEXTEN|=((*tok&7)<<12);
274                                 AnEXTEN|=EXT_D;
275                                 AnEXTEN|=EXT_BS; // Oh look, a data register! Which means that base register is suppressed
276                                 tok++;
277
278                                 // Check for size
279                                 {       // ([bd,An/PC],Xn.W/L...)
280                                         switch ((int)*tok)
281                                         {                                // Index reg size: <empty> | .W | .L 
282                                         case DOTW:
283                                                 tok++;
284                                                 break;
285                                         default:
286                                                 break;
287                                         case DOTL:
288                                                 AnEXTEN |= EXT_L;
289                                                 tok++;
290                                                 break;
291                                         case DOTB:                                      // .B not allowed here...
292                                                 goto badmode;
293                                         }
294                                 }
295
296                                 // Check for scale
297                                 if (*tok=='*')                  // ([bd,An/PC],Xn*...)
298                                 {
299                                         tok++;
300                                         if (*tok==CONST)        // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
301                                                 tok++;
302                                         switch ((int)*tok++)
303                                         {
304                                         case 1:
305                                                 break;
306                                         case 2:
307                                                 AnEXTEN |= EXT_TIMES2;
308                                                 break;
309                                         case 4:
310                                                 AnEXTEN |= EXT_TIMES4;
311                                                 break;
312                                         case 8:
313                                                 AnEXTEN |= EXT_TIMES8;
314                                                 break;
315                                         default:
316                                                 goto badmode;
317                                         }                                       
318                                 }
319                                 if (*tok==']')  // ([bd,Dn]...
320                                 {
321                                         tok++;
322                                         goto IS_SUPPRESSEDn;
323                                 }
324                         }
325                         else if (*tok==']')
326                         {
327                 // PC and Xn is suppressed
328                                 AnREG=6<<3;             // stuff 110 to mode field
329                                 //AnEXTEN|=EXT_BS|EXT_IS;
330                 AnEXTEN |= EXT_BS;
331             }
332             else
333             {
334                 goto badmode;
335             }
336
337                         // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
338                         if (*tok==']')
339                         {                                               //([bd,An/PC],Xn,od)
340                                 // Check for Xn
341                                 tok++;
342                                 if (*tok==')')
343                                 {       //Xn and od are non existent, get out of jail free card
344                                         AMn=MEMPRE;                     // ([bc,An,Xn],od) with no Xn and od
345                                         AnEXTEN|=EXT_IS|EXT_IISPREN;    //Suppress Xn and od
346                                         tok++;
347                                         goto AnOK;
348                                 }
349                                 else if (*tok!=',')
350                                         return error("comma expected after ]");
351                                 else
352                                         tok++;                          // eat the comma
353
354                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
355                                 {
356                                         AnIXREG=((*tok&7)<<12);
357                                         AnEXTEN|=EXT_A;
358                                         tok++;
359                                 }
360                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
361                                 {
362                                         AnEXTEN|=((*tok&7)<<12);
363                                         AnEXTEN|=EXT_D;
364                                         tok++;
365                                 }
366                                 else
367                                 {
368                                         //No index found, suppress it
369                                         AnEXTEN|=EXT_IS;
370                                         tok--;                                                  // Rewind tok to point to the comma
371                                         goto IS_SUPPRESSEDn;                    // https://xkcd.com/292/ - what does he know anyway?
372                                 }
373
374                                 // Check for size
375                                 {       // ([bd,An/PC],Xn.W/L...)
376                                         switch ((int)*tok)
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:                                      // .B not allowed here...
388                                                 goto badmode;
389                                         }
390                                 }
391
392                                 // Check for scale
393                                 if (*tok=='*')                  // ([bd,An/PC],Xn*...)
394                                 {
395                                         tok++;
396                                         if (*tok==CONST)        // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
397                                                 tok++;
398                                         switch ((int)*tok++)
399                                         {
400                                         case 1:
401                                                 break;
402                                         case 2:
403                                                 AnEXTEN |= EXT_TIMES2;
404                                                 break;
405                                         case 4:
406                                                 AnEXTEN |= EXT_TIMES4;
407                                                 break;
408                                         case 8:
409                                                 AnEXTEN |= EXT_TIMES8;
410                                                 break;
411                                         default:
412                                                 goto badmode;
413                                         }                                       
414                                 }
415
416                                 // Check for od
417                                 if (*tok==')')  // ([bd,An/PC],Xn)
418                                 {       //od is non existant, get out of jail free card
419                                         AMn=MEMPOST;            // let's say it's ([bd,An],Xn,od) with od=0 then
420                                         AnEXTEN|=EXT_IISPOSN; // No outer displacement
421                                         tok++;
422                                         goto AnOK;
423                                 }
424                                 else if (*tok!=',')
425                                         return error("comma expected");
426                                 else
427                                         tok++;  // eat the comma
428
429                 CHECKODn:
430                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
431                                         goto badmode;
432                                 if (optim_flags[OPT_BASE_DISP] && AnEXVAL==0)
433                                 {
434                                         // od=0 so optimise it out
435                                         AMn=MEMPOST;             // let's say it's ([bd,An],Xn,od) with od=0 then
436                                         AnEXTEN|=EXT_IISPOSN; // No outer displacement
437                                         tok++;
438                                         goto AnOK;
439                                 }
440                                 // ([bd,An/PC],Xn,od)
441                                 if (*tok == DOTL)
442                                 {
443                                         // expr.L
444                                         AnEXTEN|=EXT_IISPOSL; // Long outer displacement
445                                         AMn = MEMPOST;
446
447                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
448                         // to absolute short
449                         if (optim_flags[OPT_ABS_SHORT] && (AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
450                         {
451                                                 AnEXTEN|=EXT_IISPOSW; // Word outer displacement
452                                                 AMn = MEMPOST;
453                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
454                                         }
455
456                                 }
457                                 else
458                                 {
459                                         // expr[.W]
460                                         AnEXTEN|=EXT_IISPOSW; // Word outer displacement
461                                         AMn = MEMPOST;
462
463                                         // Is .W forced here?
464                                         if (*tok == DOTW)
465                                         {
466                                                 tok++;
467                                         }
468
469                                 }
470
471                                 // Check for final closing parenthesis
472                                 if (*tok==')')
473                                 {
474                                         tok++;
475                                         goto AnOK;
476                                 }
477                                 else
478                                         return error("Closing parenthesis missing on addressing mode");
479
480                                 IS_SUPPRESSEDn:
481
482                                 // Check for od
483                                 if (*tok==')')  // ([bd,An/PC],Xn)
484                                 {       //od is non existant, get out of jail free card
485                                         AMn=MEMPOST;            // let's say it's ([bd,An],Xn,od) with od=0 then
486                                         AnEXTEN|=EXT_IISNOIN; // No outer displacement
487                                         tok++;
488                                         goto AnOK;
489                                 }
490                                 else if (*tok!=',')
491                                         return error("comma expected");
492                                 else
493                                         tok++;  // eat the comma
494
495                 if (*tok != CONST && *tok != SYMBOL)
496                                 //if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
497                                         goto badmode;
498                 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
499                                 if (optim_flags[OPT_BASE_DISP] && AnEXVAL==0)
500                                 {
501                                         // od=0 so optimise it out
502                                         AMn=MEMPOST;             // let's say it's ([bd,An],Xn,od) with od=0 then
503                                         AnEXTEN|=EXT_IISNOIN; // No outer displacement
504                                         tok++;
505                                         goto AnOK;
506                                 }
507                                 // ([bd,An/PC],Xn,od)
508                                 if (*tok == DOTL)
509                                 {
510                                         // expr.L
511                                         tok++;
512                                         AMn = MEMPOST;
513                                         AnEXTEN|=EXT_IISNOIL; // Long outer displacement with IS suppressed
514                                         //goto AnOK;
515
516                                 }
517                                 else
518                                 {
519                                         // expr[.W][]
520                     AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
521                     AMn = MEMPRE;
522                     if (*tok == DOTW)
523                     {
524                         //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
525                                             AMn = MEMPOST;
526                                                 tok++;
527                     }
528
529                                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
530                                         // to absolute short
531                                         else if (optim_flags[OPT_BASE_DISP] && (AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
532                                         {
533                                                 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
534                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
535                                         }
536
537
538                                 }
539
540                                 // Check for final closing parenthesis
541                                 if (*tok==')')
542                                 {
543                                         tok++;
544                                         goto AnOK;
545                                 }
546                                 else
547                                         return error("Closing parenthesis missing on addressing mode");
548
549                         }
550                         else if (*tok==',')
551                         {
552                                 *tok++;                 // ([bd,An,Xn.size*scale],od)
553                                 //Check for Xn
554                                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
555                                 {
556                                         AnEXTEN|=((*tok&7)<<12);
557                                         AnEXTEN|=EXT_A;
558                                         tok++;
559                                 }
560                                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
561                                 {
562                                         AnEXTEN|=((*tok&7)<<12);
563                                         AnEXTEN|=EXT_D;
564                                         tok++;
565                                 }
566
567                                 // Check for size
568                                 { // ([bd,An/PC],Xn.W/L...)
569                                         switch ((int)*tok)
570                                         {                                // Index reg size: <empty> | .W | .L 
571                                         case DOTW:
572                                                 tok++;
573                                                 break;
574                                         default:
575                                                 break;
576                                         case DOTL:
577                                                 tok++;
578                                                 AnEXTEN |= EXT_L;
579                                                 break;
580                                         case DOTB:                                      // .B not allowed here...
581                                                 goto badmode;
582                                         }
583                                         
584                                 }
585                                 
586                                 // Check for scale
587                                 if (*tok=='*')                  // ([bd,An/PC],Xn*...)
588                                 {
589                                         tok++;
590                                         if (*tok==CONST)        // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
591                                                 tok++;
592                                         switch ((int)*tok++)
593                                         {
594                                         case 1:
595                                                 break;
596                                         case 2:
597                                                 AnEXTEN |= EXT_TIMES2;
598                                                 break;
599                                         case 4:
600                                                 AnEXTEN |= EXT_TIMES4;
601                                                 break;
602                                         case 8:
603                                                 AnEXTEN |= EXT_TIMES8;
604                                                 break;
605                                         default:
606                                                 goto badmode;
607                                         }                                       
608                                 }
609
610                                 //Check for ]
611                                 if (*tok!=']')
612                                         return error("Expected closing bracket ]");
613                                 tok++;                  // Eat the bracket
614
615                                 //Check for od
616                                 if (*tok==')')  // ([bd,An/PC,Xn]...
617                                 {       //od is non existant, get out of jail free card
618                                         //AnEXVAL=0;            // zero outer displacement
619                                         AMn=MEMPRE;                     // let's say it's ([bd,An,Xn],od) with od suppressed then
620                                         AnEXTEN|=EXT_IISPREN; // No outer displacement
621                                         tok++;
622                                         goto AnOK;
623                                 }
624                                 else if (*tok++!=',')
625                                         return error("comma expected after ]");
626                 WARNING(Put symbol and constant checks here!)
627                                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
628                                         goto badmode;
629                                 if (optim_flags[OPT_BASE_DISP] && AnEXVAL==0)
630                                 {
631                                         // od=0 so optimise it out
632                                         AMn=MEMPRE;              // let's say it's ([bd,An],Xn,od) with od=0 then
633                                         AnEXTEN|=EXT_IISPRE0; // No outer displacement
634                                         tok++;
635                                         goto AnOK;
636                                 }
637                                 // ([bd,An/PC,Xn],od)
638                                 if (*tok == DOTL)
639                                 {
640                                         // expr.L
641                                         AMn = MEMPRE;
642                                         tok++;
643
644                                         AnEXTEN|=EXT_IISPREL;
645
646                                 }
647                                 else
648                                 {
649                                         // expr.[W] 
650                                         //tok++;
651
652                                         AnEXTEN|=EXT_IISPREW;
653                                         AMn = MEMPRE;
654
655                     // Is .W forced here?
656                                         if (*tok == DOTW)
657                                         {
658                                                 tok++;
659                                         }
660
661                                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
662                                         // to absolute short
663                                         else if (optim_flags[OPT_BASE_DISP] && (AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
664                                         {
665                                                 AnEXTEN|=EXT_IISPREW;
666                                                 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
667                                         }
668                                 }
669
670                                 // Check for final closing parenthesis
671                                 if (*tok==')')
672                                 {
673                                         tok++;
674                                         goto AnOK;
675                                 }
676                                 else
677                                         return error("Closing parenthesis missing on addressing mode");
678                         }
679                         else
680                                 goto badmode;
681
682                         //goto unmode;
683                 }
684                 else
685                 {                                              // (expr... 
686                         if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
687                                 return ERROR;
688
689                         // It could be that this is really just an expression prefixing a
690                         // register as a displacement...
691                         if (*tok == ')')
692                         {
693                                 tok++;
694                                 goto CHK_FOR_DISPn;
695                         }
696
697                         // Otherwise, check for PC & etc displacements...
698                         if (*tok++ != ',')
699                                 goto badmode;
700
701                         if ((*tok >= KW_A0) && (*tok <= KW_A7))
702                         {
703                                 AnREG = *tok & 7;
704                                 tok++;
705
706                                 if (*tok == ',')
707                                 {
708                                         AMn = AINDEXED;
709                                         goto AMn_IXN;
710                                 }
711                                 else if (*tok == ')')
712                         {
713                                 AMn = ADISP;
714                                 tok++;
715                                 goto AnOK;
716                         }
717                                 else
718                                         goto badmode;
719                         }
720                         else if (*tok == KW_PC)
721                         {
722                                 if (*++tok == ',')
723                                 {                             // expr(PC,Xn...)
724                                         AMn = PCINDEXED;
725                                         goto AMn_IXN;
726                                 }
727                                 else if (*tok == ')')
728                                 {
729                                         AMn = PCDISP;                                // expr(PC) 
730                                         tok++;
731                                         goto AnOK;
732                                 }
733                                 else
734                                         goto badmode;
735                         }
736                         else
737                                 goto badmode;
738                 }
739         }
740         else if (*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')')
741         {
742                 AMn = APREDEC;
743                 AnREG = tok[2] & 7;
744                 tok += 4;
745         }
746         else if (*tok == KW_CCR)
747         {
748                 AMn = AM_CCR;
749                 tok++;
750                 goto AnOK;
751         }
752         else if (*tok == KW_SR)
753         {
754                 AMn = AM_SR;
755                 tok++;
756                 goto AnOK;
757         }
758         else if (*tok == KW_USP)
759         {
760                 AMn = AM_USP;
761                 tok++;
762                 AnREG=2;        //Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
763                 goto AnOK;
764         }
765         else if ((*tok>=KW_IC40) && (*tok<=KW_BC40))
766         {
767                 AMn=CACHES;
768                 AnREG=*tok++-KW_IC40;
769
770                 // After a cache keyword only a comma or EOL is allowed
771                 if ((*tok!=',') && (*tok!=EOL))
772                         return ERROR;
773                 goto AnOK;
774         }
775         else if ((*tok>=KW_SFC) && (*tok<=KW_CRP))
776         {
777                 AMn=CREG;
778                 AnREG=(*tok++)-KW_SFC;
779                 goto AnOK;
780         }
781         else if ((*tok>=KW_FP0) && (*tok<=KW_FP7))
782         {
783                 AMn=FREG;
784                 AnREG=(*tok++&7);
785         }
786         else if ((*tok>=KW_FPIAR) && (*tok<=KW_FPCR))
787         {
788                 AMn=FPSCR;
789                 AnREG=(1<<((*tok++)-KW_FPIAR+10));
790         }
791         // expr
792         // expr.w
793         // expr.l
794         // d16(An)
795         // d8(An,Xn[.siz])
796         // d16(PC)
797         // d8(PC,Xn[.siz])
798         else
799         {
800                 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
801                         return ERROR;
802
803 CHK_FOR_DISPn:
804                 if (*tok == DOTW)
805                 {
806                         // expr.W 
807                         tok++;
808                         AMn = ABSW;
809
810                         if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL < 0x10000))
811                                 AnEXVAL = (int32_t)(int16_t)AnEXVAL;  // Sign extend value
812
813                         goto AnOK;
814                 }
815                 else if (*tok != '(')
816                 {
817                         // expr[.L]
818                         AMn = ABSL;
819
820                         // Defined, absolute values from $FFFF8000..$00007FFF get optimized
821                         // to absolute short
822                         if (optim_flags[OPT_ABS_SHORT] && (AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
823                         {
824                                 AMn = ABSW;
825
826                                 if (sbra_flag)
827                                         warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
828                         }
829
830                         // Is .L forced here?
831                         if (*tok == DOTL)
832                         {
833                                 tok++;
834                                 AMn = ABSL;
835                         }
836
837                         goto AnOK;
838                 }
839
840                 tok++;
841
842                 if ((*tok >= KW_A0) && (*tok <= KW_A7))
843                 {
844                         AnREG = *tok++ & 7;
845
846                         if (*tok == ')')
847                         {
848                                 AMn = ADISP;
849                                 tok++;
850                                 goto AnOK;
851                         }
852
853                         AMn = AINDEXED;
854                         goto AMn_IXN;
855                 }
856                 else if (*tok == KW_PC)
857                 {
858                         if (*++tok == ')')
859                         {
860                                 AMn = PCDISP;
861                                 tok++;
862                                 goto AnOK;
863                         }
864
865                         AMn = PCINDEXED;
866                         goto AMn_IXN;
867                 }
868                 goto badmode;
869         }
870
871         // Addressing mode OK
872
873         AnOK:
874         ;
875 }
876
877 // Clean up dirty little macros
878 #undef AnOK
879 #undef AMn
880 #undef AnREG
881 #undef AnIXREG
882 #undef AnIXSIZ
883 #undef AnEXPR
884 #undef AnEXVAL
885 #undef AnEXATTR
886 #undef AnOEXPR
887 #undef AnOEXVAL
888 #undef AnOEXATTR
889 #undef AnESYM
890 #undef AMn_IX0
891 #undef AMn_IXN
892 #undef CHK_FOR_DISPn
893 #undef AnBEXPR
894 #undef AnBEXVAL
895 #undef AnBEXATTR
896 #undef AnBZISE
897 #undef AnEXTEN
898 #undef AMn_030
899 #undef IS_SUPPRESSEDn
900 #undef CHECKODn