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 }