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