mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
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:
parent
ad687bb34a
commit
ff5b74bf5b
7 changed files with 160 additions and 188 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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@*/
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue