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
This commit is contained in:
Peter Johnson 2006-06-10 08:00:14 +00:00
parent ad687bb34a
commit ff5b74bf5b
7 changed files with 160 additions and 188 deletions

View 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 */

View 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 */

View 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.

View 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,

View 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;

View 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;
}
/* Relative displacement; basically all object formats need non-byte
* for relocation here, so just do that.
*/
if (x86_ea->ea.disp.rel)
x86_ea->ea.disp.size = wordsize;
/* don't try to find out what size displacement we have if
* displen is known.
*/
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;
}
/* 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.
*/
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 */
x86_ea->ea.disp.size = wordsize;
x86_ea->valid_modrm = 1;
return 0;
}
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;
}
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?)
*/
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: 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!
*/
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@*/

View 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: