# HG changeset patch # User William Astle # Date 1339284184 21600 # Node ID 6f2e18f1fe6734fee1b63d7b13141057911be044 # Parent 5d969517db7462ed8561c00f46ea100fe476a268 Improve autobranchlength pragma Improve detection of 8 bit relative offsets when autobranchlength is in effect. This should eliminate all but the most obscure corner cases where the 16 bit mode is selected when 8 bit mode will do. diff -r 5d969517db74 -r 6f2e18f1fe67 lwasm/insn_rel.c --- a/lwasm/insn_rel.c Sat Jun 09 16:25:19 2012 -0600 +++ b/lwasm/insn_rel.c Sat Jun 09 17:23:04 2012 -0600 @@ -50,6 +50,7 @@ lw_expr_t t, e1, e2; l -> lint = -1; + l -> maxlen = OPLEN(instab[l -> insn].ops[3]) + 2; if (CURPRAGMA(l, PRAGMA_AUTOBRANCHLENGTH) == 0) { l -> lint = instab[l -> insn].ops[1]; @@ -163,6 +164,23 @@ l -> lint = 16; } } + // size of 8-bit opcode + 8 bit offset + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + as -> pretendmax = 1; + lwasm_reduce_expr(as, e2); + as -> pretendmax = 0; + l -> len = -1; + if (lw_expr_istype(e2, lw_expr_type_int)) + { + // it reduced to an integer; is it in 8 bit range? + offs = lw_expr_intval(e2); + if (offs >= -128 && offs <= 127) + { + // fits in 8 bits with a worst case scenario + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + l -> lint = 8; + } + } lw_expr_destroy(e2); } if (lw_expr_istype(e, lw_expr_type_int)) diff -r 5d969517db74 -r 6f2e18f1fe67 lwasm/lwasm.c --- a/lwasm/lwasm.c Sat Jun 09 16:25:19 2012 -0600 +++ b/lwasm/lwasm.c Sat Jun 09 17:23:04 2012 -0600 @@ -125,9 +125,18 @@ case lwasm_expr_linelen: { line_t *cl = ptr; - if (cl -> len == -1) - return NULL; - return lw_expr_build(lw_expr_type_int, cl -> len); + if (cl -> len != -1) + return lw_expr_build(lw_expr_type_int, cl -> len); + + if (cl -> as -> pretendmax) + { + if (cl -> maxlen != 0) + { + fprintf(stderr, "Pretending max, len = %d\n", cl -> maxlen); + return lw_expr_build(lw_expr_type_int, cl -> maxlen); + } + } + return NULL; } break; diff -r 5d969517db74 -r 6f2e18f1fe67 lwasm/lwasm.h --- a/lwasm/lwasm.h Sat Jun 09 16:25:19 2012 -0600 +++ b/lwasm/lwasm.h Sat Jun 09 17:23:04 2012 -0600 @@ -156,6 +156,7 @@ lw_expr_t daddr; // data address of the line (os9 only) int len; // the "size" this line occupies (address space wise) (-1 if unknown) int dlen; // the data "size" this line occupies (-1 if unknown) + int maxlen; // maximum length; will be zero if not relevant int insn; // number of insn in insn table int symset; // set if the line symbol was consumed by the instruction char *sym; // symbol, if any, on the line @@ -271,6 +272,7 @@ int execaddr; // address from "end" int inmod; // inside an os9 module? int undefzero; // used for handling "condundefzero" + int pretendmax; // set if we need to pretend the instruction is max length unsigned char crc[3]; // crc accumulator int badsymerr; // throw error on undef sym if set