comparison lwasm/insn_indexed.c @ 359:f50a54d0293a

Indexed part 1
author lost@starbug
date Wed, 31 Mar 2010 21:57:45 -0600
parents old-trunk/lwasm/old/insn_indexed.c@eb230fa7d28e
children 7d91ab7ac7d6
comparison
equal deleted inserted replaced
358:be0f9f8d799f 359:f50a54d0293a
1 /*
2 insn_indexed.c
3 Copyright © 2009 William Astle
4
5 This file is part of LWASM.
6
7 LWASM is free software: you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation, either version 3 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22 for handling indexed mode instructions
23 */
24
25 #include <config.h>
26
27 #include <ctype.h>
28 #include <string.h>
29
30 #include <lw_expr.h>
31
32 #include "lwasm.h"
33 #include "instab.h"
34
35 /*
36 l -> lint: size of operand (0, 1, 2, -1 if not determined)
37 l -> pb: actual post byte (from "resolve" stage) or info passed
38 forward to the resolve stage (if l -> line is -1); 0x80 is indir
39 bits 0-2 are register number
40 */
41 void insn_parse_indexed_aux(asmstate_t *as, line_t *l, char **p)
42 {
43 struct opvals { char *opstr; int pb; };
44
45 static const char *regs = "X Y U S W PCRPC ";
46 static const struct opvals simpleindex[] =
47 {
48 {",x", 0x84}, {",y", 0xa4}, {",u", 0xc4}, {",s", 0xe4},
49 {",x+", 0x80}, {",y+", 0xa0}, {",u+", 0xc0}, {",s+", 0xe0},
50 {",x++", 0x81}, {",y++", 0xa1}, {",u++", 0xc1}, {",s++", 0xe1},
51 {",-x", 0x82}, {",-y", 0xa2}, {",-u", 0xc2}, {",-s", 0xe2},
52 {",--x", 0x83}, {",--y", 0xa3}, {",--u", 0xc3}, {",--s", 0xe3},
53 {"a,x", 0x86}, {"a,y", 0xa6}, {"a,u", 0xc6}, {"a,s", 0xe6},
54 {"b,x", 0x85}, {"b,y", 0xa5}, {"b,u", 0xc5}, {"b,s", 0xe5},
55 {"e,x", 0x87}, {"e,y", 0xa7}, {"e,u", 0xc7}, {"e,s", 0xe7},
56 {"f,x", 0x8a}, {"f,y", 0xaa}, {"f,u", 0xca}, {"f,s", 0xea},
57 {"d,x", 0x8b}, {"d,y", 0xab}, {"d,u", 0xcb}, {"d,s", 0xed},
58 {"w,x", 0x8e}, {"w,y", 0xae}, {"w,u", 0xce}, {"w,s", 0xee},
59 {",w", 0x8f}, {",w++", 0xcf}, {",--w", 0xef},
60
61 {"[,x]", 0x94}, {"[,y]", 0xb4}, {"[,u", 0xd4}, {"[,s]", 0xf4},
62 {"[,x++]", 0x91}, {"[,y++]", 0xb1}, {"[,u++]", 0xd1}, {"[,s++]", 0xf1},
63 {"[,--x]", 0x93}, {"[,--y]", 0xb3}, {"[,--u]", 0xd3}, {"[,--s]", 0xf3},
64 {"[a,x]", 0x96}, {"[a,y]", 0xb6}, {"[a,u]", 0xd6}, {"[a,s]", 0xf6},
65 {"[b,x]", 0x95}, {"[b,y]", 0xb5}, {"[b,u]", 0xd5}, {"[b,s]", 0xf5},
66 {"[e,x]", 0x97}, {"[e,y]", 0xb7}, {"[e,u]", 0xd7}, {"[e,s]", 0xf7},
67 {"[f,x]", 0x9a}, {"[f,y]", 0xba}, {"[f,u]", 0xda}, {"[f,s]", 0xfa},
68 {"[d,x]", 0x9b}, {"[d,y]", 0xbb}, {"[d,u]", 0xdb}, {"[d,s]", 0xfd},
69 {"[w,x]", 0x9e}, {"[w,y]", 0xbe}, {"[w,u]", 0xde}, {"[w,s]", 0xfe},
70 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0},
71
72 { "", -1 }
73 };
74
75 static const char *regs9 = "X Y U S PCRPC ";
76 static const struct opvals simpleindex9[] =
77 {
78 {",x", 0x84}, {",y", 0xa4}, {",u", 0xc4}, {",s", 0xe4},
79 {",x+", 0x80}, {",y+", 0xa0}, {",u+", 0xc0}, {",s+", 0xe0},
80 {",x++", 0x81}, {",y++", 0xa1}, {",u++", 0xc1}, {",s++", 0xe1},
81 {",-x", 0x82}, {",-y", 0xa2}, {",-u", 0xc2}, {",-s", 0xe2},
82 {",--x", 0x83}, {",--y", 0xa3}, {",--u", 0xc3}, {",--s", 0xe3},
83 {"a,x", 0x86}, {"a,y", 0xa6}, {"a,u", 0xc6}, {"a,s", 0xe6},
84 {"b,x", 0x85}, {"b,y", 0xa5}, {"b,u", 0xc5}, {"b,s", 0xe5},
85 {"d,x", 0x8b}, {"d,y", 0xab}, {"d,u", 0xcb}, {"d,s", 0xed},
86
87 {"[,x]", 0x94}, {"[,y]", 0xb4}, {"[,u", 0xd4}, {"[,s]", 0xf4},
88 {"[,x++]", 0x91}, {"[,y++]", 0xb1}, {"[,u++]", 0xd1}, {"[,s++]", 0xf1},
89 {"[,--x]", 0x93}, {"[,--y]", 0xb3}, {"[,--u]", 0xd3}, {"[,--s]", 0xf3},
90 {"[a,x]", 0x96}, {"[a,y]", 0xb6}, {"[a,u]", 0xd6}, {"[a,s]", 0xf6},
91 {"[b,x]", 0x95}, {"[b,y]", 0xb5}, {"[b,u]", 0xd5}, {"[b,s]", 0xf5},
92 {"[d,x]", 0x9b}, {"[d,y]", 0xbb}, {"[d,u]", 0xdb}, {"[d,s]", 0xfd},
93
94 { "", -1 }
95 };
96 char stbuf[25];
97 int i, j, rn;
98 int indir = 0;
99 int f0 = 1;
100 const struct opvals *simples;
101 const char *reglist;
102 lw_expr_t e;
103
104 if (as -> target == TARGET_6809)
105 {
106 simples = simpleindex9;
107 reglist = regs9;
108 }
109 else
110 {
111 simples = simpleindex;
112 reglist = regs;
113 }
114
115 // fetch out operand for lookup
116 for (i = 0; i < 24; i++)
117 {
118 if (*((*p) + i) && !isspace(*((*p) + i)))
119 stbuf[i] = *((*p) + i);
120 else
121 break;
122 }
123 stbuf[i] = '\0';
124
125 // now look up operand in "simple" table
126 if (!*((*p) + i) || isspace(*((*p) + i)))
127 {
128 // do simple lookup
129 for (j = 0; simples[j].opstr[0]; j++)
130 {
131 if (!strcasecmp(stbuf, simples[j].opstr))
132 break;
133 }
134 if (simples[j].opstr[0])
135 {
136 l -> pb = simples[j].pb;
137 l -> lint = 0;
138 (*p) += i;
139 return;
140 }
141 }
142
143 // now do the "hard" ones
144
145 // is it indirect?
146 if (**p == '[')
147 {
148 indir = 1;
149 (*p)++;
150 }
151
152 // look for a "," - all indexed modes have a "," except extended indir
153 rn = 0;
154 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
155 {
156 if ((*p)[i] == ',')
157 {
158 rn = 1;
159 break;
160 }
161 }
162
163 // if no "," and indirect, do extended indir
164 if (!rn && indir)
165 {
166 // extended indir
167 l -> pb = 0x9f;
168 e = lwasm_parse_expr(as, p);
169 if (!e || **p != ']')
170 {
171 lwasm_register_error(as, l, "Bad operand");
172 return;
173 }
174
175 (*p)++;
176 l -> lint = 2;
177 return;
178 }
179
180 if (**p == '<')
181 {
182 l -> lint = 1;
183 (*p)++;
184 }
185 else if (**p == '>')
186 {
187 l -> lint = 2;
188 (*p)++;
189 }
190
191 if (**p == '0' && *(*p+1) == ',')
192 {
193 f0 = 1;
194 }
195
196 // now we have to evaluate the expression
197 e = lwasm_parse_expr(as, p);
198 if (!e)
199 {
200 lwasm_register_error(as, l, "Bad operand");
201 return;
202 }
203 lwasm_save_expr(l, 0, e);
204
205 // now look for a comma; if not present, explode
206 if (*(*p)++ != ',')
207 {
208 lwasm_register_error(as, l, "Bad operand");
209 return;
210 }
211
212 // now get the register
213 rn = lwasm_lookupreg3(reglist, p);
214 if (rn < 0)
215 {
216 lwasm_register_error(as, l, "Bad register");
217 return;
218 }
219
220 if (indir)
221 {
222 if (**p != ']')
223 {
224 lwasm_register_error(as, l, "Bad operand");
225 return;
226 }
227 else
228 (*p)++;
229 }
230
231 // nnnn,W is only 16 bit (or 0 bit)
232 if (rn == 4)
233 {
234 if (l -> lint == 1)
235 {
236 lwasm_register_error(as, l, "n,W cannot be 8 bit");
237 return;
238 }
239
240 if (l -> lint == 2)
241 {
242 l -> pb = indir ? 0xb0 : 0xcf;
243 l -> lint = 2;
244 return;
245 }
246
247 l -> pb = (0x80 * indir) | rn;
248
249 /* [,w] and ,w
250 if (indir)
251 *b1 = 0x90;
252 else
253 *b1 = 0x8f;
254 */
255 return;
256 }
257
258 // PCR? then we have PC relative addressing (like B??, LB??)
259 if (rn == 5)
260 {
261 lw_expr_t e1, e2;
262 // external references are handled exactly the same as for
263 // relative addressing modes
264 // on pass 1, adjust the expression for a subtraction of the
265 // current address
266
267 e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
268 e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, l -> addr, e1);
269 lw_expr_destroy(e1);
270 e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, e, l -> addr);
271 lwasm_save_expr(l, 0, e1);
272 lw_expr_destroy(e2);
273 }
274
275 l -> pb = (indir * 0x80) | rn | (f0 * 0x40);
276 }
277
278 PARSEFUNC(insn_parse_indexed)
279 {
280 l -> lint = -1;
281 insn_parse_indexed_aux(as, l, p);
282
283 if (l -> lint != -1)
284 {
285 l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
286 }
287 }
288
289 void insn_resolve_indexed_aux(asmstate_t *as, line_t *l)
290 {
291 }
292
293 RESOLVEFUNC(insn_resolve_indexed)
294 {
295 insn_resolve_indexed_aux(as, l);
296
297 if (l -> lint != -1 && l -> pb != -1)
298 {
299 l -> len = OPLEN(instab[l -> insn].ops[0]) + l -> lint + 1;
300 }
301 }
302
303 void insn_emit_indexed_aux(asmstate_t *as, line_t *l)
304 {
305 lw_expr_t e;
306
307 lwasm_emitop(l, instab[l -> insn].ops[0]);
308 lwasm_emitop(l, l -> pb);
309 if (l -> lint > 0)
310 {
311 e = lwasm_fetch_expr(l, 0);
312 lwasm_emitexpr(l, e, l -> lint);
313 }
314 }
315
316 EMITFUNC(insn_emit_indexed)
317 {
318 insn_emit_indexed_aux(as, l);
319 }