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