summaryrefslogtreecommitdiff
path: root/libyasm
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2009-07-24 19:01:35 +0000
committerPeter Johnson <peter@tortall.net>2009-07-24 19:01:35 +0000
commitdd7c64f68a26be4c6ca3e07c53c874c86b6d601b (patch)
tree97da4e929fb9a18ed94c196ecbcda26d080496e7 /libyasm
parentc2dce0a354d2274724ae61b14fb854861c0c618f (diff)
downloadyasm-dd7c64f68a26be4c6ca3e07c53c874c86b6d601b.tar.gz
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
Diffstat (limited to 'libyasm')
-rw-r--r--libyasm/tests/Makefile.inc2
-rw-r--r--libyasm/tests/value-shr-symexpr.asm6
-rw-r--r--libyasm/tests/value-shr-symexpr.hex8
-rw-r--r--libyasm/value.c54
4 files changed, 30 insertions, 40 deletions
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;