# HG changeset patch # User lost # Date 1231614315 0 # Node ID b6b1e79cc2778f4c0f6f14d0e69f2b6236abbcfd # Parent 8929e1ee99cf7616e37e2ff90f787f7dfb46a7d1 Moved indexed modes to new expression framework diff -r 8929e1ee99cf -r b6b1e79cc277 src/insn_indexed.c --- a/src/insn_indexed.c Sat Jan 10 07:18:59 2009 +0000 +++ b/src/insn_indexed.c Sat Jan 10 19:05:15 2009 +0000 @@ -63,17 +63,15 @@ { "", -1 } }; char stbuf[25]; - int i; - int f8 = 0, f16 = 0; - int rn; + int i, j, rn; + int f8 = 0, f16 = 0, f0 = 0; + int r, v; int indir = 0; - int rval; - int f0 = 0; - const char *p2; - lwasm_expr_stack_t *s; - + + // initialize output bytes *b1 = *b2 = *b3 = -1; + // fetch out operand for lookup for (i = 0; i < 24; i++) { if (*((*p) + i) && !isspace(*((*p) + i))) @@ -82,9 +80,10 @@ break; } stbuf[i] = '\0'; + + // now look up operand in "simple" table if (!*((*p) + i) || isspace(*((*p) + i))) { - int j; // do simple lookup for (j = 0; simpleindex[j].opstr[0]; j++) { @@ -98,21 +97,17 @@ return; } } - - // now we have the hard ones to work out here - - // if we've previously forced the sizes, make a note of it - if (l -> fsize == 1) - f8 = 1; - else if (l -> fsize == 2) - f16 = 1; - + + // now do the "hard" ones + + // is it indirect? if (**p == '[') { indir = 1; (*p)++; } + // look for a "," - all indexed modes have a "," except extended indir rn = 0; for (i = 0; (*p)[i] && !isspace((*p)[i]); i++) { @@ -122,37 +117,45 @@ break; } } - + + // if no "," and indirect, do extended indir if (!rn && indir) { // extended indir *b1 = 0x9f; *b2 = 0; *b3 = 0; - s = lwasm_evaluate_expr(as, l, *p, &p2); - if (!s) + + r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); + if (r < 0) { - register_error(as, l, 1, "Bad expression"); return; } - *p = p2; + if (**p != ']') { register_error(as, l, 1, "Bad operand"); return; } + (*p)++; - if (!lwasm_expr_is_constant(s)) + + if (r == 1 && as -> passnum == 2) { - register_error(as, l, 2, "Incomplete reference"); + l -> relocoff = as -> addr - l -> codeaddr + 1; } - rn = lwasm_expr_get_value(s); - lwasm_expr_stack_free(s); - *b2 = (rn >> 8) & 0xff; - *b3 = rn & 0xff; + + *b2 = (v >> 8) & 0xff; + *b3 = v & 0xff; return; } + // if we've previously forced the offset size, make a note of it + if (l -> fsize == 1) + f8 = 1; + else if (l -> fsize == 2) + f16 = 1; + if (**p == '<') { f8 = 1; @@ -170,52 +173,76 @@ } // now we have to evaluate the expression - s = lwasm_evaluate_expr(as, l, *p, &p2); - *p = p2; - if (!s) + r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0); + if (r < 0) { - register_error(as, l, 1, "Bad expression"); return; } - if (!lwasm_expr_is_constant(s)) + if (f8 && r != 0) { - register_error(as, l, 2, "Incomplete reference"); - if (!f8 && !f0) - { - f16 = 1; - l -> fsize = 2; - } + register_error(as, l, 2, "Illegal external or inter-section reference"); + r = 0; + v = 0; } - rval = lwasm_expr_get_value(s); - lwasm_expr_stack_free(s); - + // now look for a comma; if not present, explode if (*(*p)++ != ',') { // syntax error; force 0 bit *b1 = 00; + l -> fsize = 0; return; } // now get the register rn = lwasm_lookupreg3(regs, p); if (rn < 0) - goto reterr; - + { + *b1 = 0; + l -> fsize = 0; + register_error(as, l, 1, "Bad register"); + return; + } + if (indir) { if (**p != ']') - goto reterr; + { + register_error(as, l, 1, "Bad operand"); + l -> fsize = 0; + *b1 = 0; + return; + } else (*p)++; } - // nnnn,W is only 16 bit + // incomplete reference on pass 1 forces 16 bit + if (r == 1 && as -> passnum == 1) + { + f16 = 1; + l -> fsize = 2; + } + + // incomplete reference on pass 2 needs relocoff set + if (r == 1 && as -> passnum == 2) + { + l -> relocoff = as -> addr - l -> codeaddr + 1; + } + + // nnnn,W is only 16 bit (or 0 bit) if (rn == 4) { if (f8) - goto reterr; - if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && rval == 0) + { + register_error(as, l, 1, "n,W cannot be 8 bit"); + l -> fsize = 0; + *b1 = 0; + return; + } + // note: set f16 above for incomplete references + // also set reloc offset + if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && v == 0) { if (indir) *b1 = 0x90; @@ -223,21 +250,24 @@ *b1 = 0x8f; return; } + if (indir) *b1 = 0xb0; else *b1 = 0xcf; - *b2 = (rval >> 8) & 0xff; - *b3 = rval & 0xff; + *b2 = (v >> 8) & 0xff; + *b3 = v & 0xff; return; } + // set indir to correct bit value if (indir) indir = 0x10; - // PCR? redo v1, v2 relative to current address + // PCR? then we have PC relative addressing (like B??, LB??) if (rn == 5) { - rval -= as -> addr; + // FIXME: handle external references sensibly + v -= as -> addr; // we have a slight problem here // PCR based on current insn loc is really @@ -246,80 +276,85 @@ // so we only need to worry about the size of the operand // hence the 2 and 3 magic numbers below instead of 3 and 4 // (and that also avoids errors with two byte opcodes, etc) - if (f8 || (!f16 && rval >= -125 && rval <= 130)) + if (f8 || (!f16 && v >= -125 && v <= 130)) { *b1 = indir | 0x8C; - rval -= 2; - if (rval < -128 || rval > 127) + v -= 2; + if (v < -128 || v > 127) register_error(as, l, 2, "Byte overflow"); - *b2 = rval & 0xff; + *b2 = v & 0xff; return; } // anything else is 16 bit offset // need 16 bit *b1 = indir | 0x8D; - rval -= 3; - *b2 = (rval >> 8) & 0xff; - *b3 = rval & 0xff; + v -= 3; + *b2 = (v >> 8) & 0xff; + *b3 = v & 0xff; return; } - // constant offset from PC + // constant offset from PC (using PC as regular register :) ) + // FIXME: handle external references intelligently if (rn == 6) { - if (f8 || (!f16 && rval >= -128 && rval <= 127)) + if (f8 || (!f16 && v >= -128 && v <= 127)) { *b1 = indir | 0x8C; - if (rval < -128 || rval > 127) + if (v < -128 || v > 127) register_error(as, l, 2, "Byte overflow"); - *b2 = rval & 0xff; + *b2 = v & 0xff; return; } // everything else must be 16 bit // need 16 bit *b1 = indir | 0x8D; - *b2 = (rval >> 8) & 0xff; - *b3 = rval & 0xff; + *b2 = (v >> 8) & 0xff; + *b3 = v & 0xff; return; } // we only have to deal with x,y,u,s here - if (!f8 && !f16 && rval >= -16 && rval <= 15) + if (!f8 && !f16 && v >= -16 && v <= 15) { - if (rval == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) + // zero offset going to ,R? + if (v == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE)) { *b1 = rn << 5 | indir | 0x80 | 0x04; return; } - // we pick the smallest value here + + // no 5 bit on indirect if (indir) { f8 = 1; + l -> fsize = 1; goto no5bit; } - *b1 = rn << 5 | (rval & 0x1F); + + // 5 bit addressing + *b1 = rn << 5 | (v & 0x1F); return; } + no5bit: - if (f16 || (!f8 && (rval < -128 || rval > 127))) + if (f16 || (!f8 && (v < -128 || v > 127))) { // must be a 16 bit offset here *b1 = rn << 5 | indir | 0x80 | 0x09; - *b2 = (rval >> 8) & 0xff; - *b3 = rval & 0xff; + *b2 = (v >> 8) & 0xff; + *b3 = v & 0xff; return; } // if we're here, we have an 8 bit offset + // note: cannot get here if incomplete reference detected above *b1 = rn << 5 | indir | 0x80 | 0x08; - if (rval < -128 || rval > 127) + if (v < -128 || v > 127) register_error(as, l, 2, "Byte overflow"); - *b2 = rval & 0xff; - return; -reterr: - *b1 = 0; + *b2 = v & 0xff; return; }