]> Shamusworld >> Repos - rmac/blob - parmode.h
Fix problem in tokenizer that caused legit code to make assembler barf.
[rmac] / parmode.h
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011 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 different var names
10 {
11    // Dn
12    // An
13    // # expression
14    if((*tok >= KW_D0) && (*tok <= KW_D7)) {
15       AMn = DREG;
16       AnREG = *tok++ & 7;
17    } else if((*tok >= KW_A0) && (*tok <= KW_A7)) {
18       AMn = AREG;
19       AnREG = *tok++ & 7;
20    } else if(*tok == '#') {
21       ++tok;
22       if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
23          return(ERROR);
24       AMn = IMMED;
25    }
26    // (An)
27    // (An)+
28    // (An,Xn[.siz][*scale])
29    // (PC,Xn[.siz][*scale])
30    // (d16,An)
31    // (d8,An,Xn[.siz][*scale])
32    // (d16,PC)
33    // (d8,PC,Xn[.siz][*scale])
34    // ([bd,An],Xn,od)
35    // ([bd,An,Xn],od)
36    // ([bd,PC],Xn,od)
37    // ([bd,PC,Xn],od)
38    else if(*tok == '(') {
39       ++tok;
40       if((*tok >= KW_A0) && (*tok <= KW_A7)) {
41          AnREG = *tok++ & 7;
42          if(*tok == ')') {
43             ++tok;
44             if(*tok == '+') {
45                ++tok;
46                AMn = APOSTINC;
47             } else AMn = AIND;
48             goto AnOK;
49          }
50          AMn = AINDEXED;
51          goto AMn_IX0;                                      // Handle ",Xn[.siz][*scale])"
52       } else if(*tok == KW_PC) {                            // (PC,Xn[.siz][*scale]) 
53          ++tok;
54          AMn = PCINDEXED;
55
56          // Common index handler; enter here with `tok' pointing at the comma.
57
58          AMn_IX0:                                           // Handle indexed with missing expr
59
60          AnEXVAL = 0;
61          AnEXATTR = ABS | DEFINED;
62
63          AMn_IXN:                                           // Handle any indexed (tok -> a comma)
64
65          if(*tok++ != ',')
66             goto badmode;
67          if(*tok < KW_D0 || *tok > KW_A7)
68             goto badmode;
69          AnIXREG = *tok++ & 15;
70
71          switch((int)*tok)      {                                // Index reg size: <empty> | .W | .L 
72             case DOTW:
73                ++tok;
74             default:
75                AnIXSIZ = 0;
76                break;
77             case DOTL:
78                AnIXSIZ = 0x0800;
79                ++tok;
80                break;
81             case DOTB:                                      // .B not allowed here...
82                goto badmode;
83          }
84
85          if(*tok == '*') {                                  // scale: *1, *2, *4, *8 
86             ++tok;
87             if(*tok++ != CONST || *tok > 8)
88                goto badmode;
89
90             switch((int)*tok++) {
91                case 1:
92                   break;
93                case 2:
94                   AnIXSIZ |= TIMES2;
95                   break;
96                case 4:
97                   AnIXSIZ |= TIMES4;
98                   break;
99                case 8:
100                   AnIXSIZ |= TIMES8;
101                   break;
102                default:
103                   goto badmode;
104             }
105          }
106
107          if(*tok++ != ')')                                  // final ")" 
108             goto badmode;
109          goto AnOK;
110       } else if(*tok == '[') {                              // ([... 
111          goto unmode;
112       } else {                                              // (expr... 
113          if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
114             return ERROR;
115          if(*tok++ != ',')
116             goto badmode;
117
118          if((*tok >= KW_A0) && (*tok <= KW_A7)) {
119             AnREG = *tok & 7;
120             ++tok;
121             if(*tok == ',') {
122                AMn = AINDEXED;
123                goto AMn_IXN;
124             } else if(*tok == ')') {
125                AMn = ADISP;
126                ++tok;
127                goto AnOK;
128             } else goto badmode;
129          } else if(*tok == KW_PC) {
130             if(*++tok == ',') {                             // expr(PC,Xn...)
131                AMn = PCINDEXED;
132                goto AMn_IXN;
133             } else if(*tok == ')') {
134                AMn = PCDISP;                                // expr(PC) 
135                ++tok;
136                goto AnOK;
137             } else goto badmode;
138          } else goto badmode;
139       }
140    } else if(*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')') {
141       AMn = APREDEC;
142       AnREG = tok[2] & 7;
143       tok += 4;
144    } else if(*tok == KW_CCR) {
145       AMn = AM_CCR;
146       ++tok;
147       goto AnOK;
148    } else if(*tok == KW_SR) {
149       AMn = AM_SR;
150       ++tok;
151       goto AnOK;
152    } else if(*tok == KW_USP) {
153       AMn = AM_USP;
154       ++tok;
155       goto AnOK;
156    }
157    // expr
158    // expr.w
159    // expr.l
160    // d16(An)
161    // d8(An,Xn[.siz])
162    // d16(PC)
163    // d8(PC,Xn[.siz])
164    else {
165       if(expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
166          return ERROR;
167
168       if(*tok == DOTW) {                                    // expr.W 
169          ++tok;
170          AMn = ABSW;
171          goto AnOK;
172       } else if(*tok != '(') {                              // expr[.L]
173          AMn = ABSL;
174          // Defined, absolute values from $FFFF8000..$00007FFF get optimized to absolute short
175          if((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
176             AMn = ABSW;
177
178          if(*tok == DOTL) {                                 // force .L 
179             ++tok;
180             AMn = ABSL;
181          }
182          goto AnOK;
183       }
184
185       ++tok;
186       if((*tok >= KW_A0) && (*tok <= KW_A7)) {
187          AnREG = *tok++ & 7;
188          if(*tok == ')') {
189             AMn = ADISP;
190             ++tok;
191             goto AnOK;
192          }
193          AMn = AINDEXED;
194          goto AMn_IXN;
195       } else if(*tok == KW_PC) {
196          if(*++tok == ')') {
197             AMn = PCDISP;
198             ++tok;
199             goto AnOK;
200          }
201          AMn = PCINDEXED;
202          goto AMn_IXN;
203       }
204       goto badmode;
205    }
206
207    // Addressing mode OK
208
209    AnOK:
210    ;
211 }
212
213 // Cleanup dirty little macros
214 #undef AnOK
215 #undef AMn
216 #undef AnREG
217 #undef AnIXREG
218 #undef AnIXSIZ
219 #undef AnEXPR
220 #undef AnEXVAL
221 #undef AnEXATTR
222 #undef AnOEXPR
223 #undef AnOEXVAL
224 #undef AnOEXATTR
225 #undef AnESYM
226 #undef AMn_IX0
227 #undef AMn_IXN