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