From: Peter Johnson Date: Fri, 24 Jul 2009 19:01:35 +0000 (-0000) Subject: Fix #178: Don't "distribute" shift right op. X-Git-Tag: v1.0.0~86 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dd7c64f68a26be4c6ca3e07c53c874c86b6d601b;p=yasm Fix #178: Don't "distribute" shift right op. This breaks horribly for things like (sym+511)>>9 in -f bin, as the result is zero instead of something more useful. Also don't check RHS for symbols; these will fall out later in the assembly process if they cannot be simplified. svn path=/trunk/yasm/; revision=2220 --- diff --git a/libyasm/tests/Makefile.inc b/libyasm/tests/Makefile.inc index 23f422bf..44cb5bc1 100644 --- a/libyasm/tests/Makefile.inc +++ b/libyasm/tests/Makefile.inc @@ -83,6 +83,8 @@ EXTRA_DIST += libyasm/tests/value-samesym.hex EXTRA_DIST += libyasm/tests/value-mask.asm EXTRA_DIST += libyasm/tests/value-mask.errwarn EXTRA_DIST += libyasm/tests/value-mask.hex +EXTRA_DIST += libyasm/tests/value-shr-symexpr.asm +EXTRA_DIST += libyasm/tests/value-shr-symexpr.hex check_PROGRAMS += bitvect_test check_PROGRAMS += floatnum_test diff --git a/libyasm/tests/value-shr-symexpr.asm b/libyasm/tests/value-shr-symexpr.asm new file mode 100644 index 00000000..988abbff --- /dev/null +++ b/libyasm/tests/value-shr-symexpr.asm @@ -0,0 +1,6 @@ +dw foo +dw (foo+((1<<9)-1)) +dw (foo+((1<<9)-1)) >> 9 +foo: +dw (bar+foo)>>(0+1) +bar: diff --git a/libyasm/tests/value-shr-symexpr.hex b/libyasm/tests/value-shr-symexpr.hex new file mode 100644 index 00000000..b3169287 --- /dev/null +++ b/libyasm/tests/value-shr-symexpr.hex @@ -0,0 +1,8 @@ +06 +00 +05 +02 +01 +00 +07 +00 diff --git a/libyasm/value.c b/libyasm/value.c index 180bf6af..a49daa03 100644 --- a/libyasm/value.c +++ b/libyasm/value.c @@ -336,54 +336,28 @@ value_finalize_scan(yasm_value *value, yasm_expr *e, * XXX: should rshift be an expr instead?? */ - /* Check for not allowed cases on RHS */ - switch (e->terms[1].type) { - case YASM_EXPR_REG: - case YASM_EXPR_FLOAT: - return 1; /* not legal */ - case YASM_EXPR_SYM: - return 1; - case YASM_EXPR_EXPR: - if (value_finalize_scan(value, e->terms[1].data.expn, - expr_precbc, 1)) - return 1; - break; - default: - break; - } + /* Check for single sym on LHS */ + if (e->terms[0].type != YASM_EXPR_SYM) + break; - /* Check for single sym and allowed cases on LHS */ - switch (e->terms[0].type) { - /*case YASM_EXPR_REG: ????? should this be illegal ????? */ - case YASM_EXPR_FLOAT: - return 1; /* not legal */ - case YASM_EXPR_SYM: - if (value->rel || ssym_not_ok) - return 1; - value->rel = e->terms[0].data.sym; - /* and replace with 0 */ - e->terms[0].type = YASM_EXPR_INT; - e->terms[0].data.intn = yasm_intnum_create_uint(0); - break; - case YASM_EXPR_EXPR: - /* recurse */ - if (value_finalize_scan(value, e->terms[0].data.expn, - expr_precbc, ssym_not_ok)) - return 1; - break; - default: - break; /* ignore */ - } + /* If we already have a sym, we can't take another one */ + if (value->rel || ssym_not_ok) + return 1; - /* Handle RHS */ - if (!value->rel) - break; /* no handling needed */ + /* RHS must be a positive integer */ if (e->terms[1].type != YASM_EXPR_INT) return 1; /* can't shift sym by non-constant integer */ shamt = yasm_intnum_get_uint(e->terms[1].data.intn); if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX) return 1; /* total shift would be too large */ + + /* Update value */ value->rshift += shamt; + value->rel = e->terms[0].data.sym; + + /* Replace symbol with 0 */ + e->terms[0].type = YASM_EXPR_INT; + e->terms[0].data.intn = yasm_intnum_create_uint(0); /* Just leave SHR in place */ break;