Mercurial > hg-old > index.cgi
annotate lwasm/insn_gen.c @ 426:652eee8f0c82
Fixed lw_expr_destroy() to not crash on NULL
author | lost@l-w.ca |
---|---|
date | Sun, 19 Sep 2010 10:40:37 -0600 |
parents | 848d3cca8078 |
children | b8549694b4c9 |
rev | line source |
---|---|
339 | 1 /* |
2 insn_gen.c, Copyright © 2009 William Astle | |
3 | |
4 This file is part of LWASM. | |
5 | |
6 LWASM is free software: you can redistribute it and/or modify it under the | |
7 terms of the GNU General Public License as published by the Free Software | |
8 Foundation, either version 3 of the License, or (at your option) any later | |
9 version. | |
10 | |
11 This program is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 more details. | |
15 | |
16 You should have received a copy of the GNU General Public License along with | |
17 this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 Contains code for parsing general addressing modes (IMM+DIR+EXT+IND) | |
20 */ | |
21 | |
22 #include <config.h> | |
23 | |
24 #include <ctype.h> | |
25 #include <stdlib.h> | |
26 | |
361 | 27 #include <lw_expr.h> |
28 | |
339 | 29 #include "lwasm.h" |
30 #include "instab.h" | |
31 | |
361 | 32 extern void insn_indexed_parse_aux(asmstate_t *as, line_t *l, char **p); |
382 | 33 extern void insn_indexed_resolve_aux(asmstate_t *as, line_t *l, int force, int elen); |
361 | 34 extern void insn_indexed_emit_aux(asmstate_t *as, line_t *l); |
339 | 35 |
36 // "extra" is required due to the way OIM, EIM, TIM, and AIM work | |
361 | 37 void insn_parse_gen_aux(asmstate_t *as, line_t *l, char **p) |
339 | 38 { |
39 const char *optr2; | |
40 int v1, tv, rval; | |
361 | 41 lw_expr_t *s; |
339 | 42 |
361 | 43 optr2 = *p; |
339 | 44 while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++ |
45 /* do nothing */ ; | |
46 | |
361 | 47 if (*optr2 == ',' || **p == '[') |
339 | 48 { |
361 | 49 l -> lint = -1; |
50 l -> lint2 = 1; | |
51 insn_parse_indexed_aux(as, l, p); | |
52 goto out; | |
53 } | |
339 | 54 |
361 | 55 if (**p == '<') |
56 { | |
57 (*p)++; | |
58 l -> lint2 = 0; | |
59 } | |
60 | |
61 // for compatibility with asxxxx | |
62 // * followed by a digit, alpha, or _, or ., or ?, or another * is "f8" | |
63 else if (**p == '*') | |
64 { | |
65 tv = *(*p + 1); | |
66 if (isdigit(tv) || isalpha(tv) || tv == '_' || tv == '.' || tv == '?' || tv == '@' || tv == '*' || tv == '+' || tv == '-') | |
339 | 67 { |
361 | 68 l -> lint2 = 0; |
69 (*p)++; | |
339 | 70 } |
361 | 71 } |
72 else if (**p == '>') | |
73 { | |
74 (*p)++; | |
75 l -> lint2 = 2; | |
76 } | |
77 else | |
78 { | |
79 l -> lint2 = -1; | |
80 } | |
81 | |
82 s = lwasm_parse_expr(as, p); | |
83 if (!s) | |
84 { | |
85 lwasm_register_error(as, l, "Bad operand"); | |
86 return; | |
87 } | |
88 | |
89 lwasm_save_expr(l, 0, s); | |
90 | |
91 if (as -> output_format == OUTPUT_OBJ && l -> lint2 == -1) | |
92 { | |
93 l -> lint2 = 2; | |
94 goto out; | |
95 } | |
96 | |
383
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
382
diff
changeset
|
97 if (l -> lint2 != -1) |
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
382
diff
changeset
|
98 goto out; |
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
382
diff
changeset
|
99 |
361 | 100 // if we have a constant now, figure out dp vs nondp |
101 if (lw_expr_istype(s, lw_expr_type_int)) | |
102 { | |
103 v1 = lw_expr_intval(s); | |
104 if (((v1 >> 8) & 0xff) == (l -> dpval & 0xff)) | |
339 | 105 { |
361 | 106 l -> lint2 = 0; |
107 goto out; | |
339 | 108 } |
361 | 109 l -> lint2 = 2; |
110 } | |
111 | |
112 out: | |
113 if (l -> lint2 != -1) | |
114 { | |
115 if (l -> lint2 == 0) | |
116 { | |
117 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
118 } | |
119 else if (l -> lint2 == 2) | |
120 { | |
121 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
122 } | |
123 else if (l -> lint2 == 1 && l -> lint != -1) | |
339 | 124 { |
361 | 125 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; |
339 | 126 } |
361 | 127 } |
128 } | |
339 | 129 |
382 | 130 void insn_resolve_gen_aux(asmstate_t *as, line_t *l, int force, int elen) |
361 | 131 { |
132 lw_expr_t *e; | |
133 | |
134 if (l -> lint2 == 1) | |
135 { | |
136 // indexed | |
382 | 137 insn_resolve_indexed_aux(as, l, force, elen); |
361 | 138 goto out; |
139 } | |
140 | |
141 if (l -> lint2 != -1) | |
142 return; | |
143 | |
144 e = lwasm_fetch_expr(l, 0); | |
145 if (lw_expr_istype(e, lw_expr_type_int)) | |
146 { | |
147 int v; | |
339 | 148 |
361 | 149 v = lw_expr_intval(e); |
150 | |
151 if (((v >> 8) & 0xff) == (l -> dpval & 0xff)) | |
339 | 152 { |
361 | 153 l -> lint2 = 0; |
154 goto out; | |
339 | 155 } |
361 | 156 l -> lint2 = 2; |
157 goto out; | |
158 } | |
159 | |
160 if (force) | |
161 { | |
162 l -> lint2 = 2; | |
163 } | |
164 | |
165 out: | |
166 if (l -> lint2 != -1) | |
167 { | |
168 if (l -> lint2 == 0) | |
169 { | |
170 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
171 } | |
172 else if (l -> lint2 == 2) | |
339 | 173 { |
361 | 174 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; |
339 | 175 } |
361 | 176 else if (l -> lint2 == 1 && l -> lint != -1) |
177 { | |
178 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
179 } | |
180 } | |
181 } | |
339 | 182 |
362 | 183 void insn_emit_gen_aux(asmstate_t *as, line_t *l, int extra) |
361 | 184 { |
185 lw_expr_t e; | |
186 | |
187 e = lwasm_fetch_expr(l, 0); | |
188 lwasm_emitop(l, instab[l -> insn].ops[l -> lint2]); | |
362 | 189 |
190 if (extra != -1) | |
191 lwasm_emit(l, extra); | |
192 | |
382 | 193 if (l -> lint2 == 1) |
361 | 194 { |
195 lwasm_emit(l, l -> pb); | |
382 | 196 if (l -> lint > 0) |
197 lwasm_emitexpr(l, e, l -> lint); | |
361 | 198 return; |
199 } | |
200 | |
201 if (l -> lint2 == 2) | |
202 lwasm_emitexpr(l, e, 2); | |
203 else | |
204 lwasm_emitexpr(l, e, 1); | |
339 | 205 } |
206 | |
207 // the various insn_gen? functions have an immediate mode of ? bits | |
361 | 208 PARSEFUNC(insn_parse_gen0) |
339 | 209 { |
210 if (**p == '#') | |
211 { | |
361 | 212 lwasm_register_error(as, l, "Immediate mode not allowed"); |
339 | 213 return; |
214 } | |
215 | |
216 // handle non-immediate | |
361 | 217 insn_parse_gen_aux(as, l, p); |
339 | 218 } |
219 | |
361 | 220 RESOLVEFUNC(insn_resolve_gen0) |
339 | 221 { |
361 | 222 if (l -> len != -1) |
223 return; | |
224 | |
225 // handle non-immediate | |
382 | 226 insn_resolve_gen_aux(as, l, force, 0); |
361 | 227 } |
228 | |
229 EMITFUNC(insn_emit_gen0) | |
230 { | |
362 | 231 insn_emit_gen_aux(as, l, -1); |
361 | 232 } |
233 | |
234 PARSEFUNC(insn_parse_gen8) | |
235 { | |
339 | 236 if (**p == '#') |
237 { | |
361 | 238 lw_expr_t e; |
239 | |
339 | 240 (*p)++; |
361 | 241 e = lwasm_parse_expr(as, p); |
242 if (!e) | |
339 | 243 { |
361 | 244 lwasm_register_error(as, l, "Bad operand"); |
245 return; | |
339 | 246 } |
361 | 247 l -> len = OPLEN(instab[l -> insn].ops[3]) + 1; |
248 l -> lint2 = 3; | |
249 lwasm_save_expr(l, 0, e); | |
339 | 250 return; |
251 } | |
252 | |
361 | 253 // handle non-immediate |
254 insn_parse_gen_aux(as, l, p); | |
255 if (l -> lint2 != -1) | |
256 { | |
257 if (l -> lint2 == 0) | |
258 { | |
259 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
260 } | |
261 else if (l -> lint2 == 2) | |
262 { | |
263 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
264 } | |
265 else if (l -> lint2 == 1 && l -> lint != -1) | |
266 { | |
267 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
268 } | |
269 } | |
339 | 270 } |
271 | |
361 | 272 RESOLVEFUNC(insn_resolve_gen8) |
273 { | |
274 if (l -> len != -1) | |
275 return; | |
276 | |
277 // handle non-immediate | |
382 | 278 insn_resolve_gen_aux(as, l, force, 0); |
361 | 279 } |
280 | |
281 EMITFUNC(insn_emit_gen8) | |
339 | 282 { |
361 | 283 if (l -> lint2 == 3) |
284 { | |
285 lw_expr_t e; | |
286 e = lwasm_fetch_expr(l, 0); | |
287 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
288 lwasm_emitexpr(l, e, 1); | |
289 return; | |
290 } | |
291 | |
362 | 292 insn_emit_gen_aux(as, l, -1); |
361 | 293 } |
294 | |
295 PARSEFUNC(insn_parse_gen16) | |
296 { | |
339 | 297 if (**p == '#') |
298 { | |
361 | 299 lw_expr_t e; |
300 | |
339 | 301 (*p)++; |
361 | 302 e = lwasm_parse_expr(as, p); |
303 if (!e) | |
339 | 304 { |
361 | 305 lwasm_register_error(as, l, "Bad operand"); |
306 return; | |
339 | 307 } |
361 | 308 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; |
309 l -> lint2 = 3; | |
310 lwasm_save_expr(l, 0, e); | |
339 | 311 return; |
312 } | |
313 | |
361 | 314 // handle non-immediate |
315 insn_parse_gen_aux(as, l, p); | |
316 if (l -> lint2 != -1) | |
317 { | |
318 if (l -> lint2 == 0) | |
319 { | |
320 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
321 } | |
322 else if (l -> lint2 == 2) | |
323 { | |
324 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
325 } | |
326 else if (l -> lint2 == 1 && l -> lint != -1) | |
327 { | |
328 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
329 } | |
330 } | |
339 | 331 } |
332 | |
361 | 333 RESOLVEFUNC(insn_resolve_gen16) |
334 { | |
335 if (l -> len != -1) | |
336 return; | |
337 | |
338 // handle non-immediate | |
382 | 339 insn_resolve_gen_aux(as, l, force, 0); |
361 | 340 } |
341 | |
342 EMITFUNC(insn_emit_gen16) | |
339 | 343 { |
361 | 344 if (l -> lint2 == 3) |
345 { | |
346 lw_expr_t e; | |
347 e = lwasm_fetch_expr(l, 0); | |
348 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
349 lwasm_emitexpr(l, e, 2); | |
350 return; | |
351 } | |
352 | |
362 | 353 insn_emit_gen_aux(as, l, -1); |
361 | 354 } |
355 | |
356 PARSEFUNC(insn_parse_gen32) | |
357 { | |
339 | 358 if (**p == '#') |
359 { | |
361 | 360 lw_expr_t e; |
361 | |
339 | 362 (*p)++; |
361 | 363 e = lwasm_parse_expr(as, p); |
364 if (!e) | |
339 | 365 { |
361 | 366 lwasm_register_error(as, l, "Bad operand"); |
367 return; | |
339 | 368 } |
361 | 369 l -> len = OPLEN(instab[l -> insn].ops[3]) + 4; |
370 l -> lint2 = 3; | |
371 lwasm_save_expr(l, 0, e); | |
339 | 372 return; |
373 } | |
374 | |
361 | 375 // handle non-immediate |
376 insn_parse_gen_aux(as, l, p); | |
377 if (l -> lint2 != -1) | |
378 { | |
379 if (l -> lint2 == 0) | |
380 { | |
381 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
382 } | |
383 else if (l -> lint2 == 2) | |
384 { | |
385 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
386 } | |
387 else if (l -> lint2 == 1 && l -> lint != -1) | |
388 { | |
389 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
390 } | |
391 } | |
339 | 392 } |
393 | |
361 | 394 RESOLVEFUNC(insn_resolve_gen32) |
395 { | |
396 if (l -> len != -1) | |
397 return; | |
398 | |
399 // handle non-immediate | |
382 | 400 insn_resolve_gen_aux(as, l, force, 0); |
361 | 401 } |
402 | |
403 EMITFUNC(insn_emit_gen32) | |
339 | 404 { |
361 | 405 if (l -> lint2 == 3) |
406 { | |
407 lw_expr_t e; | |
408 e = lwasm_fetch_expr(l, 0); | |
409 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
410 lwasm_emitexpr(l, e, 4); | |
411 return; | |
412 } | |
413 | |
362 | 414 insn_emit_gen_aux(as, l, -1); |
361 | 415 } |
416 | |
417 PARSEFUNC(insn_parse_imm8) | |
418 { | |
419 lw_expr_t e; | |
339 | 420 |
421 if (**p == '#') | |
422 { | |
423 (*p)++; | |
424 | |
361 | 425 e = lwasm_parse_expr(as, p); |
426 if (!e) | |
427 { | |
428 lwasm_register_error(as, l, "Bad operand"); | |
429 return; | |
430 } | |
431 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
432 lwasm_save_expr(l, 0, e); | |
433 } | |
434 } | |
339 | 435 |
361 | 436 EMITFUNC(insn_emit_imm8) |
437 { | |
438 lw_expr_t e; | |
439 | |
440 lwasm_emitop(l, instab[l -> insn].ops[0]); | |
383
848d3cca8078
Fixed imm8 to actually use expression and also fixed gen mode to respect > and <
lost@starbug
parents:
382
diff
changeset
|
441 e = lwasm_fetch_expr(l, 0); |
361 | 442 lwasm_emitexpr(l, e, 1); |
339 | 443 } |