Mercurial > hg-old > index.cgi
comparison src/insn_indexed.c @ 101:f59c0916753d
Fixed relative branches and PCR addressing to handle constant intra-section references properly
author | lost |
---|---|
date | Fri, 23 Jan 2009 03:36:27 +0000 |
parents | e12edcfbebd5 |
children |
comparison
equal
deleted
inserted
replaced
100:579ac3697918 | 101:f59c0916753d |
---|---|
65 char stbuf[25]; | 65 char stbuf[25]; |
66 int i, j, rn; | 66 int i, j, rn; |
67 int f8 = 0, f16 = 0, f0 = 0; | 67 int f8 = 0, f16 = 0, f0 = 0; |
68 int r, v; | 68 int r, v; |
69 int indir = 0; | 69 int indir = 0; |
70 int fs8 = 0, fs16 = 0; | |
70 | 71 |
71 // initialize output bytes | 72 // initialize output bytes |
72 *b1 = *b2 = *b3 = -1; | 73 *b1 = *b2 = *b3 = -1; |
73 | 74 |
74 // fetch out operand for lookup | 75 // fetch out operand for lookup |
154 else if (l -> fsize == 2) | 155 else if (l -> fsize == 2) |
155 f16 = 1; | 156 f16 = 1; |
156 | 157 |
157 if (**p == '<') | 158 if (**p == '<') |
158 { | 159 { |
159 f8 = 1; | 160 fs8 = 1; |
160 (*p)++; | 161 (*p)++; |
161 } | 162 } |
162 else if (**p == '>') | 163 else if (**p == '>') |
163 { | 164 { |
164 f16 = 1; | 165 fs16 = 1; |
165 (*p)++; | 166 (*p)++; |
166 } | 167 } |
167 | 168 |
168 if (**p == '0' && *(*p+1) == ',') | 169 if (**p == '0' && *(*p+1) == ',') |
169 { | 170 { |
174 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); | 175 r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); |
175 if (r < 0) | 176 if (r < 0) |
176 { | 177 { |
177 return; | 178 return; |
178 } | 179 } |
179 if (f8 && r != 0) | |
180 { | |
181 register_error(as, l, 2, "Illegal external or inter-section reference"); | |
182 r = 0; | |
183 v = 0; | |
184 } | |
185 | |
186 // now look for a comma; if not present, explode | 180 // now look for a comma; if not present, explode |
187 if (*(*p)++ != ',') | 181 if (*(*p)++ != ',') |
188 { | 182 { |
189 // syntax error; force 0 bit | 183 // syntax error; force 0 bit |
190 *b1 = 00; | 184 *b1 = 00; |
262 if (indir) indir = 0x10; | 256 if (indir) indir = 0x10; |
263 | 257 |
264 // PCR? then we have PC relative addressing (like B??, LB??) | 258 // PCR? then we have PC relative addressing (like B??, LB??) |
265 if (rn == 5) | 259 if (rn == 5) |
266 { | 260 { |
267 // FIXME: handle external references sensibly | 261 lwasm_expr_term_t *t; |
268 v -= as -> addr; | 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 // need to re-evaluate the expression with "SECTCONST"... | |
268 r = lwasm_expr_result2(as, l, (char **)p, EXPR_SECTCONST | EXPR_REEVAL, &v, 0); | |
269 if (r != 0) | |
270 v = 0; | |
271 if (as -> passnum == 1) | |
272 { | |
273 l -> fsize = 0; | |
274 } | |
275 f8 = f16 = 0; | |
276 if (r == 1 && as -> passnum == 1 && !fs8) | |
277 { | |
278 l -> fsize = 2; | |
279 f16 = 1; | |
280 } | |
281 if (fs8) | |
282 f8 = 1; | |
283 if (fs16) | |
284 f16 = 1; | |
285 if (l -> fsize == 2) | |
286 f16 = 1; | |
287 else if (l -> fsize == 1) | |
288 f8 = 1; | |
289 if (as -> passnum == 1) | |
290 v -= as -> addr; | |
269 | 291 |
270 // we have a slight problem here | 292 // we have a slight problem here |
271 // PCR based on current insn loc is really | 293 // PCR based on current insn loc is really |
272 // -125 <= offset <= +130 (8 bit offset) | 294 // -125 <= offset <= +130 (8 bit offset) |
273 // NOTE: when we are called, we already have the opcode emitted | 295 // NOTE: when we are called, we already have the opcode emitted |
274 // so we only need to worry about the size of the operand | 296 // so we only need to worry about the size of the operand |
275 // hence the 2 and 3 magic numbers below instead of 3 and 4 | 297 // hence the 2 and 3 magic numbers below instead of 3 and 4 |
276 // (and that also avoids errors with two byte opcodes, etc) | 298 // (and that also avoids errors with two byte opcodes, etc) |
277 if (f8 || (!f16 && v >= -125 && v <= 130)) | 299 if (f8 || (!f16 && v >= -125 && v <= 130)) |
278 { | 300 { |
301 f8 = 1; | |
302 l -> fsize = 1; | |
279 *b1 = indir | 0x8C; | 303 *b1 = indir | 0x8C; |
280 v -= 2; | 304 if (as -> passnum == 1) |
305 v -= 2; | |
281 if (v < -128 || v > 127) | 306 if (v < -128 || v > 127) |
282 register_error(as, l, 2, "Byte overflow"); | 307 register_error(as, l, 2, "Byte overflow"); |
283 *b2 = v & 0xff; | 308 *b2 = v & 0xff; |
284 return; | 309 if (r != 0 && as -> passnum == 2) |
310 { | |
311 register_error(as, l, 2, "Illegal incomplete reference"); | |
312 } | |
313 goto finpcr; | |
285 } | 314 } |
286 | 315 |
287 // anything else is 16 bit offset | 316 // anything else is 16 bit offset |
288 // need 16 bit | 317 // need 16 bit |
318 | |
319 l -> fsize = 2; | |
289 *b1 = indir | 0x8D; | 320 *b1 = indir | 0x8D; |
290 v -= 3; | 321 if (as -> passnum == 1) |
322 v -= 3; | |
291 *b2 = (v >> 8) & 0xff; | 323 *b2 = (v >> 8) & 0xff; |
292 *b3 = v & 0xff; | 324 *b3 = v & 0xff; |
293 return; | 325 if (as -> passnum == 2 && r == 1) |
326 { | |
327 t = lwasm_expr_term_create_secbase(); | |
328 lwasm_expr_stack_push(l -> exprs[0], t); | |
329 lwasm_expr_term_free(t); | |
330 t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS); | |
331 lwasm_expr_stack_push(l -> exprs[0], t); | |
332 lwasm_expr_term_free(t); | |
333 } | |
334 | |
335 finpcr: | |
336 if (as -> passnum == 1) | |
337 { | |
338 // need to adjust the expression | |
339 if (l -> exprs[0]) | |
340 { | |
341 t = lwasm_expr_term_create_int(as -> addr + (f8 ? 2 : 3)); | |
342 lwasm_expr_stack_push(l -> exprs[0], t); | |
343 lwasm_expr_term_free(t); | |
344 t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS); | |
345 lwasm_expr_stack_push(l -> exprs[0], t); | |
346 lwasm_expr_term_free(t); | |
347 } | |
348 else | |
349 { | |
350 l -> exprvals[0] -= as -> addr + (f8 ? 2 : 3); | |
351 } | |
352 } | |
353 return; | |
354 } | |
355 if (fs16) | |
356 f16 = 1; | |
357 if (fs8) | |
358 f8 = 1; | |
359 | |
360 if (f8 && r != 0) | |
361 { | |
362 register_error(as, l, 2, "Illegal external or inter-section reference"); | |
363 r = 0; | |
364 v = 0; | |
294 } | 365 } |
295 | 366 |
296 // constant offset from PC (using PC as regular register :) ) | 367 // constant offset from PC (using PC as regular register :) ) |
297 // FIXME: handle external references intelligently | 368 // FIXME: handle external references intelligently |
298 if (rn == 6) | 369 if (rn == 6) |