]> granicus.if.org Git - yasm/commitdiff
Fix all tests with miscomparing object files. Dramatically clean up some
authorPeter Johnson <peter@tortall.net>
Sat, 10 Jun 2006 08:00:14 +0000 (08:00 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 10 Jun 2006 08:00:14 +0000 (08:00 -0000)
x86 code (mainly x86_checkea_calc_displen(), and parts of
x86_bc_insn_calc_len()) to use new yasm_value_get_intnum().
Allow NULL to be passed as bc to yasm_value_get_intnum() to prevent
calculation of PC-relative values (returning NULL instead).

svn path=/branches/new-optimizer/; revision=1561

libyasm/section.c
libyasm/value.c
libyasm/value.h
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
modules/arch/x86/x86id.c

index 4e11cf592d0881a17c7c8c0a6763d999e98024ea..23d2a715cc8cc65c3c8e1f98fdb92cae1bdd9b29 100644 (file)
@@ -207,6 +207,7 @@ yasm_object_create_absolute(yasm_object *object, yasm_expr *start,
     STAILQ_INIT(&s->bcs);
     bc = yasm_bc_create_common(NULL, NULL, 0);
     bc->section = s;
+    bc->offset = 0;
     STAILQ_INSERT_TAIL(&s->bcs, bc, link);
 
     /* Initialize relocs */
index 8e9f0a5ba7ba9542c2f08569b2b719479eceac67..94726d136ce16b87bf3f688304966ee3e87750de 100644 (file)
@@ -478,17 +478,17 @@ yasm_value_finalize(yasm_value *value)
 }
 
 yasm_intnum *
-yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc)
+yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
 {
     /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
     /*@only@*/ yasm_intnum *outval;
     int sym_local;
 
     if (value->abs) {
-       /* Handle integer expressions, if non-integer go ahead and return
+       /* Handle integer expressions, if non-integer or too complex, return
         * NULL.
         */
-       intn = yasm_expr_get_intnum(&value->abs, 1);
+       intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
        if (!intn)
            return NULL;
     }
@@ -500,6 +500,9 @@ yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc)
        /*@dependent@*/ yasm_bytecode *rel_prevbc;
        unsigned long dist;
 
+       if (!bc)
+           return NULL;    /* Can't calculate relative value */
+
        sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
        if (value->wrt || value->seg_of || value->section_rel || !sym_local)
            return NULL;    /* we can't handle SEG, WRT, or external symbols */
index 66320554c8b9eddcb0f082cd01e3b5fb484f80b3..89a93aa8ff97d79626df26989f7b0c391111ee12 100644 (file)
@@ -103,13 +103,16 @@ int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
 /** Get value if absolute or PC-relative section-local relative.  Returns NULL
  * otherwise.
  * \param value                value
- * \param bc           current bytecode (for PC-relative calculation)
+ * \param bc           current bytecode (for PC-relative calculation); if
+ *                     NULL, NULL is returned for PC-relative values.
+ * \param calc_bc_dist if nonzero, calculates bytecode distances in absolute
+ *                     portion of value
  * \note Adds in value.rel (correctly) if PC-relative and in the same section
  *       as bc (and there is no WRT or SEG).
  * \return Intnum if can be resolved to integer value, otherwise NULL.
  */
 /*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum
-    (yasm_value *value, yasm_bytecode *bc);
+    (yasm_value *value, /*@null@*/ yasm_bytecode *bc, int calc_bc_dist);
 
 /** Output value if constant or PC-relative section-local.  This should be
  * used from objfmt yasm_output_value_func() functions.
index 79942e270442a676ac0c8ae8d224343c8de1e759..eb896544aa5c25c4b2924923bd950bb6ac00d813 100644 (file)
@@ -206,8 +206,9 @@ typedef struct x86_insn {
 
        /* Instructions that take a sign-extended imm8 as well as imm values
         * (eg, the arith instructions and a subset of the imul instructions)
-        * should set this and put the imm8 form in the second (and possibly
-        * third) byte of the opcode.
+        * should set this and put the imm8 form as the "normal" opcode (in
+        * the first one or two bytes) and non-imm8 form in the second or
+        * third byte of the opcode.
         */
        X86_POSTOP_SIGNEXT_IMM8,
 
index f65376f9f5cccd1996c851ea89458b399861aae3..2aeca231546817142f5bc32fbc32241f8b2b2b2a 100644 (file)
@@ -529,14 +529,14 @@ x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
            /* failed, don't bother checking rest of insn */
            return -1;
 
-       if (x86_ea->ea.disp.size == 0) {
+       if (x86_ea->ea.disp.size == 0 && x86_ea->ea.need_nonzero_len) {
            /* Handle unknown case, default to byte-sized and set as
             * critical expression.
             */
            bc->len += 1;
            add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127);
        } else
-           bc->len + x86_ea->ea.disp.size/8;
+           bc->len += x86_ea->ea.disp.size/8;
 
        /* Handle address16 postop case */
        if (insn->postop == X86_POSTOP_ADDRESS16)
@@ -548,47 +548,40 @@ x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
     }
 
     if (imm) {
-       yasm_intnum *zero = yasm_intnum_create_uint(0);
-       const yasm_intnum *num = zero;
        unsigned int immlen = imm->val.size;
-       long val;
-
-       if (imm->val.abs)
-           num = yasm_expr_get_intnum(&imm->val.abs, 0);
 
        /* TODO: check imm->len vs. sized len from expr? */
 
        /* Handle signext_imm8 postop special-casing */
        if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
-           if (imm->val.rel || num) {
-               if (imm->val.rel)
-                   val = 1000; /* has relative portion, don't collapse */
-               else
-                   val = yasm_intnum_get_int(num);
-               if (val >= -128 && val <= 127) {
+           /*@null@*/ /*@only@*/ yasm_intnum *num;
+           num = yasm_value_get_intnum(&imm->val, NULL, 0);
+
+           if (!num) {
+               /* Unknown; default to byte form and set as critical
+                * expression.
+                */
+               immlen = 8;
+               add_span(add_span_data, bc, 2, &imm->val, -128, 127);
+           } else {
+               if (yasm_intnum_in_range(num, -128, 127)) {
                    /* We can use the sign-extended byte form: shorten
                     * the immediate length to 1 and make the byte form
                     * permanent.
                     */
                    imm->val.size = 8;
                    immlen = 8;
-                   if (insn->opcode.opcode[2] != 0) {
-                       insn->opcode.opcode[1] = insn->opcode.opcode[2];
-                       insn->opcode.len++;
-                   }
+               } else {
+                   /* We can't.  Copy over the word-sized opcode. */
+                   insn->opcode.opcode[0] =
+                       insn->opcode.opcode[insn->opcode.len];
+                   insn->opcode.len = 1;
                }
                insn->postop = X86_POSTOP_NONE;
-           } else {
-               /* Unknown; default to byte form and set as critical
-                * expression.
-                */
-               immlen = 8;
-               add_span(add_span_data, bc, 2, &imm->val, -128, 127);
            }
+           yasm_intnum_destroy(num);
        }
 
-       yasm_intnum_destroy(zero);
-
        bc->len += immlen/8;
     }
 
@@ -626,8 +619,13 @@ x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
 
     if (imm && imm->val.abs) {
        if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
-           bc->len--;
+           /* Update bc->len for new opcode and immediate size */
+           bc->len -= insn->opcode.len;
            bc->len += imm->val.size/8;
+
+           /* Change to the word-sized opcode */
+           insn->opcode.opcode[0] = insn->opcode.opcode[insn->opcode.len];
+           insn->opcode.len = 1;
            insn->postop = X86_POSTOP_NONE;
        }
     }
@@ -818,24 +816,8 @@ x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
        }
 
        if (x86_ea->ea.need_disp) {
-           x86_effaddr eat = *x86_ea;  /* structure copy */
-           unsigned char addrsize = insn->common.addrsize;
            unsigned int disp_len = x86_ea->ea.disp.size/8;
 
-           eat.valid_modrm = 0;    /* force checkea to actually run */
-
-           if (x86_ea->ea.disp.abs) {
-               /* Call checkea() to simplify the registers out of the
-                * displacement.  Throw away all of the return values except
-                * for the modified expr.
-                */
-               if (yasm_x86__expr_checkea
-                   (&eat, &addrsize, insn->common.mode_bits,
-                    insn->postop == X86_POSTOP_ADDRESS16, &insn->rex))
-                   yasm_internal_error(N_("checkea failed"));
-               x86_ea->ea.disp.abs = eat.ea.disp.abs;
-           }
-
            if (x86_ea->ea.disp.ip_rel) {
                /* Adjust relative displacement to end of bytecode */
                /*@only@*/ yasm_intnum *delta;
index 8f62158c5ae8f7b1ce3835cbce1a738133c5dd91..21ae3debe903c5b74e3a970cb34557d31b7aceb6 100644 (file)
@@ -404,8 +404,7 @@ static int
 x86_checkea_calc_displen(x86_effaddr *x86_ea, unsigned int wordsize, int noreg,
                         int dispreq)
 {
-    /*@null@*/ const yasm_intnum *intn = NULL;
-    long dispval;
+    /*@null@*/ /*@only@*/ yasm_intnum *num;
 
     x86_ea->valid_modrm = 0;   /* default to not yet valid */
 
@@ -416,124 +415,107 @@ x86_checkea_calc_displen(x86_effaddr *x86_ea, unsigned int wordsize, int noreg,
         * appropriately and we're done with the ModRM byte.
         */
        case 8:
-           /* Byte is not valid override in noreg case; fix it. */
+           /* Byte is only a valid override if there are registers in the
+            * EA.  With no registers, we must have a 16/32 value.
+            */
            if (noreg) {
-               x86_ea->ea.disp.size = 0;
                yasm_warn_set(YASM_WARN_GENERAL,
                              N_("invalid displacement size; fixed"));
+               x86_ea->ea.disp.size = wordsize;
            } else
                x86_ea->modrm |= 0100;
            x86_ea->valid_modrm = 1;
-           break;
+           return 0;
        case 16:
        case 32:
+           /* Don't allow changing displacement different from BITS setting
+            * directly; require an address-size override to change it.
+            */
            if (wordsize != x86_ea->ea.disp.size) {
                yasm_error_set(YASM_ERROR_VALUE,
                    N_("invalid effective address (displacement size)"));
                return 1;
            }
-           /* 2/4 is not valid override in noreg case; fix it. */
-           if (noreg) {
-               if (wordsize != x86_ea->ea.disp.size)
-                   yasm_warn_set(YASM_WARN_GENERAL,
-                                 N_("invalid displacement size; fixed"));
-               x86_ea->ea.disp.size = 0;
-           } else
+           if (!noreg)
                x86_ea->modrm |= 0200;
            x86_ea->valid_modrm = 1;
-           break;
+           return 0;
        default:
            /* we shouldn't ever get any other size! */
            yasm_internal_error(N_("strange EA displacement size"));
     }
 
-    if (x86_ea->ea.disp.size == 0) {
-       /* the displacement length hasn't been forced (or the forcing wasn't
-        * valid), try to determine what it is.
+    /* The displacement length hasn't been forced (or the forcing wasn't
+     * valid), try to determine what it is.
+     */
+    if (noreg) {
+       /* No register in ModRM expression, so it must be disp16/32,
+        * and as the Mod bits are set to 0 by the caller, we're done
+        * with the ModRM byte.
         */
-       if (noreg) {
-           /* no register in ModRM expression, so it must be disp16/32,
-            * and as the Mod bits are set to 0 by the caller, we're done
-            * with the ModRM byte.
-            */
-           x86_ea->ea.disp.size = wordsize;
-           x86_ea->valid_modrm = 1;
-           return 0;
-       } else if (dispreq) {
-           /* for BP/EBP, there *must* be a displacement value, but we
-            * may not know the size (8 or 16/32) for sure right now.
-            */
-           x86_ea->ea.need_nonzero_len = 1;
-           x86_ea->modrm |= 0100;
-           x86_ea->valid_modrm = 1;
-           return 0;
-       }
+       x86_ea->ea.disp.size = wordsize;
+       x86_ea->valid_modrm = 1;
+       return 0;
+    }
 
-       /* Relative displacement; basically all object formats need non-byte
-        * for relocation here, so just do that.
+    if (dispreq) {
+       /* for BP/EBP, there *must* be a displacement value, but we
+        * may not know the size (8 or 16/32) for sure right now.
         */
-       if (x86_ea->ea.disp.rel)
-           x86_ea->ea.disp.size = wordsize;
+       x86_ea->ea.need_nonzero_len = 1;
+    }
 
-       /* don't try to find out what size displacement we have if
-        * displen is known.
+    if (x86_ea->ea.disp.rel) {
+       /* Relative displacement; basically all object formats need non-byte
+        * for relocation here, so just do that. (TODO: handle this
+        * differently?)
         */
-       if (x86_ea->ea.disp.size != 0) {
-           if (x86_ea->ea.disp.size == 8)
-               x86_ea->modrm |= 0100;
-           else
-               x86_ea->modrm |= 0200;
-           x86_ea->valid_modrm = 1;
-           return 0;
-       }
+       x86_ea->ea.disp.size = wordsize;
+       x86_ea->modrm |= 0200;
+       x86_ea->valid_modrm = 1;
+       return 0;
+    }
 
-       /* At this point there's 3 possibilities for the displacement:
-        *  - None (if =0)
-        *  - signed 8 bit (if in -128 to 127 range)
-        *  - 16/32 bit (word size)
-        * For now, check intnum value right now; if it's not 0,
-        * assume 8 bit and set up for allowing 16 bit later.
-        * FIXME: this should really set up two thresholds, one for 8-bit
-        * expansion and one for 16-bit expansion.  The complex expression
-        * equaling zero is probably a rare case, so we ignore it for now.
+    /* At this point there's 3 possibilities for the displacement:
+     *  - None (if =0)
+     *  - signed 8 bit (if in -128 to 127 range)
+     *  - 16/32 bit (word size)
+     * For now, check intnum value right now; if it's not 0,
+     * assume 8 bit and set up for allowing 16 bit later.
+     * FIXME: The complex expression equaling zero is probably a rare case,
+     * so we ignore it for now.
+     */
+    num = yasm_value_get_intnum(&x86_ea->ea.disp, NULL, 0);
+    if (!num) {
+       /* Still has unknown values. */
+       x86_ea->ea.need_nonzero_len = 1;
+       x86_ea->modrm |= 0100;
+       x86_ea->valid_modrm = 1;
+       return 0;
+    }
+
+    /* Figure out what size displacement we will have. */
+    if (yasm_intnum_is_zero(num) && !x86_ea->ea.need_nonzero_len) {
+       /* If we know that the displacement is 0 right now,
+        * go ahead and delete the expr and make it so no
+        * displacement value is included in the output.
+        * The Mod bits of ModRM are set to 0 above, and
+        * we're done with the ModRM byte!
         */
-       if (x86_ea->ea.disp.abs &&
-           !(intn = yasm_expr_get_intnum(&x86_ea->ea.disp.abs, 0))) {
-           /* expr still has unknown values: treat like BP/EBP above */
-           x86_ea->ea.need_nonzero_len = 1;
-           x86_ea->modrm |= 0100;
-           x86_ea->valid_modrm = 1;
-           return 0;
-       }       
-
-       if (intn)
-           dispval = yasm_intnum_get_int(intn);
-       else
-           dispval = 0;
-
-       /* Figure out what size displacement we will have. */
-       if (!x86_ea->ea.need_nonzero_len && dispval == 0) {
-           /* if we know that the displacement is 0 right now,
-            * go ahead and delete the expr and make it so no
-            * displacement value is included in the output.
-            * The Mod bits of ModRM are set to 0 above, and
-            * we're done with the ModRM byte!
-            */
-           yasm_expr_destroy(x86_ea->ea.disp.abs);
-           x86_ea->ea.disp.abs = NULL;
-           x86_ea->ea.need_disp = 0;
-       } else if (dispval >= -128 && dispval <= 127) {
-           /* It fits into a signed byte */
-           x86_ea->ea.disp.size = 8;
-           x86_ea->modrm |= 0100;
-       } else {
-           /* It's a 16/32-bit displacement */
-           x86_ea->ea.disp.size = wordsize;
-           x86_ea->modrm |= 0200;
-       }
-       x86_ea->valid_modrm = 1;        /* We're done with ModRM */
+       yasm_value_delete(&x86_ea->ea.disp);
+       x86_ea->ea.need_disp = 0;
+    } else if (yasm_intnum_in_range(num, -128, 127)) {
+       /* It fits into a signed byte */
+       x86_ea->ea.disp.size = 8;
+       x86_ea->modrm |= 0100;
+    } else {
+       /* It's a 16/32-bit displacement */
+       x86_ea->ea.disp.size = wordsize;
+       x86_ea->modrm |= 0200;
     }
+    x86_ea->valid_modrm = 1;   /* We're done with ModRM */
 
+    yasm_intnum_destroy(num);
     return 0;
 }
 /*@=nullstate@*/
index 326c17808ec0eff18346509a66c9903bdb854bb5..5929993690d966238c2d4dfd03336597d550fbb2 100644 (file)
@@ -53,7 +53,7 @@ RCSID("$Id$");
 #define MOD_Imm8    (1UL<<9)   /* Parameter is included as immediate byte */
 #define MOD_AdSizeR (1UL<<10)  /* Parameter replaces addrsize (jmp only) */
 #define MOD_DOpS64R (1UL<<11)  /* Parameter replaces default 64-bit opersize */
-#define MOD_Op2AddSp (1UL<<12) /* Parameter is added as "spare" to opcode byte 2 */
+#define MOD_Op1AddSp (1UL<<12) /* Parameter is added as "spare" to opcode byte 2 */
 
 /* Modifiers that aren't: these are used with the GAS parser to indicate
  * special cases.
@@ -154,7 +154,7 @@ RCSID("$Id$");
  * indicate postponed actions.
  *  - 3 bits = postponed action:
  *             0 = none
- *             1 = large imm16/32 that can become a sign-extended imm8.
+ *             1 = sign-extended imm8 that could expand to a large imm16/32
  *             2 = could become a short opcode mov with bits=64 and a32 prefix
  *             3 = forced 16-bit address size (override ignored, no prefix)
  *             4 = large imm64 that can become a sign-extended imm32.
@@ -223,7 +223,7 @@ RCSID("$Id$");
 #define OPA_MASK       (0xFUL<<13)
 
 #define OPAP_None      (0UL<<17)
-#define OPAP_SImm8Avail        (1UL<<17)
+#define OPAP_SImm8     (1UL<<17)
 #define OPAP_ShortMov  (2UL<<17)
 #define OPAP_A16       (3UL<<17)
 #define OPAP_SImm32Avail (4UL<<17)
@@ -623,17 +623,17 @@ static const x86_insn_info push_insn[] = {
       {OPT_Imm|OPS_32|OPA_SImm, 0, 0} },
     { CPU_Any, MOD_GasOnly|MOD_GasSufB, 0, 64, 0, 1, {0x6A, 0, 0}, 0, 1,
       {OPT_Imm|OPS_8|OPS_Relaxed|OPA_SImm, 0, 0} },
-    { CPU_Any, MOD_GasOnly|MOD_GasSufW, 16, 64, 0, 1, {0x68, 0x6A, 0}, 0, 1,
-      {OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0, 0} },
+    { CPU_Any, MOD_GasOnly|MOD_GasSufW, 16, 64, 0, 1, {0x6A, 0x68, 0}, 0, 1,
+      {OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0, 0} },
     { CPU_386|CPU_Not64, MOD_GasOnly|MOD_GasSufL, 32, 0, 0, 1,
-      {0x68, 0x6A, 0}, 0, 1,
-      {OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0, 0} },
+      {0x6A, 0x68, 0}, 0, 1,
+      {OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0, 0} },
     { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 64, 0, 1,
-      {0x68, 0x6A, 0}, 0, 1,
-      {OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0, 0} },
+      {0x6A, 0x68, 0}, 0, 1,
+      {OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8, 0, 0} },
     { CPU_Any|CPU_Not64, MOD_GasIllegal, 0, 0, 0, 1,
-      {0x68, 0x6A, 0}, 0, 1,
-      {OPT_Imm|OPS_BITS|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0, 0} },
+      {0x6A, 0x68, 0}, 0, 1,
+      {OPT_Imm|OPS_BITS|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0, 0} },
     { CPU_Not64, 0, 0, 0, 0, 1, {0x0E, 0, 0}, 0, 1,
       {OPT_CS|OPS_Any|OPA_None, 0, 0} },
     { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x0E, 0, 0}, 0, 1,
@@ -843,22 +843,22 @@ static const x86_insn_info arith_insn[] = {
       {OPT_Areg|OPS_8|OPA_None, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} },
     { CPU_Any, MOD_Op0Add|MOD_GasIllegal, 16, 0, 0, 1, {0x05, 0, 0}, 0, 2,
       {OPT_Areg|OPS_16|OPA_None, OPT_Imm|OPS_16|OPA_Imm, 0} },
-    { CPU_Any, MOD_Op0Add|MOD_Op2AddSp|MOD_GasSufW, 16, 0, 0, 1,
-      {0x05, 0x83, 0xC0}, 0, 2,
+    { CPU_Any, MOD_Op2Add|MOD_Op1AddSp|MOD_GasSufW, 16, 0, 0, 2,
+      {0x83, 0xC0, 0x05}, 0, 2,
       {OPT_Areg|OPS_16|OPA_None,
-       OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+       OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
     { CPU_386, MOD_Op0Add|MOD_GasIllegal, 32, 0, 0, 1, {0x05, 0, 0}, 0, 2,
       {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPA_Imm, 0} },
-    { CPU_386, MOD_Op0Add|MOD_Op2AddSp|MOD_GasSufL, 32, 0, 0, 1,
-      {0x05, 0x83, 0xC0}, 0, 2,
+    { CPU_386, MOD_Op2Add|MOD_Op1AddSp|MOD_GasSufL, 32, 0, 0, 2,
+      {0x83, 0xC0, 0x05}, 0, 2,
       {OPT_Areg|OPS_32|OPA_None,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
     { CPU_Hammer|CPU_64, MOD_Op0Add|MOD_GasIllegal, 64, 0, 0, 1, {0x05, 0, 0},
       0, 2, {OPT_Areg|OPS_64|OPA_None, OPT_Imm|OPS_32|OPA_Imm, 0} },
-    { CPU_Hammer|CPU_64, MOD_Op0Add|MOD_Op2AddSp|MOD_GasSufQ, 64, 0, 0, 1,
-      {0x05, 0x83, 0xC0}, 0,
+    { CPU_Hammer|CPU_64, MOD_Op2Add|MOD_Op1AddSp|MOD_GasSufQ, 64, 0, 0, 2,
+      {0x83, 0xC0, 0x05}, 0,
       2, {OPT_Areg|OPS_64|OPA_None,
-         OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+         OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
 
     /* Also have forced-size forms to override the optimization */
     { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2,
@@ -869,23 +869,23 @@ static const x86_insn_info arith_insn[] = {
       {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} },
     { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasIllegal, 16, 0, 0, 1, {0x81, 0, 0}, 0,
       2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_16|OPA_Imm, 0} },
-    { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0x81, 0x83, 0}, 0,
+    { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0x83, 0x81, 0}, 0,
       2, {OPT_RM|OPS_16|OPA_EA,
-         OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+         OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
     { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x83, 0, 0}, 0, 2,
       {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} },
     { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasIllegal, 32, 0, 0, 1, {0x81, 0, 0}, 0,
       2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} },
-    { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x81, 0x83, 0}, 0,
+    { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x83, 0x81, 0}, 0,
       2, {OPT_RM|OPS_32|OPA_EA,
-         OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+         OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
     { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1,
       {0x83, 0, 0}, 0, 2,
       {OPT_RM|OPS_64|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} },
     { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1,
-      {0x81, 0x83, 0}, 0, 2,
+      {0x83, 0x81, 0}, 0, 2,
       {OPT_RM|OPS_64|OPA_EA,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} },
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8, 0} },
     { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1,
       {0x81, 0, 0}, 0, 2,
       {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} },
@@ -1048,25 +1048,25 @@ static const x86_insn_info imul_insn[] = {
     { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 2,
       {OPT_Reg|OPS_64|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} },
 
-    { CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
+    { CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3,
       {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA,
-       OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
-    { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
+       OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8} },
+    { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3,
       {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
-    { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 3,
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8} },
+    { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3,
       {OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail} },
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8} },
 
-    { CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
+    { CPU_186, MOD_GasSufW, 16, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2,
       {OPT_Reg|OPS_16|OPA_SpareEA,
-       OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} },
-    { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
+       OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm|OPAP_SImm8, 0} },
+    { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2,
       {OPT_Reg|OPS_32|OPA_SpareEA,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} },
-    { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x69, 0x6B, 0}, 0, 2,
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8, 0} },
+    { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2,
       {OPT_Reg|OPS_64|OPA_SpareEA,
-       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0} }
+       OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8, 0} }
 };
 
 /* Shifts - standard */
@@ -2712,8 +2712,8 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
        insn->def_opersize_64 = (unsigned char)(mod_data & 0xFF);
        mod_data >>= 8;
     }
-    if (info->modifiers & MOD_Op2AddSp) {
-       insn->opcode.opcode[2] += (unsigned char)(mod_data & 0xFF)<<3;
+    if (info->modifiers & MOD_Op1AddSp) {
+       insn->opcode.opcode[1] += (unsigned char)(mod_data & 0xFF)<<3;
        /*mod_data >>= 8;*/
     }
 
@@ -2845,7 +2845,7 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc,
            switch ((int)(info->operands[i] & OPAP_MASK)) {
                case OPAP_None:
                    break;
-               case OPAP_SImm8Avail:
+               case OPAP_SImm8:
                    insn->postop = X86_POSTOP_SIGNEXT_IMM8;
                    break;
                case OPAP_ShortMov: