Mercurial > hg > index.cgi
comparison lwasm/insn_gen.c @ 0:2c24602be78f
Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author | lost@l-w.ca |
---|---|
date | Wed, 19 Jan 2011 22:27:17 -0700 |
parents | |
children | 7317fbe024af |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:2c24602be78f |
---|---|
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 <ctype.h> | |
23 #include <stdlib.h> | |
24 | |
25 #include <lw_expr.h> | |
26 | |
27 #include "lwasm.h" | |
28 #include "instab.h" | |
29 | |
30 extern void insn_indexed_parse_aux(asmstate_t *as, line_t *l, char **p); | |
31 extern void insn_indexed_resolve_aux(asmstate_t *as, line_t *l, int force, int elen); | |
32 extern void insn_indexed_emit_aux(asmstate_t *as, line_t *l); | |
33 | |
34 // "extra" is required due to the way OIM, EIM, TIM, and AIM work | |
35 void insn_parse_gen_aux(asmstate_t *as, line_t *l, char **p) | |
36 { | |
37 const char *optr2; | |
38 int v1, tv, rval; | |
39 lw_expr_t s; | |
40 | |
41 optr2 = *p; | |
42 while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++ | |
43 /* do nothing */ ; | |
44 | |
45 if (*optr2 == ',' || **p == '[') | |
46 { | |
47 l -> lint = -1; | |
48 l -> lint2 = 1; | |
49 insn_parse_indexed_aux(as, l, p); | |
50 goto out; | |
51 } | |
52 | |
53 if (**p == '<') | |
54 { | |
55 (*p)++; | |
56 l -> lint2 = 0; | |
57 } | |
58 | |
59 // for compatibility with asxxxx | |
60 // * followed by a digit, alpha, or _, or ., or ?, or another * is "f8" | |
61 else if (**p == '*') | |
62 { | |
63 tv = *(*p + 1); | |
64 if (isdigit(tv) || isalpha(tv) || tv == '_' || tv == '.' || tv == '?' || tv == '@' || tv == '*' || tv == '+' || tv == '-') | |
65 { | |
66 l -> lint2 = 0; | |
67 (*p)++; | |
68 } | |
69 } | |
70 else if (**p == '>') | |
71 { | |
72 (*p)++; | |
73 l -> lint2 = 2; | |
74 } | |
75 else | |
76 { | |
77 l -> lint2 = -1; | |
78 } | |
79 | |
80 s = lwasm_parse_expr(as, p); | |
81 if (!s) | |
82 { | |
83 lwasm_register_error(as, l, "Bad operand"); | |
84 return; | |
85 } | |
86 | |
87 lwasm_save_expr(l, 0, s); | |
88 | |
89 if (as -> output_format == OUTPUT_OBJ && l -> lint2 == -1) | |
90 { | |
91 l -> lint2 = 2; | |
92 goto out; | |
93 } | |
94 | |
95 if (l -> lint2 != -1) | |
96 goto out; | |
97 | |
98 // if we have a constant now, figure out dp vs nondp | |
99 if (lw_expr_istype(s, lw_expr_type_int)) | |
100 { | |
101 v1 = lw_expr_intval(s); | |
102 if (((v1 >> 8) & 0xff) == (l -> dpval & 0xff)) | |
103 { | |
104 l -> lint2 = 0; | |
105 goto out; | |
106 } | |
107 l -> lint2 = 2; | |
108 } | |
109 | |
110 out: | |
111 if (l -> lint2 != -1) | |
112 { | |
113 if (l -> lint2 == 0) | |
114 { | |
115 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
116 } | |
117 else if (l -> lint2 == 2) | |
118 { | |
119 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
120 } | |
121 else if (l -> lint2 == 1 && l -> lint != -1) | |
122 { | |
123 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
124 } | |
125 } | |
126 } | |
127 | |
128 void insn_resolve_gen_aux(asmstate_t *as, line_t *l, int force, int elen) | |
129 { | |
130 lw_expr_t e; | |
131 | |
132 if (l -> lint2 == 1) | |
133 { | |
134 // indexed | |
135 insn_resolve_indexed_aux(as, l, force, elen); | |
136 goto out; | |
137 } | |
138 | |
139 if (l -> lint2 != -1) | |
140 return; | |
141 | |
142 e = lwasm_fetch_expr(l, 0); | |
143 if (lw_expr_istype(e, lw_expr_type_int)) | |
144 { | |
145 int v; | |
146 | |
147 v = lw_expr_intval(e); | |
148 | |
149 if (((v >> 8) & 0xff) == (l -> dpval & 0xff)) | |
150 { | |
151 l -> lint2 = 0; | |
152 goto out; | |
153 } | |
154 l -> lint2 = 2; | |
155 goto out; | |
156 } | |
157 | |
158 if (force) | |
159 { | |
160 l -> lint2 = 2; | |
161 } | |
162 | |
163 out: | |
164 if (l -> lint2 != -1) | |
165 { | |
166 if (l -> lint2 == 0) | |
167 { | |
168 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
169 } | |
170 else if (l -> lint2 == 2) | |
171 { | |
172 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
173 } | |
174 else if (l -> lint2 == 1 && l -> lint != -1) | |
175 { | |
176 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
177 } | |
178 } | |
179 } | |
180 | |
181 void insn_emit_gen_aux(asmstate_t *as, line_t *l, int extra) | |
182 { | |
183 lw_expr_t e; | |
184 | |
185 e = lwasm_fetch_expr(l, 0); | |
186 lwasm_emitop(l, instab[l -> insn].ops[l -> lint2]); | |
187 | |
188 if (extra != -1) | |
189 lwasm_emit(l, extra); | |
190 | |
191 if (l -> lint2 == 1) | |
192 { | |
193 lwasm_emit(l, l -> pb); | |
194 if (l -> lint > 0) | |
195 lwasm_emitexpr(l, e, l -> lint); | |
196 return; | |
197 } | |
198 | |
199 if (l -> lint2 == 2) | |
200 lwasm_emitexpr(l, e, 2); | |
201 else | |
202 lwasm_emitexpr(l, e, 1); | |
203 } | |
204 | |
205 // the various insn_gen? functions have an immediate mode of ? bits | |
206 PARSEFUNC(insn_parse_gen0) | |
207 { | |
208 if (**p == '#') | |
209 { | |
210 lwasm_register_error(as, l, "Immediate mode not allowed"); | |
211 return; | |
212 } | |
213 | |
214 // handle non-immediate | |
215 insn_parse_gen_aux(as, l, p); | |
216 } | |
217 | |
218 RESOLVEFUNC(insn_resolve_gen0) | |
219 { | |
220 if (l -> len != -1) | |
221 return; | |
222 | |
223 // handle non-immediate | |
224 insn_resolve_gen_aux(as, l, force, 0); | |
225 } | |
226 | |
227 EMITFUNC(insn_emit_gen0) | |
228 { | |
229 insn_emit_gen_aux(as, l, -1); | |
230 } | |
231 | |
232 PARSEFUNC(insn_parse_gen8) | |
233 { | |
234 if (**p == '#') | |
235 { | |
236 lw_expr_t e; | |
237 | |
238 (*p)++; | |
239 e = lwasm_parse_expr(as, p); | |
240 if (!e) | |
241 { | |
242 lwasm_register_error(as, l, "Bad operand"); | |
243 return; | |
244 } | |
245 l -> len = OPLEN(instab[l -> insn].ops[3]) + 1; | |
246 l -> lint2 = 3; | |
247 lwasm_save_expr(l, 0, e); | |
248 return; | |
249 } | |
250 | |
251 // handle non-immediate | |
252 insn_parse_gen_aux(as, l, p); | |
253 if (l -> lint2 != -1) | |
254 { | |
255 if (l -> lint2 == 0) | |
256 { | |
257 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
258 } | |
259 else if (l -> lint2 == 2) | |
260 { | |
261 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
262 } | |
263 else if (l -> lint2 == 1 && l -> lint != -1) | |
264 { | |
265 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
266 } | |
267 } | |
268 } | |
269 | |
270 RESOLVEFUNC(insn_resolve_gen8) | |
271 { | |
272 if (l -> len != -1) | |
273 return; | |
274 | |
275 // handle non-immediate | |
276 insn_resolve_gen_aux(as, l, force, 0); | |
277 } | |
278 | |
279 EMITFUNC(insn_emit_gen8) | |
280 { | |
281 if (l -> lint2 == 3) | |
282 { | |
283 lw_expr_t e; | |
284 e = lwasm_fetch_expr(l, 0); | |
285 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
286 lwasm_emitexpr(l, e, 1); | |
287 return; | |
288 } | |
289 | |
290 insn_emit_gen_aux(as, l, -1); | |
291 } | |
292 | |
293 PARSEFUNC(insn_parse_gen16) | |
294 { | |
295 if (**p == '#') | |
296 { | |
297 lw_expr_t e; | |
298 | |
299 (*p)++; | |
300 e = lwasm_parse_expr(as, p); | |
301 if (!e) | |
302 { | |
303 lwasm_register_error(as, l, "Bad operand"); | |
304 return; | |
305 } | |
306 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; | |
307 l -> lint2 = 3; | |
308 lwasm_save_expr(l, 0, e); | |
309 return; | |
310 } | |
311 | |
312 // handle non-immediate | |
313 insn_parse_gen_aux(as, l, p); | |
314 if (l -> lint2 != -1) | |
315 { | |
316 if (l -> lint2 == 0) | |
317 { | |
318 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
319 } | |
320 else if (l -> lint2 == 2) | |
321 { | |
322 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
323 } | |
324 else if (l -> lint2 == 1 && l -> lint != -1) | |
325 { | |
326 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
327 } | |
328 } | |
329 } | |
330 | |
331 RESOLVEFUNC(insn_resolve_gen16) | |
332 { | |
333 if (l -> len != -1) | |
334 return; | |
335 | |
336 // handle non-immediate | |
337 insn_resolve_gen_aux(as, l, force, 0); | |
338 } | |
339 | |
340 EMITFUNC(insn_emit_gen16) | |
341 { | |
342 if (l -> lint2 == 3) | |
343 { | |
344 lw_expr_t e; | |
345 e = lwasm_fetch_expr(l, 0); | |
346 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
347 lwasm_emitexpr(l, e, 2); | |
348 return; | |
349 } | |
350 | |
351 insn_emit_gen_aux(as, l, -1); | |
352 } | |
353 | |
354 PARSEFUNC(insn_parse_gen32) | |
355 { | |
356 if (**p == '#') | |
357 { | |
358 lw_expr_t e; | |
359 | |
360 (*p)++; | |
361 e = lwasm_parse_expr(as, p); | |
362 if (!e) | |
363 { | |
364 lwasm_register_error(as, l, "Bad operand"); | |
365 return; | |
366 } | |
367 l -> len = OPLEN(instab[l -> insn].ops[3]) + 4; | |
368 l -> lint2 = 3; | |
369 lwasm_save_expr(l, 0, e); | |
370 return; | |
371 } | |
372 | |
373 // handle non-immediate | |
374 insn_parse_gen_aux(as, l, p); | |
375 if (l -> lint2 != -1) | |
376 { | |
377 if (l -> lint2 == 0) | |
378 { | |
379 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
380 } | |
381 else if (l -> lint2 == 2) | |
382 { | |
383 l -> len = OPLEN(instab[l -> insn].ops[2]) + 2; | |
384 } | |
385 else if (l -> lint2 == 1 && l -> lint != -1) | |
386 { | |
387 l -> len = OPLEN(instab[l -> insn].ops[1]) + l -> lint + 1; | |
388 } | |
389 } | |
390 } | |
391 | |
392 RESOLVEFUNC(insn_resolve_gen32) | |
393 { | |
394 if (l -> len != -1) | |
395 return; | |
396 | |
397 // handle non-immediate | |
398 insn_resolve_gen_aux(as, l, force, 0); | |
399 } | |
400 | |
401 EMITFUNC(insn_emit_gen32) | |
402 { | |
403 if (l -> lint2 == 3) | |
404 { | |
405 lw_expr_t e; | |
406 e = lwasm_fetch_expr(l, 0); | |
407 lwasm_emitop(l, instab[l -> insn].ops[3]); | |
408 lwasm_emitexpr(l, e, 4); | |
409 return; | |
410 } | |
411 | |
412 insn_emit_gen_aux(as, l, -1); | |
413 } | |
414 | |
415 PARSEFUNC(insn_parse_imm8) | |
416 { | |
417 lw_expr_t e; | |
418 | |
419 if (**p == '#') | |
420 { | |
421 (*p)++; | |
422 | |
423 e = lwasm_parse_expr(as, p); | |
424 if (!e) | |
425 { | |
426 lwasm_register_error(as, l, "Bad operand"); | |
427 return; | |
428 } | |
429 l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; | |
430 lwasm_save_expr(l, 0, e); | |
431 } | |
432 } | |
433 | |
434 EMITFUNC(insn_emit_imm8) | |
435 { | |
436 lw_expr_t e; | |
437 | |
438 lwasm_emitop(l, instab[l -> insn].ops[0]); | |
439 e = lwasm_fetch_expr(l, 0); | |
440 lwasm_emitexpr(l, e, 1); | |
441 } |