Mercurial > hg-old > index.cgi
comparison src/insn_indexed.c @ 81:b6b1e79cc277
Moved indexed modes to new expression framework
author | lost |
---|---|
date | Sat, 10 Jan 2009 19:05:15 +0000 |
parents | 538e15927776 |
children | e12edcfbebd5 |
comparison
equal
deleted
inserted
replaced
80:8929e1ee99cf | 81:b6b1e79cc277 |
---|---|
61 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0}, | 61 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0}, |
62 | 62 |
63 { "", -1 } | 63 { "", -1 } |
64 }; | 64 }; |
65 char stbuf[25]; | 65 char stbuf[25]; |
66 int i; | 66 int i, j, rn; |
67 int f8 = 0, f16 = 0; | 67 int f8 = 0, f16 = 0, f0 = 0; |
68 int rn; | 68 int r, v; |
69 int indir = 0; | 69 int indir = 0; |
70 int rval; | 70 |
71 int f0 = 0; | 71 // initialize output bytes |
72 const char *p2; | |
73 lwasm_expr_stack_t *s; | |
74 | |
75 *b1 = *b2 = *b3 = -1; | 72 *b1 = *b2 = *b3 = -1; |
76 | 73 |
74 // fetch out operand for lookup | |
77 for (i = 0; i < 24; i++) | 75 for (i = 0; i < 24; i++) |
78 { | 76 { |
79 if (*((*p) + i) && !isspace(*((*p) + i))) | 77 if (*((*p) + i) && !isspace(*((*p) + i))) |
80 stbuf[i] = *((*p) + i); | 78 stbuf[i] = *((*p) + i); |
81 else | 79 else |
82 break; | 80 break; |
83 } | 81 } |
84 stbuf[i] = '\0'; | 82 stbuf[i] = '\0'; |
83 | |
84 // now look up operand in "simple" table | |
85 if (!*((*p) + i) || isspace(*((*p) + i))) | 85 if (!*((*p) + i) || isspace(*((*p) + i))) |
86 { | 86 { |
87 int j; | |
88 // do simple lookup | 87 // do simple lookup |
89 for (j = 0; simpleindex[j].opstr[0]; j++) | 88 for (j = 0; simpleindex[j].opstr[0]; j++) |
90 { | 89 { |
91 if (!strcasecmp(stbuf, simpleindex[j].opstr)) | 90 if (!strcasecmp(stbuf, simpleindex[j].opstr)) |
92 break; | 91 break; |
96 *b1 = simpleindex[j].pb; | 95 *b1 = simpleindex[j].pb; |
97 (*p) += i; | 96 (*p) += i; |
98 return; | 97 return; |
99 } | 98 } |
100 } | 99 } |
101 | 100 |
102 // now we have the hard ones to work out here | 101 // now do the "hard" ones |
103 | 102 |
104 // if we've previously forced the sizes, make a note of it | 103 // is it indirect? |
104 if (**p == '[') | |
105 { | |
106 indir = 1; | |
107 (*p)++; | |
108 } | |
109 | |
110 // look for a "," - all indexed modes have a "," except extended indir | |
111 rn = 0; | |
112 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++) | |
113 { | |
114 if ((*p)[i] == ',') | |
115 { | |
116 rn = 1; | |
117 break; | |
118 } | |
119 } | |
120 | |
121 // if no "," and indirect, do extended indir | |
122 if (!rn && indir) | |
123 { | |
124 // extended indir | |
125 *b1 = 0x9f; | |
126 *b2 = 0; | |
127 *b3 = 0; | |
128 | |
129 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); | |
130 if (r < 0) | |
131 { | |
132 return; | |
133 } | |
134 | |
135 if (**p != ']') | |
136 { | |
137 register_error(as, l, 1, "Bad operand"); | |
138 return; | |
139 } | |
140 | |
141 (*p)++; | |
142 | |
143 if (r == 1 && as -> passnum == 2) | |
144 { | |
145 l -> relocoff = as -> addr - l -> codeaddr + 1; | |
146 } | |
147 | |
148 *b2 = (v >> 8) & 0xff; | |
149 *b3 = v & 0xff; | |
150 return; | |
151 } | |
152 | |
153 // if we've previously forced the offset size, make a note of it | |
105 if (l -> fsize == 1) | 154 if (l -> fsize == 1) |
106 f8 = 1; | 155 f8 = 1; |
107 else if (l -> fsize == 2) | 156 else if (l -> fsize == 2) |
108 f16 = 1; | 157 f16 = 1; |
109 | |
110 if (**p == '[') | |
111 { | |
112 indir = 1; | |
113 (*p)++; | |
114 } | |
115 | |
116 rn = 0; | |
117 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++) | |
118 { | |
119 if ((*p)[i] == ',') | |
120 { | |
121 rn = 1; | |
122 break; | |
123 } | |
124 } | |
125 | |
126 if (!rn && indir) | |
127 { | |
128 // extended indir | |
129 *b1 = 0x9f; | |
130 *b2 = 0; | |
131 *b3 = 0; | |
132 s = lwasm_evaluate_expr(as, l, *p, &p2); | |
133 if (!s) | |
134 { | |
135 register_error(as, l, 1, "Bad expression"); | |
136 return; | |
137 } | |
138 *p = p2; | |
139 if (**p != ']') | |
140 { | |
141 register_error(as, l, 1, "Bad operand"); | |
142 return; | |
143 } | |
144 (*p)++; | |
145 if (!lwasm_expr_is_constant(s)) | |
146 { | |
147 register_error(as, l, 2, "Incomplete reference"); | |
148 } | |
149 rn = lwasm_expr_get_value(s); | |
150 lwasm_expr_stack_free(s); | |
151 *b2 = (rn >> 8) & 0xff; | |
152 *b3 = rn & 0xff; | |
153 return; | |
154 } | |
155 | 158 |
156 if (**p == '<') | 159 if (**p == '<') |
157 { | 160 { |
158 f8 = 1; | 161 f8 = 1; |
159 (*p)++; | 162 (*p)++; |
168 { | 171 { |
169 f0 = 1; | 172 f0 = 1; |
170 } | 173 } |
171 | 174 |
172 // now we have to evaluate the expression | 175 // now we have to evaluate the expression |
173 s = lwasm_evaluate_expr(as, l, *p, &p2); | 176 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); |
174 *p = p2; | 177 if (r < 0) |
175 if (!s) | 178 { |
176 { | 179 return; |
177 register_error(as, l, 1, "Bad expression"); | 180 } |
178 return; | 181 if (f8 && r != 0) |
179 } | 182 { |
180 if (!lwasm_expr_is_constant(s)) | 183 register_error(as, l, 2, "Illegal external or inter-section reference"); |
181 { | 184 r = 0; |
182 register_error(as, l, 2, "Incomplete reference"); | 185 v = 0; |
183 if (!f8 && !f0) | 186 } |
184 { | 187 |
185 f16 = 1; | |
186 l -> fsize = 2; | |
187 } | |
188 } | |
189 rval = lwasm_expr_get_value(s); | |
190 lwasm_expr_stack_free(s); | |
191 | |
192 // now look for a comma; if not present, explode | 188 // now look for a comma; if not present, explode |
193 if (*(*p)++ != ',') | 189 if (*(*p)++ != ',') |
194 { | 190 { |
195 // syntax error; force 0 bit | 191 // syntax error; force 0 bit |
196 *b1 = 00; | 192 *b1 = 00; |
193 l -> fsize = 0; | |
197 return; | 194 return; |
198 } | 195 } |
199 | 196 |
200 // now get the register | 197 // now get the register |
201 rn = lwasm_lookupreg3(regs, p); | 198 rn = lwasm_lookupreg3(regs, p); |
202 if (rn < 0) | 199 if (rn < 0) |
203 goto reterr; | 200 { |
204 | 201 *b1 = 0; |
202 l -> fsize = 0; | |
203 register_error(as, l, 1, "Bad register"); | |
204 return; | |
205 } | |
206 | |
205 if (indir) | 207 if (indir) |
206 { | 208 { |
207 if (**p != ']') | 209 if (**p != ']') |
208 goto reterr; | 210 { |
211 register_error(as, l, 1, "Bad operand"); | |
212 l -> fsize = 0; | |
213 *b1 = 0; | |
214 return; | |
215 } | |
209 else | 216 else |
210 (*p)++; | 217 (*p)++; |
211 } | 218 } |
212 | 219 |
213 // nnnn,W is only 16 bit | 220 // incomplete reference on pass 1 forces 16 bit |
221 if (r == 1 && as -> passnum == 1) | |
222 { | |
223 f16 = 1; | |
224 l -> fsize = 2; | |
225 } | |
226 | |
227 // incomplete reference on pass 2 needs relocoff set | |
228 if (r == 1 && as -> passnum == 2) | |
229 { | |
230 l -> relocoff = as -> addr - l -> codeaddr + 1; | |
231 } | |
232 | |
233 // nnnn,W is only 16 bit (or 0 bit) | |
214 if (rn == 4) | 234 if (rn == 4) |
215 { | 235 { |
216 if (f8) | 236 if (f8) |
217 goto reterr; | 237 { |
218 if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && rval == 0) | 238 register_error(as, l, 1, "n,W cannot be 8 bit"); |
239 l -> fsize = 0; | |
240 *b1 = 0; | |
241 return; | |
242 } | |
243 // note: set f16 above for incomplete references | |
244 // also set reloc offset | |
245 if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && v == 0) | |
219 { | 246 { |
220 if (indir) | 247 if (indir) |
221 *b1 = 0x90; | 248 *b1 = 0x90; |
222 else | 249 else |
223 *b1 = 0x8f; | 250 *b1 = 0x8f; |
224 return; | 251 return; |
225 } | 252 } |
253 | |
226 if (indir) | 254 if (indir) |
227 *b1 = 0xb0; | 255 *b1 = 0xb0; |
228 else | 256 else |
229 *b1 = 0xcf; | 257 *b1 = 0xcf; |
230 *b2 = (rval >> 8) & 0xff; | 258 *b2 = (v >> 8) & 0xff; |
231 *b3 = rval & 0xff; | 259 *b3 = v & 0xff; |
232 return; | 260 return; |
233 } | 261 } |
234 | 262 |
263 // set indir to correct bit value | |
235 if (indir) indir = 0x10; | 264 if (indir) indir = 0x10; |
236 | 265 |
237 // PCR? redo v1, v2 relative to current address | 266 // PCR? then we have PC relative addressing (like B??, LB??) |
238 if (rn == 5) | 267 if (rn == 5) |
239 { | 268 { |
240 rval -= as -> addr; | 269 // FIXME: handle external references sensibly |
270 v -= as -> addr; | |
241 | 271 |
242 // we have a slight problem here | 272 // we have a slight problem here |
243 // PCR based on current insn loc is really | 273 // PCR based on current insn loc is really |
244 // -125 <= offset <= +130 (8 bit offset) | 274 // -125 <= offset <= +130 (8 bit offset) |
245 // NOTE: when we are called, we already have the opcode emitted | 275 // NOTE: when we are called, we already have the opcode emitted |
246 // so we only need to worry about the size of the operand | 276 // so we only need to worry about the size of the operand |
247 // hence the 2 and 3 magic numbers below instead of 3 and 4 | 277 // hence the 2 and 3 magic numbers below instead of 3 and 4 |
248 // (and that also avoids errors with two byte opcodes, etc) | 278 // (and that also avoids errors with two byte opcodes, etc) |
249 if (f8 || (!f16 && rval >= -125 && rval <= 130)) | 279 if (f8 || (!f16 && v >= -125 && v <= 130)) |
250 { | 280 { |
251 *b1 = indir | 0x8C; | 281 *b1 = indir | 0x8C; |
252 rval -= 2; | 282 v -= 2; |
253 if (rval < -128 || rval > 127) | 283 if (v < -128 || v > 127) |
254 register_error(as, l, 2, "Byte overflow"); | 284 register_error(as, l, 2, "Byte overflow"); |
255 *b2 = rval & 0xff; | 285 *b2 = v & 0xff; |
256 return; | 286 return; |
257 } | 287 } |
258 | 288 |
259 // anything else is 16 bit offset | 289 // anything else is 16 bit offset |
260 // need 16 bit | 290 // need 16 bit |
261 *b1 = indir | 0x8D; | 291 *b1 = indir | 0x8D; |
262 rval -= 3; | 292 v -= 3; |
263 *b2 = (rval >> 8) & 0xff; | 293 *b2 = (v >> 8) & 0xff; |
264 *b3 = rval & 0xff; | 294 *b3 = v & 0xff; |
265 return; | 295 return; |
266 } | 296 } |
267 | 297 |
268 // constant offset from PC | 298 // constant offset from PC (using PC as regular register :) ) |
299 // FIXME: handle external references intelligently | |
269 if (rn == 6) | 300 if (rn == 6) |
270 { | 301 { |
271 if (f8 || (!f16 && rval >= -128 && rval <= 127)) | 302 if (f8 || (!f16 && v >= -128 && v <= 127)) |
272 { | 303 { |
273 *b1 = indir | 0x8C; | 304 *b1 = indir | 0x8C; |
274 if (rval < -128 || rval > 127) | 305 if (v < -128 || v > 127) |
275 register_error(as, l, 2, "Byte overflow"); | 306 register_error(as, l, 2, "Byte overflow"); |
276 *b2 = rval & 0xff; | 307 *b2 = v & 0xff; |
277 return; | 308 return; |
278 } | 309 } |
279 | 310 |
280 // everything else must be 16 bit | 311 // everything else must be 16 bit |
281 // need 16 bit | 312 // need 16 bit |
282 *b1 = indir | 0x8D; | 313 *b1 = indir | 0x8D; |
283 *b2 = (rval >> 8) & 0xff; | 314 *b2 = (v >> 8) & 0xff; |
284 *b3 = rval & 0xff; | 315 *b3 = v & 0xff; |
285 return; | 316 return; |
286 } | 317 } |
287 | 318 |
288 // we only have to deal with x,y,u,s here | 319 // we only have to deal with x,y,u,s here |
289 if (!f8 && !f16 && rval >= -16 && rval <= 15) | 320 if (!f8 && !f16 && v >= -16 && v <= 15) |
290 { | 321 { |
291 if (rval == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) | 322 // zero offset going to ,R? |
323 if (v == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) | |
292 { | 324 { |
293 *b1 = rn << 5 | indir | 0x80 | 0x04; | 325 *b1 = rn << 5 | indir | 0x80 | 0x04; |
294 return; | 326 return; |
295 } | 327 } |
296 // we pick the smallest value here | 328 |
329 // no 5 bit on indirect | |
297 if (indir) | 330 if (indir) |
298 { | 331 { |
299 f8 = 1; | 332 f8 = 1; |
333 l -> fsize = 1; | |
300 goto no5bit; | 334 goto no5bit; |
301 } | 335 } |
302 *b1 = rn << 5 | (rval & 0x1F); | 336 |
303 return; | 337 // 5 bit addressing |
304 } | 338 *b1 = rn << 5 | (v & 0x1F); |
339 return; | |
340 } | |
341 | |
305 no5bit: | 342 no5bit: |
306 if (f16 || (!f8 && (rval < -128 || rval > 127))) | 343 if (f16 || (!f8 && (v < -128 || v > 127))) |
307 { | 344 { |
308 // must be a 16 bit offset here | 345 // must be a 16 bit offset here |
309 *b1 = rn << 5 | indir | 0x80 | 0x09; | 346 *b1 = rn << 5 | indir | 0x80 | 0x09; |
310 *b2 = (rval >> 8) & 0xff; | 347 *b2 = (v >> 8) & 0xff; |
311 *b3 = rval & 0xff; | 348 *b3 = v & 0xff; |
312 return; | 349 return; |
313 } | 350 } |
314 | 351 |
315 // if we're here, we have an 8 bit offset | 352 // if we're here, we have an 8 bit offset |
353 // note: cannot get here if incomplete reference detected above | |
316 *b1 = rn << 5 | indir | 0x80 | 0x08; | 354 *b1 = rn << 5 | indir | 0x80 | 0x08; |
317 if (rval < -128 || rval > 127) | 355 if (v < -128 || v > 127) |
318 register_error(as, l, 2, "Byte overflow"); | 356 register_error(as, l, 2, "Byte overflow"); |
319 *b2 = rval & 0xff; | 357 *b2 = v & 0xff; |
320 return; | |
321 reterr: | |
322 *b1 = 0; | |
323 return; | 358 return; |
324 } | 359 } |
325 | 360 |
326 OPFUNC(insn_indexed) | 361 OPFUNC(insn_indexed) |
327 { | 362 { |