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 }