From ff5b74bf5bc4830c1f76d20bf6f825989bbb6e6f Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 10 Jun 2006 08:00:14 +0000 Subject: [PATCH] Fix all tests with miscomparing object files. Dramatically clean up some 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 | 1 + libyasm/value.c | 9 +- libyasm/value.h | 7 +- modules/arch/x86/x86arch.h | 5 +- modules/arch/x86/x86bc.c | 68 ++++++--------- modules/arch/x86/x86expr.c | 164 +++++++++++++++++-------------------- modules/arch/x86/x86id.c | 82 +++++++++---------- 7 files changed, 154 insertions(+), 182 deletions(-) diff --git a/libyasm/section.c b/libyasm/section.c index 4e11cf59..23d2a715 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -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 */ diff --git a/libyasm/value.c b/libyasm/value.c index 8e9f0a5b..94726d13 100644 --- a/libyasm/value.c +++ b/libyasm/value.c @@ -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 */ diff --git a/libyasm/value.h b/libyasm/value.h index 66320554..89a93aa8 100644 --- a/libyasm/value.h +++ b/libyasm/value.h @@ -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. diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index 79942e27..eb896544 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -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, diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index f65376f9..2aeca231 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -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; diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c index 8f62158c..21ae3deb 100644 --- a/modules/arch/x86/x86expr.c +++ b/modules/arch/x86/x86expr.c @@ -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@*/ diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 326c1780..59299936 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -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: -- 2.50.1