comparison src/insn_indexed.c @ 81:b6b1e79cc277

Moved indexed modes to new expression framework
author lost
date Sat, 10 Jan 2009 19:05:15 +0000
parents 538e15927776
children e12edcfbebd5
comparison
equal deleted inserted replaced
80:8929e1ee99cf 81:b6b1e79cc277
61 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0}, 61 {"[,w]", 0x90}, {"[,w++]", 0xd0}, {"[,--w]", 0xf0},
62 62
63 { "", -1 } 63 { "", -1 }
64 }; 64 };
65 char stbuf[25]; 65 char stbuf[25];
66 int i; 66 int i, j, rn;
67 int f8 = 0, f16 = 0; 67 int f8 = 0, f16 = 0, f0 = 0;
68 int rn; 68 int r, v;
69 int indir = 0; 69 int indir = 0;
70 int rval; 70
71 int f0 = 0; 71 // initialize output bytes
72 const char *p2;
73 lwasm_expr_stack_t *s;
74
75 *b1 = *b2 = *b3 = -1; 72 *b1 = *b2 = *b3 = -1;
76 73
74 // fetch out operand for lookup
77 for (i = 0; i < 24; i++) 75 for (i = 0; i < 24; i++)
78 { 76 {
79 if (*((*p) + i) && !isspace(*((*p) + i))) 77 if (*((*p) + i) && !isspace(*((*p) + i)))
80 stbuf[i] = *((*p) + i); 78 stbuf[i] = *((*p) + i);
81 else 79 else
82 break; 80 break;
83 } 81 }
84 stbuf[i] = '\0'; 82 stbuf[i] = '\0';
83
84 // now look up operand in "simple" table
85 if (!*((*p) + i) || isspace(*((*p) + i))) 85 if (!*((*p) + i) || isspace(*((*p) + i)))
86 { 86 {
87 int j;
88 // do simple lookup 87 // do simple lookup
89 for (j = 0; simpleindex[j].opstr[0]; j++) 88 for (j = 0; simpleindex[j].opstr[0]; j++)
90 { 89 {
91 if (!strcasecmp(stbuf, simpleindex[j].opstr)) 90 if (!strcasecmp(stbuf, simpleindex[j].opstr))
92 break; 91 break;
96 *b1 = simpleindex[j].pb; 95 *b1 = simpleindex[j].pb;
97 (*p) += i; 96 (*p) += i;
98 return; 97 return;
99 } 98 }
100 } 99 }
101 100
102 // now we have the hard ones to work out here 101 // now do the "hard" ones
103 102
104 // if we've previously forced the sizes, make a note of it 103 // is it indirect?
104 if (**p == '[')
105 {
106 indir = 1;
107 (*p)++;
108 }
109
110 // look for a "," - all indexed modes have a "," except extended indir
111 rn = 0;
112 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
113 {
114 if ((*p)[i] == ',')
115 {
116 rn = 1;
117 break;
118 }
119 }
120
121 // if no "," and indirect, do extended indir
122 if (!rn && indir)
123 {
124 // extended indir
125 *b1 = 0x9f;
126 *b2 = 0;
127 *b3 = 0;
128
129 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0);
130 if (r < 0)
131 {
132 return;
133 }
134
135 if (**p != ']')
136 {
137 register_error(as, l, 1, "Bad operand");
138 return;
139 }
140
141 (*p)++;
142
143 if (r == 1 && as -> passnum == 2)
144 {
145 l -> relocoff = as -> addr - l -> codeaddr + 1;
146 }
147
148 *b2 = (v >> 8) & 0xff;
149 *b3 = v & 0xff;
150 return;
151 }
152
153 // if we've previously forced the offset size, make a note of it
105 if (l -> fsize == 1) 154 if (l -> fsize == 1)
106 f8 = 1; 155 f8 = 1;
107 else if (l -> fsize == 2) 156 else if (l -> fsize == 2)
108 f16 = 1; 157 f16 = 1;
109
110 if (**p == '[')
111 {
112 indir = 1;
113 (*p)++;
114 }
115
116 rn = 0;
117 for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
118 {
119 if ((*p)[i] == ',')
120 {
121 rn = 1;
122 break;
123 }
124 }
125
126 if (!rn && indir)
127 {
128 // extended indir
129 *b1 = 0x9f;
130 *b2 = 0;
131 *b3 = 0;
132 s = lwasm_evaluate_expr(as, l, *p, &p2);
133 if (!s)
134 {
135 register_error(as, l, 1, "Bad expression");
136 return;
137 }
138 *p = p2;
139 if (**p != ']')
140 {
141 register_error(as, l, 1, "Bad operand");
142 return;
143 }
144 (*p)++;
145 if (!lwasm_expr_is_constant(s))
146 {
147 register_error(as, l, 2, "Incomplete reference");
148 }
149 rn = lwasm_expr_get_value(s);
150 lwasm_expr_stack_free(s);
151 *b2 = (rn >> 8) & 0xff;
152 *b3 = rn & 0xff;
153 return;
154 }
155 158
156 if (**p == '<') 159 if (**p == '<')
157 { 160 {
158 f8 = 1; 161 f8 = 1;
159 (*p)++; 162 (*p)++;
168 { 171 {
169 f0 = 1; 172 f0 = 1;
170 } 173 }
171 174
172 // now we have to evaluate the expression 175 // now we have to evaluate the expression
173 s = lwasm_evaluate_expr(as, l, *p, &p2); 176 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0);
174 *p = p2; 177 if (r < 0)
175 if (!s) 178 {
176 { 179 return;
177 register_error(as, l, 1, "Bad expression"); 180 }
178 return; 181 if (f8 && r != 0)
179 } 182 {
180 if (!lwasm_expr_is_constant(s)) 183 register_error(as, l, 2, "Illegal external or inter-section reference");
181 { 184 r = 0;
182 register_error(as, l, 2, "Incomplete reference"); 185 v = 0;
183 if (!f8 && !f0) 186 }
184 { 187
185 f16 = 1;
186 l -> fsize = 2;
187 }
188 }
189 rval = lwasm_expr_get_value(s);
190 lwasm_expr_stack_free(s);
191
192 // now look for a comma; if not present, explode 188 // now look for a comma; if not present, explode
193 if (*(*p)++ != ',') 189 if (*(*p)++ != ',')
194 { 190 {
195 // syntax error; force 0 bit 191 // syntax error; force 0 bit
196 *b1 = 00; 192 *b1 = 00;
193 l -> fsize = 0;
197 return; 194 return;
198 } 195 }
199 196
200 // now get the register 197 // now get the register
201 rn = lwasm_lookupreg3(regs, p); 198 rn = lwasm_lookupreg3(regs, p);
202 if (rn < 0) 199 if (rn < 0)
203 goto reterr; 200 {
204 201 *b1 = 0;
202 l -> fsize = 0;
203 register_error(as, l, 1, "Bad register");
204 return;
205 }
206
205 if (indir) 207 if (indir)
206 { 208 {
207 if (**p != ']') 209 if (**p != ']')
208 goto reterr; 210 {
211 register_error(as, l, 1, "Bad operand");
212 l -> fsize = 0;
213 *b1 = 0;
214 return;
215 }
209 else 216 else
210 (*p)++; 217 (*p)++;
211 } 218 }
212 219
213 // nnnn,W is only 16 bit 220 // incomplete reference on pass 1 forces 16 bit
221 if (r == 1 && as -> passnum == 1)
222 {
223 f16 = 1;
224 l -> fsize = 2;
225 }
226
227 // incomplete reference on pass 2 needs relocoff set
228 if (r == 1 && as -> passnum == 2)
229 {
230 l -> relocoff = as -> addr - l -> codeaddr + 1;
231 }
232
233 // nnnn,W is only 16 bit (or 0 bit)
214 if (rn == 4) 234 if (rn == 4)
215 { 235 {
216 if (f8) 236 if (f8)
217 goto reterr; 237 {
218 if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && rval == 0) 238 register_error(as, l, 1, "n,W cannot be 8 bit");
239 l -> fsize = 0;
240 *b1 = 0;
241 return;
242 }
243 // note: set f16 above for incomplete references
244 // also set reloc offset
245 if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && v == 0)
219 { 246 {
220 if (indir) 247 if (indir)
221 *b1 = 0x90; 248 *b1 = 0x90;
222 else 249 else
223 *b1 = 0x8f; 250 *b1 = 0x8f;
224 return; 251 return;
225 } 252 }
253
226 if (indir) 254 if (indir)
227 *b1 = 0xb0; 255 *b1 = 0xb0;
228 else 256 else
229 *b1 = 0xcf; 257 *b1 = 0xcf;
230 *b2 = (rval >> 8) & 0xff; 258 *b2 = (v >> 8) & 0xff;
231 *b3 = rval & 0xff; 259 *b3 = v & 0xff;
232 return; 260 return;
233 } 261 }
234 262
263 // set indir to correct bit value
235 if (indir) indir = 0x10; 264 if (indir) indir = 0x10;
236 265
237 // PCR? redo v1, v2 relative to current address 266 // PCR? then we have PC relative addressing (like B??, LB??)
238 if (rn == 5) 267 if (rn == 5)
239 { 268 {
240 rval -= as -> addr; 269 // FIXME: handle external references sensibly
270 v -= as -> addr;
241 271
242 // we have a slight problem here 272 // we have a slight problem here
243 // PCR based on current insn loc is really 273 // PCR based on current insn loc is really
244 // -125 <= offset <= +130 (8 bit offset) 274 // -125 <= offset <= +130 (8 bit offset)
245 // NOTE: when we are called, we already have the opcode emitted 275 // NOTE: when we are called, we already have the opcode emitted
246 // so we only need to worry about the size of the operand 276 // so we only need to worry about the size of the operand
247 // hence the 2 and 3 magic numbers below instead of 3 and 4 277 // hence the 2 and 3 magic numbers below instead of 3 and 4
248 // (and that also avoids errors with two byte opcodes, etc) 278 // (and that also avoids errors with two byte opcodes, etc)
249 if (f8 || (!f16 && rval >= -125 && rval <= 130)) 279 if (f8 || (!f16 && v >= -125 && v <= 130))
250 { 280 {
251 *b1 = indir | 0x8C; 281 *b1 = indir | 0x8C;
252 rval -= 2; 282 v -= 2;
253 if (rval < -128 || rval > 127) 283 if (v < -128 || v > 127)
254 register_error(as, l, 2, "Byte overflow"); 284 register_error(as, l, 2, "Byte overflow");
255 *b2 = rval & 0xff; 285 *b2 = v & 0xff;
256 return; 286 return;
257 } 287 }
258 288
259 // anything else is 16 bit offset 289 // anything else is 16 bit offset
260 // need 16 bit 290 // need 16 bit
261 *b1 = indir | 0x8D; 291 *b1 = indir | 0x8D;
262 rval -= 3; 292 v -= 3;
263 *b2 = (rval >> 8) & 0xff; 293 *b2 = (v >> 8) & 0xff;
264 *b3 = rval & 0xff; 294 *b3 = v & 0xff;
265 return; 295 return;
266 } 296 }
267 297
268 // constant offset from PC 298 // constant offset from PC (using PC as regular register :) )
299 // FIXME: handle external references intelligently
269 if (rn == 6) 300 if (rn == 6)
270 { 301 {
271 if (f8 || (!f16 && rval >= -128 && rval <= 127)) 302 if (f8 || (!f16 && v >= -128 && v <= 127))
272 { 303 {
273 *b1 = indir | 0x8C; 304 *b1 = indir | 0x8C;
274 if (rval < -128 || rval > 127) 305 if (v < -128 || v > 127)
275 register_error(as, l, 2, "Byte overflow"); 306 register_error(as, l, 2, "Byte overflow");
276 *b2 = rval & 0xff; 307 *b2 = v & 0xff;
277 return; 308 return;
278 } 309 }
279 310
280 // everything else must be 16 bit 311 // everything else must be 16 bit
281 // need 16 bit 312 // need 16 bit
282 *b1 = indir | 0x8D; 313 *b1 = indir | 0x8D;
283 *b2 = (rval >> 8) & 0xff; 314 *b2 = (v >> 8) & 0xff;
284 *b3 = rval & 0xff; 315 *b3 = v & 0xff;
285 return; 316 return;
286 } 317 }
287 318
288 // we only have to deal with x,y,u,s here 319 // we only have to deal with x,y,u,s here
289 if (!f8 && !f16 && rval >= -16 && rval <= 15) 320 if (!f8 && !f16 && v >= -16 && v <= 15)
290 { 321 {
291 if (rval == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) 322 // zero offset going to ,R?
323 if (v == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE))
292 { 324 {
293 *b1 = rn << 5 | indir | 0x80 | 0x04; 325 *b1 = rn << 5 | indir | 0x80 | 0x04;
294 return; 326 return;
295 } 327 }
296 // we pick the smallest value here 328
329 // no 5 bit on indirect
297 if (indir) 330 if (indir)
298 { 331 {
299 f8 = 1; 332 f8 = 1;
333 l -> fsize = 1;
300 goto no5bit; 334 goto no5bit;
301 } 335 }
302 *b1 = rn << 5 | (rval & 0x1F); 336
303 return; 337 // 5 bit addressing
304 } 338 *b1 = rn << 5 | (v & 0x1F);
339 return;
340 }
341
305 no5bit: 342 no5bit:
306 if (f16 || (!f8 && (rval < -128 || rval > 127))) 343 if (f16 || (!f8 && (v < -128 || v > 127)))
307 { 344 {
308 // must be a 16 bit offset here 345 // must be a 16 bit offset here
309 *b1 = rn << 5 | indir | 0x80 | 0x09; 346 *b1 = rn << 5 | indir | 0x80 | 0x09;
310 *b2 = (rval >> 8) & 0xff; 347 *b2 = (v >> 8) & 0xff;
311 *b3 = rval & 0xff; 348 *b3 = v & 0xff;
312 return; 349 return;
313 } 350 }
314 351
315 // if we're here, we have an 8 bit offset 352 // if we're here, we have an 8 bit offset
353 // note: cannot get here if incomplete reference detected above
316 *b1 = rn << 5 | indir | 0x80 | 0x08; 354 *b1 = rn << 5 | indir | 0x80 | 0x08;
317 if (rval < -128 || rval > 127) 355 if (v < -128 || v > 127)
318 register_error(as, l, 2, "Byte overflow"); 356 register_error(as, l, 2, "Byte overflow");
319 *b2 = rval & 0xff; 357 *b2 = v & 0xff;
320 return;
321 reterr:
322 *b1 = 0;
323 return; 358 return;
324 } 359 }
325 360
326 OPFUNC(insn_indexed) 361 OPFUNC(insn_indexed)
327 { 362 {