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