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