]> granicus.if.org Git - yasm/commitdiff
Fix #178: Don't "distribute" shift right op.
authorPeter Johnson <peter@tortall.net>
Fri, 24 Jul 2009 19:01:35 +0000 (19:01 -0000)
committerPeter Johnson <peter@tortall.net>
Fri, 24 Jul 2009 19:01:35 +0000 (19:01 -0000)
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

libyasm/tests/Makefile.inc
libyasm/tests/value-shr-symexpr.asm [new file with mode: 0644]
libyasm/tests/value-shr-symexpr.hex [new file with mode: 0644]
libyasm/value.c

index 23f422bf59198dee2beb42e89b398442bd9d5a91..44cb5bc18b09abf77609b08fccb43220a867ec7a 100644 (file)
@@ -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 (file)
index 0000000..988abbf
--- /dev/null
@@ -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 (file)
index 0000000..b316928
--- /dev/null
@@ -0,0 +1,8 @@
+06 
+00 
+05 
+02 
+01 
+00 
+07 
+00 
index 180bf6af853f55ff76c50db9046870f0a4c97c31..a49daa03fad2faceff7442d324749e267366b74a 100644 (file)
@@ -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;