BR 2887108: Use overflow_ helper to catch inappropriate imm optimization
authorCyrill Gorcunov <gorcunov@gmail.com>
Sat, 31 Oct 2009 07:34:43 +0000 (10:34 +0300)
committerCyrill Gorcunov <gorcunov@gmail.com>
Sat, 31 Oct 2009 07:35:11 +0000 (10:35 +0300)
We should use overflow_ helpers before check if an immediate
operand fit a type range, otherwise we may loose high bits.

For example when we assemble the following instruction

imul eax,eax,0x10000

with -Ox passed we optimze it up to imm8 though it must be imm32.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
parser.c

index d0d660b750f54a1362c90ade082eb179f504564f..34fcf474ae54f779eb3fb8e49aa8b71c40323c24 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -855,11 +855,10 @@ restart_parse:
                 result->oprs[operand].segment = NO_SEG; /* don't care again */
                 result->oprs[operand].wrt = NO_SEG;     /* still don't care */
 
+                /* Be optimistic */
                 if(optimizing >= 0 && !(result->oprs[operand].type & STRICT))
-                {
-                    /* Be optimistic */
                     result->oprs[operand].type |= SBYTE16 | SBYTE32 | SBYTE64;
-                }
+
             } else if (is_reloc(value)) {       /* it's immediate */
                 result->oprs[operand].type |= IMMEDIATE;
                 result->oprs[operand].offset = reloc_value(value);
@@ -874,12 +873,14 @@ restart_parse:
                        int32_t v32 = (int32_t)v64;
                        int16_t v16 = (int16_t)v32;
 
-                       if (v64 >= -128 && v64 <= 127)
+                        if (v64 >= -128 && v64 <= 127)
                             result->oprs[operand].type |= SBYTE64;
-                       if (v32 >= -128 && v32 <= 127)
-                            result->oprs[operand].type |= SBYTE32;
-                       if (v16 >= -128 && v16 <= 127)
-                            result->oprs[operand].type |= SBYTE16;
+                        if (!overflow_signed(v64, sizeof(v32)))
+                            if (v32 >= -128 && v32 <= 127)
+                                result->oprs[operand].type |= SBYTE32;
+                        if (!overflow_signed(v64, sizeof(v16)))
+                            if (v16 >= -128 && v16 <= 127)
+                                result->oprs[operand].type |= SBYTE16;
                     }
                 }
             } else {            /* it's a register */