mirror of
https://github.com/netwide-assembler/nasm
synced 2026-08-26 16:23:04 -04:00
WIP: more matching and template work
Further work on a better matching system. Still a work in progress, however. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
parent
f114a6276e
commit
75f6f4cdb2
34 changed files with 486 additions and 379 deletions
108
asm/assemble.c
108
asm/assemble.c
|
|
@ -113,6 +113,7 @@ static uint32_t rexflags(int, opflags_t, uint32_t);
|
|||
static uint32_t op_rexflags(const operand *, uint32_t);
|
||||
static uint32_t op_evexflags(const operand *, uint32_t);
|
||||
static void add_asp(insn *);
|
||||
static void set_initial_opsize(insn *);
|
||||
|
||||
static int process_ea(operand *input, int rfield, opflags_t rflags,
|
||||
insn *ins, enum ea_type expected,
|
||||
|
|
@ -945,6 +946,9 @@ int64_t assemble(insn *instruction)
|
|||
/* Check to see if we need an address-size prefix */
|
||||
add_asp(instruction);
|
||||
|
||||
/* Set default/prefix-controlled operand size */
|
||||
set_initial_opsize(instruction);
|
||||
|
||||
m = find_match(&temp, instruction);
|
||||
|
||||
if (m >= MOK_GOOD) {
|
||||
|
|
@ -1785,7 +1789,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||
}
|
||||
|
||||
case 0334:
|
||||
ins->rex |= REX_L;
|
||||
ins->rex |= REX_L; /* Ignored in 64-bit mode */
|
||||
break;
|
||||
|
||||
case 0335:
|
||||
|
|
@ -2934,11 +2938,15 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
unsigned int arflag;
|
||||
unsigned int armask, smmask;
|
||||
bool if_anysize, if_sx;
|
||||
opflags_t arsize, smsize;
|
||||
opflags_t opsize, arsize, smsize;
|
||||
opflags_t isize[MAX_OPERANDS]; /* Adjusted instruction operand sizes */
|
||||
opflags_t tsize[MAX_OPERANDS]; /* Adjusted template operand sizes */
|
||||
opflags_t itype[MAX_OPERANDS]; /* Adjusted instruction flags */
|
||||
|
||||
/* Jump size/type declarators are more like types than sizes */
|
||||
const opflags_t jsize_mask = NEAR|FAR|SHORT|ABS;
|
||||
const opflags_t msize_mask = SIZE_MASK & ~jsize_mask;
|
||||
|
||||
/*
|
||||
* Check the opcode
|
||||
*/
|
||||
|
|
@ -3012,7 +3020,7 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
const struct operand * const op = &ins->oprs[i];
|
||||
const opflags_t ttype = itemp->opd[i];
|
||||
|
||||
isize[i] = op->type & SIZE_MASK;
|
||||
isize[i] = op->type & msize_mask;
|
||||
itype[i] = op->type - isize[i];
|
||||
if (op->type & ~ttype & (COLON | TO))
|
||||
return MERR_INVALOP;
|
||||
|
|
@ -3020,6 +3028,15 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
return MERR_WRONGIMM;
|
||||
}
|
||||
|
||||
/* "Default" operand size (from mode and prefixes only) */
|
||||
opsize = mode_to_op(ins->op_size);
|
||||
if (itemp_has(itemp, IF_NWSIZE) && bits == 64 && opsize == BITS32)
|
||||
opsize = BITS64;
|
||||
|
||||
/* Some key flags */
|
||||
if_anysize = itemp_has(itemp, IF_ANYSIZE);
|
||||
if_sx = itemp_has(itemp, IF_SX);
|
||||
|
||||
/*
|
||||
* Compare various operand flags that don't depend on sizes,
|
||||
* and compute the "true" template operand sizes.
|
||||
|
|
@ -3030,8 +3047,8 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
const decoflags_t ideco = itemp->deco[i];
|
||||
const bool is_broadcast = deco & BRDCAST_MASK;
|
||||
|
||||
if (!is_broadcast) {
|
||||
tsize[i] = ttype & SIZE_MASK;
|
||||
if (likely(!is_broadcast)) {
|
||||
tsize[i] = ttype & msize_mask;
|
||||
} else {
|
||||
const decoflags_t ideco_brsize = ideco & BRSIZE_MASK;
|
||||
|
||||
|
|
@ -3048,12 +3065,32 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
tsize[i] = 0; /* Is this even possible? */
|
||||
}
|
||||
|
||||
/* Handle implied SHORT or NEAR */
|
||||
if (unlikely(ttype & (NEAR|SHORT))) {
|
||||
if ((ttype & (NEAR|SHORT)) == (NEAR|SHORT)) {
|
||||
/* Only a short form exists; allow both NEAR and SHORT */
|
||||
if (!(itype[i] & (FAR|ABS)))
|
||||
itype[i] |= NEAR|SHORT;
|
||||
} else if ((itype[i] & SHORT) || isize[i] == BITS8) {
|
||||
/* An explicit SHORT or BITS8 cancel NEAR; are synonyms */
|
||||
itype[i] &= ~NEAR;
|
||||
if (!isize[i])
|
||||
isize[i] = BITS8;
|
||||
} else if (!(itype[i] & (FAR|ABS|SHORT))) {
|
||||
/* NEAR is implicit unless otherwise specified */
|
||||
itype[i] |= ttype & NEAR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if we need to coerce an explicitly sized immediate */
|
||||
if (unlikely(itype[i] & ttype & IMMEDIATE)) {
|
||||
/*
|
||||
* If this is an *explicitly* sized immediate,
|
||||
* allow it to match an extending pattern.
|
||||
*
|
||||
* Handle sizing of SHORT/NEAR here, too.
|
||||
*/
|
||||
|
||||
switch (isize[i]) {
|
||||
case BITS8:
|
||||
if (ttype & BYTEEXTMASK) {
|
||||
|
|
@ -3077,7 +3114,7 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
itype[i] |= SDWORD;
|
||||
}
|
||||
|
||||
if (ttype & ~itype[i] & ~(SIZE_MASK|REGSET_MASK))
|
||||
if (ttype & ~itype[i] & ~(msize_mask|REGSET_MASK))
|
||||
return MERR_INVALOP;
|
||||
|
||||
if (~ideco & deco & OPMASK_MASK)
|
||||
|
|
@ -3098,35 +3135,33 @@ static enum match_result matches(const struct itemplate * const itemp,
|
|||
|
||||
nasm_static_assert(SIZE_SHIFT >= IF_SB);
|
||||
nasm_static_assert((BITS8 >> SIZE_SHIFT) == 1);
|
||||
arsize = (arflag & (IFM_SB|IFM_SW|IFM_SD|IFM_SQ|
|
||||
IFM_ST|IFM_SO|IFM_SY|IFM_SZ))
|
||||
<< (SIZE_SHIFT - IF_SB);
|
||||
arsize = (arflag & IF_TSMASK) << (SIZE_SHIFT - IF_SB);
|
||||
|
||||
if (arflag & IFM_SIZE)
|
||||
arsize = mode_to_op(bits);
|
||||
|
||||
if_anysize = itemp_has(itemp, IF_ANYSIZE);
|
||||
if_sx = itemp_has(itemp, IF_SX);
|
||||
if (arflag & IFM_OSIZE)
|
||||
arsize = opsize;
|
||||
else if (arflag & IFM_ASIZE)
|
||||
arsize = mode_to_op(ins->addr_size);
|
||||
|
||||
/* Flags for which the AR and SM flags apply */
|
||||
armask = itemp_arx(itemp);
|
||||
smmask = itemp_smx(itemp);
|
||||
|
||||
/* Apply ARx sizes and handle size coersion */
|
||||
for (i = 0; i < oprs; i++) {
|
||||
const unsigned int bit = 1U << i;
|
||||
if (!if_sx) {
|
||||
for (i = 0; i < oprs; i++) {
|
||||
const unsigned int bit = 1U << i;
|
||||
|
||||
if (!isize[i] && is_class(REGISTER, itype[i]))
|
||||
isize[i] = tsize[i];
|
||||
|
||||
if (armask & bit) {
|
||||
if (!isize[i] && !if_sx)
|
||||
isize[i] = arsize;
|
||||
if (!isize[i]) {
|
||||
if (is_class(REGISTER, itype[i]) && tsize[i])
|
||||
isize[i] = tsize[i];
|
||||
else if (armask & bit)
|
||||
isize[i] = arsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look the common subset for the size-matched operands */
|
||||
smsize = SIZE_MASK;
|
||||
smsize = msize_mask;
|
||||
if (smmask) {
|
||||
unsigned int nosizemask = 0;
|
||||
for (i = 0; i < oprs; i++) {
|
||||
|
|
@ -3924,6 +3959,33 @@ static void add_asp(insn *ins)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the initial operand size, based only on the mode and any prefixes.
|
||||
* The actual operand size may change after instruction pattern selection.
|
||||
*/
|
||||
static void set_initial_opsize(insn *ins)
|
||||
{
|
||||
const int bits = ins->bits;
|
||||
|
||||
switch (ins->prefixes[PPS_OSIZE]) {
|
||||
case P_OSP:
|
||||
ins->op_size = bits == 16 ? 32 : 16;
|
||||
break;
|
||||
case P_O16:
|
||||
ins->op_size = 16;
|
||||
break;
|
||||
case P_O32:
|
||||
ins->op_size = 32;
|
||||
break;
|
||||
case P_O64:
|
||||
ins->op_size = 64;
|
||||
break;
|
||||
default:
|
||||
ins->op_size = bits == 16 ? 16 : 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main entry point to this module, called from asm/nasm.c.
|
||||
*/
|
||||
|
|
|
|||
100
asm/exprlib.c
100
asm/exprlib.c
|
|
@ -79,6 +79,57 @@ bool is_really_simple(const expr *vect)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Classify an expression based on its components
|
||||
*/
|
||||
enum expr_classes expr_class(const expr *vect)
|
||||
{
|
||||
enum expr_classes class = EC_ZERO;
|
||||
|
||||
for (; vect->type; vect++) {
|
||||
if (!vect->value) {
|
||||
/* Value-0 term */
|
||||
} else if (vect->type < EXPR_UNKNOWN) {
|
||||
if ((class & EC_REGISTER) || vect->value != 1)
|
||||
class |= EC_REGEXPR;
|
||||
else
|
||||
class |= EC_REGISTER;
|
||||
} else if (vect->type == EXPR_UNKNOWN) {
|
||||
class |= EC_UNKNOWN;
|
||||
} else if (vect->type == EXPR_SIMPLE) {
|
||||
/* Pure number term */
|
||||
class |= EC_CONST;
|
||||
} else if (vect->type == EXPR_WRT) {
|
||||
class |= EC_WRT;
|
||||
} else if (vect->type < EXPR_SEGBASE) {
|
||||
class |= EC_COMPLEX;
|
||||
} else if (vect->type >= EXPR_SEGBASE + SEG_ABS) {
|
||||
/* It is an absolute segment */
|
||||
if (class & (EC_SEG|EC_SEGABS))
|
||||
class |= EC_COMPLEX;
|
||||
class |= EC_SEGABS;
|
||||
} else {
|
||||
/* It is a segment */
|
||||
if (vect->value == 1) {
|
||||
if (class & (EC_SEG|EC_SEGABS))
|
||||
class |= EC_COMPLEX;
|
||||
class |= EC_SEG;
|
||||
} else if (vect->value == -1) {
|
||||
/* can only subtract current segment, and only once */
|
||||
if (vect->type != location.segment + EXPR_SEGBASE ||
|
||||
(class & EC_SELFREL))
|
||||
class |= EC_COMPLEX;
|
||||
class |= EC_SELFREL;
|
||||
} else {
|
||||
/* Non-simple segment arithmetic */
|
||||
class |= EC_COMPLEX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return class;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the argument is relocatable (i.e. a simple
|
||||
* scalar, plus at most one segment-base, possibly a subtraction
|
||||
|
|
@ -86,39 +137,7 @@ bool is_really_simple(const expr *vect)
|
|||
*/
|
||||
bool is_reloc(const expr *vect)
|
||||
{
|
||||
bool has_rel = false; /* Has a self-segment-subtract */
|
||||
bool has_seg = false; /* Has a segment base */
|
||||
|
||||
for (; vect->type; vect++) {
|
||||
if (!vect->value) {
|
||||
/* skip value-0 terms */
|
||||
continue;
|
||||
} else if (vect->type < EXPR_SIMPLE) {
|
||||
/* false if a register is present */
|
||||
return false;
|
||||
} else if (vect->type == EXPR_SIMPLE) {
|
||||
/* skip over a pure number term... */
|
||||
continue;
|
||||
} else if (vect->type == EXPR_WRT) {
|
||||
/* skip over a WRT term... */
|
||||
continue;
|
||||
} else if (vect->type < EXPR_SEGBASE) {
|
||||
/* other special type -> problem */
|
||||
return false;
|
||||
} else if (vect->value == 1) {
|
||||
if (has_seg)
|
||||
return false; /* only one segbase allowed */
|
||||
has_seg = true;
|
||||
} else if (vect->value == -1) {
|
||||
if (vect->type != location.segment + EXPR_SEGBASE)
|
||||
return false; /* can only subtract current segment */
|
||||
if (has_rel)
|
||||
return false; /* already is relative */
|
||||
has_rel = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(expr_class(vect) & ~EC_RELOC);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -126,9 +145,7 @@ bool is_reloc(const expr *vect)
|
|||
*/
|
||||
bool is_unknown(const expr *vect)
|
||||
{
|
||||
while (vect->type && vect->type < EXPR_UNKNOWN)
|
||||
vect++;
|
||||
return (vect->type == EXPR_UNKNOWN);
|
||||
return !!(expr_class(vect) & EC_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -137,9 +154,7 @@ bool is_unknown(const expr *vect)
|
|||
*/
|
||||
bool is_just_unknown(const expr *vect)
|
||||
{
|
||||
while (vect->type && !vect->value)
|
||||
vect++;
|
||||
return (vect->type == EXPR_UNKNOWN);
|
||||
return expr_class(vect) == EC_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -191,10 +206,5 @@ int32_t reloc_wrt(const expr *vect)
|
|||
*/
|
||||
bool is_self_relative(const expr *vect)
|
||||
{
|
||||
for (; vect->type; vect++) {
|
||||
if (vect->type == location.segment + EXPR_SEGBASE && vect->value == -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return !!(expr_class(vect) & EC_SELFREL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 1996-2020 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
*
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* floats.h header file for the floating-point constant module of
|
||||
* the Netwide Assembler
|
||||
*/
|
||||
|
|
@ -61,7 +61,7 @@ struct ieee_format {
|
|||
extern const struct ieee_format fp_formats[FLOAT_ERR];
|
||||
|
||||
int float_const(const char *str, int s, uint8_t *result, enum floatize ffmt);
|
||||
enum floatize float_deffmt(int bytes);
|
||||
enum floatize const_func float_deffmt(int bytes);
|
||||
int float_option(const char *option);
|
||||
|
||||
#endif /* NASM_FLOATS_H */
|
||||
|
|
|
|||
|
|
@ -1776,7 +1776,7 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
|||
/**
|
||||
* get warning index; 0 if this is non-suppressible.
|
||||
*/
|
||||
static size_t warn_index(errflags severity)
|
||||
static size_t pure_func warn_index(errflags severity)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
|
|
@ -1853,7 +1853,7 @@ static bool is_suppressed(errflags severity)
|
|||
* @param severity the severity of the warning or error
|
||||
* @return true if we should error out
|
||||
*/
|
||||
static errflags true_error_type(errflags severity)
|
||||
static errflags pure_func true_error_type(errflags severity)
|
||||
{
|
||||
const uint8_t warn_is_err = WARN_ST_ENABLED|WARN_ST_ERROR;
|
||||
int type;
|
||||
|
|
|
|||
44
asm/parser.c
44
asm/parser.c
|
|
@ -1230,27 +1230,39 @@ restart_parse:
|
|||
nasm_nonfatal("invalid use of FAR operand specifier");
|
||||
recover = true;
|
||||
} else { /* it's not a memory reference */
|
||||
if (is_just_unknown(value)) { /* it's immediate but unknown */
|
||||
op->type |= IMM_NORMAL;
|
||||
op->opflags |= OPFLAG_UNKNOWN;
|
||||
op->offset = 0; /* don't care */
|
||||
op->segment = NO_SEG; /* don't care again */
|
||||
op->wrt = NO_SEG; /* still don't care */
|
||||
const enum expr_classes eclass = expr_class(value);
|
||||
|
||||
set_imm_flags(op, result->opt);
|
||||
} else if (is_reloc(value)) { /* it's immediate */
|
||||
uint64_t n = reloc_value(value);
|
||||
|
||||
op->type |= IMM_NORMAL;
|
||||
op->offset = n;
|
||||
if (!(eclass & ~(EC_RELOC | EC_UNKNOWN))) {
|
||||
/* It is an immediate */
|
||||
op->offset = reloc_value(value);
|
||||
op->segment = reloc_seg(value);
|
||||
op->wrt = reloc_wrt(value);
|
||||
if (is_self_relative(value))
|
||||
if (eclass & EC_SELFREL)
|
||||
op->opflags |= OPFLAG_RELATIVE;
|
||||
if (is_simple(value))
|
||||
if (!(eclass & ~EC_SIMPLE))
|
||||
op->opflags |= OPFLAG_SIMPLE;
|
||||
if (eclass & EC_UNKNOWN)
|
||||
op->opflags |= OPFLAG_UNKNOWN;
|
||||
|
||||
op->type |= IMM_NORMAL;
|
||||
set_imm_flags(op, result->opt);
|
||||
|
||||
/*
|
||||
* Special hack: if the previous operand was a colon
|
||||
* immediate operand with an explicit size, and this
|
||||
* one does not have an explicit size, move the size
|
||||
* specifier to this operand. This handles the case:
|
||||
* "jmp dword foo:bar" (really being "jmp foo:dword bar".)
|
||||
*/
|
||||
if (opnum > 0 &&
|
||||
unlikely(is_class(op[-1].type, IMM_NORMAL|COLON))) {
|
||||
opflags_t nsize = op->type & SIZE_MASK;
|
||||
opflags_t osize = op[-1].type & SIZE_MASK;
|
||||
if (osize && !nsize) {
|
||||
op->type ^= osize;
|
||||
op[-1].type ^= osize;
|
||||
}
|
||||
}
|
||||
} else if (value->type == EXPR_RDSAE) {
|
||||
/*
|
||||
* it's not an operand but a rounding or SAE decorator.
|
||||
|
|
@ -1316,7 +1328,7 @@ restart_parse:
|
|||
* we want to produce a warning iff the specified size
|
||||
* is different from the register size
|
||||
*/
|
||||
rs = op->type & SIZE_MASK;
|
||||
rs = op->type & (SIZE_MASK & ~NEAR);
|
||||
} else {
|
||||
rs = 0;
|
||||
}
|
||||
|
|
@ -1346,7 +1358,7 @@ restart_parse:
|
|||
op->basereg = value->type;
|
||||
|
||||
if (rs) {
|
||||
opflags_t opsize = nasm_reg_flags[value->type] & SIZE_MASK;
|
||||
opflags_t opsize = nasm_reg_flags[value->type] & (SIZE_MASK & ~NEAR);
|
||||
if (!opsize) {
|
||||
op->type |= rs; /* For non-size-specific registers, permit size override */
|
||||
} else if (opsize != rs) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ struct stdscan_state;
|
|||
|
||||
void stdscan_set(const struct stdscan_state *);
|
||||
const struct stdscan_state *stdscan_get(void);
|
||||
char *stdscan_tell(void);
|
||||
char * pure_func stdscan_tell(void);
|
||||
void stdscan_reset(char *buffer);
|
||||
int stdscan(void *pvt, struct tokenval *tv);
|
||||
void stdscan_pushback(const struct tokenval *tv);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
dnl --------------------------------------------------------------------------
|
||||
dnl PA_ADD_FLAGS(flagvar, flags)
|
||||
dnl PA_ADD_FLAGS(flagvar, flags [, real-flags [, success [, failure]]])
|
||||
dnl
|
||||
dnl Add [flags] to the variable [flagvar] if and only if it is accepted
|
||||
dnl by all languages affected by [flagvar], if those languages have
|
||||
dnl been previously seen in the script.
|
||||
dnl Add [real-flags] (default [flags]) to the variable [flagvar] if
|
||||
dnl and only if [flags] are accepted by all languages affected by
|
||||
dnl [flagvar], if those languages have been previously seen in the
|
||||
dnl script.
|
||||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN([PA_ADD_FLAGS],
|
||||
[
|
||||
|
|
|
|||
|
|
@ -15,5 +15,6 @@ AC_DEFUN([PA_COMMON_ATTRIBUTES],
|
|||
PA_FUNC_ATTRIBUTE(const)
|
||||
PA_FUNC_ATTRIBUTE(pure)
|
||||
PA_FUNC_ATTRIBUTE(cold,,,,,unlikely_func)
|
||||
PA_FUNC_ATTRIBUTE(used)
|
||||
PA_FUNC_ATTRIBUTE(unused)
|
||||
PA_FUNC_ATTRIBUTE_ERROR])
|
||||
|
|
|
|||
|
|
@ -9,5 +9,7 @@ AC_DEFUN([PA_OPTION_DEBUG],
|
|||
[PA_ADD_LANGFLAGS([-g3])], [PA_ADD_LANGFLAGS([-ggdb3 -g3])])
|
||||
PA_ARG_ENABLED([debug], [optimize for debugging],
|
||||
[PA_ADD_LANGFLAGS([-Og -O0])
|
||||
AC_DEFINE([WITH_DEBUG], 1,
|
||||
[Define to 1 to include code specifically indended to help debugging.])
|
||||
$1],
|
||||
[$2])])
|
||||
|
|
|
|||
|
|
@ -5,4 +5,7 @@ dnl Try to enable profiling if --enable-profiling is set.
|
|||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN([PA_OPTION_PROFILING],
|
||||
[PA_ARG_ENABLED([profiling], [compile with profiling (-pg option)],
|
||||
[PA_ADD_LANGFLAGS([-pg])])])
|
||||
[PA_ADD_LANGFLAGS([-pg])
|
||||
AC_DEFINE([WITH_PROFILING], 1,
|
||||
[Define to 1 to include code specifically indended to help profiling.])
|
||||
])])
|
||||
|
|
|
|||
|
|
@ -107,6 +107,22 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef used_func
|
||||
# ifdef HAVE_FUNC_ATTRIBUTE_USED
|
||||
# define used_func ATTRIBUTE(used)
|
||||
# else
|
||||
# define used_func
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef used_func_ptr
|
||||
# ifdef HAVE_FUNC_PTR_ATTRIBUTE_USED
|
||||
# define used_func_ptr ATTRIBUTE(used)
|
||||
# else
|
||||
# define used_func_ptr
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef unused_func
|
||||
# ifdef HAVE_FUNC_ATTRIBUTE_UNUSED
|
||||
# define unused_func ATTRIBUTE(unused)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ size_t strlcpy(char *, const char *, size_t);
|
|||
#endif
|
||||
|
||||
#if !defined(HAVE_STRCHRNUL) || !HAVE_DECL_STRCHRNUL
|
||||
char *strrchrnul(const char *, int);
|
||||
char * pure_func strrchrnul(const char *, int);
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus /* C++ has false, true, bool as keywords */
|
||||
|
|
|
|||
|
|
@ -67,10 +67,10 @@ struct hash_iterator {
|
|||
const struct hash_node *next;
|
||||
};
|
||||
|
||||
uint64_t crc64(uint64_t crc, const char *string);
|
||||
uint64_t crc64i(uint64_t crc, const char *string);
|
||||
uint64_t crc64b(uint64_t crc, const void *data, size_t len);
|
||||
uint64_t crc64ib(uint64_t crc, const void *data, size_t len);
|
||||
uint64_t pure_func crc64(uint64_t crc, const char *string);
|
||||
uint64_t pure_func crc64i(uint64_t crc, const char *string);
|
||||
uint64_t pure_func crc64b(uint64_t crc, const void *data, size_t len);
|
||||
uint64_t pure_func crc64ib(uint64_t crc, const void *data, size_t len);
|
||||
#define CRC64_INIT UINT64_C(0xffffffffffffffff)
|
||||
|
||||
static inline uint64_t crc64_byte(uint64_t crc, uint8_t v)
|
||||
|
|
@ -79,7 +79,7 @@ static inline uint64_t crc64_byte(uint64_t crc, uint8_t v)
|
|||
return crc64_tab[(uint8_t)(v ^ crc)] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
uint32_t crc32b(uint32_t crc, const void *data, size_t len);
|
||||
uint32_t pure_func crc32b(uint32_t crc, const void *data, size_t len);
|
||||
|
||||
void **hash_find(struct hash_table *head, const char *string,
|
||||
struct hash_insert *insert);
|
||||
|
|
|
|||
|
|
@ -71,8 +71,11 @@ static inline int iflag_cmp(const iflag_t *a, const iflag_t *b)
|
|||
IF_GEN_HELPER(xor, ^)
|
||||
|
||||
/* Some helpers which are to work with predefined masks */
|
||||
#define IF_SMASK (IFM_SB|IFM_SW|IFM_SD|IFM_SQ|IFM_ST|IFM_SO|\
|
||||
IFM_SY|IFM_SZ|IFM_SIZE|IFM_ANYSIZE|IFM_SX)
|
||||
/* TSMASK = "True size" mask */
|
||||
#define IF_TSMASK (IFM_SB|IFM_SW|IFM_SD|IFM_SQ|IFM_ST|IFM_SO|\
|
||||
IFM_SY|IFM_SZ)
|
||||
#define IF_SMASK (IF_TSMASK|IFM_NWSIZE|IFM_OSIZE|IFM_ASIZE|\
|
||||
IFM_ANYSIZE|IFM_SX)
|
||||
#define IF_ARMASK (IFM_AR0|IFM_AR1|IFM_AR2|IFM_AR3|IFM_AR4)
|
||||
#define IF_SMMASK (IFM_SM0|IFM_SM1|IFM_SM2|IFM_SM3|IFM_SM4)
|
||||
|
||||
|
|
|
|||
|
|
@ -368,6 +368,22 @@ typedef struct {
|
|||
/*
|
||||
* Library routines to manipulate expression data types.
|
||||
*/
|
||||
enum expr_classes {
|
||||
EC_ZERO = 0, /* All-zero expression */
|
||||
EC_CONST = 1, /* Additive constant */
|
||||
EC_SEGABS = 2, /* Absolute segment reference */
|
||||
EC_SIMPLE = EC_CONST | EC_SEGABS,
|
||||
EC_SELFREL = 4, /* Self-relative expression */
|
||||
EC_SEG = 8, /* Has a segment base */
|
||||
EC_WRT = 16, /* Has WRT */
|
||||
EC_RELOC = EC_SIMPLE | EC_SELFREL | EC_SEG | EC_WRT,
|
||||
EC_UNKNOWN = 32, /* Has an "unknown" part */
|
||||
EC_REGISTER = 64, /* Has a register */
|
||||
EC_REGEXPR = 128, /* Has more than one register and/or reg*n */
|
||||
EC_COMPLEX = 256 /* Even more complex, problematic */
|
||||
};
|
||||
|
||||
enum expr_classes expr_class(const expr *vect);
|
||||
bool is_reloc(const expr *vect);
|
||||
bool is_simple(const expr *vect);
|
||||
bool is_really_simple(const expr *vect);
|
||||
|
|
|
|||
|
|
@ -364,14 +364,14 @@ void fwriteaddr(uint64_t data, int size, FILE * fp);
|
|||
*
|
||||
* bsi() is case sensitive, bsii() is case insensitive.
|
||||
*/
|
||||
int bsi(const char *string, const char **array, int size);
|
||||
int bsii(const char *string, const char **array, int size);
|
||||
int pure_func bsi(const char *string, const char **array, int size);
|
||||
int pure_func bsii(const char *string, const char **array, int size);
|
||||
|
||||
/*
|
||||
* Convenient string processing helper routines
|
||||
*/
|
||||
char *nasm_skip_spaces(const char *p);
|
||||
char *nasm_skip_word(const char *p);
|
||||
char * pure_func nasm_skip_spaces(const char *p);
|
||||
char * pure_func nasm_skip_word(const char *p);
|
||||
char *nasm_zap_spaces_fwd(char *p);
|
||||
char *nasm_zap_spaces_rev(char *p);
|
||||
char *nasm_trim_spaces(char *p);
|
||||
|
|
@ -395,8 +395,8 @@ char * safe_alloc nasm_catfile(const char *dir, const char *path);
|
|||
/*
|
||||
* Various tokens to readable strings, with limit checking
|
||||
*/
|
||||
const char * pure_func register_name(int);
|
||||
const char * pure_func prefix_name(int);
|
||||
const char * const_func register_name(int);
|
||||
const char * const_func prefix_name(int);
|
||||
bool const_func is_hint_nop(uint64_t);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -47,6 +47,6 @@ struct perfect_hash {
|
|||
const char * const *strings;
|
||||
};
|
||||
|
||||
int perfhash_find(const struct perfect_hash *, const char *);
|
||||
int pure_func perfhash_find(const struct perfect_hash *, const char *);
|
||||
|
||||
#endif /* PERFHASH_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 1996-2009 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
|
|
@ -41,8 +41,8 @@ typedef uint64_t raaindex;
|
|||
|
||||
#define raa_init() NULL
|
||||
void raa_free(struct RAA *);
|
||||
int64_t raa_read(struct RAA *, raaindex);
|
||||
void *raa_read_ptr(struct RAA *, raaindex);
|
||||
int64_t pure_func raa_read(struct RAA *, raaindex);
|
||||
void * pure_func raa_read_ptr(struct RAA *, raaindex);
|
||||
struct RAA * never_null raa_write(struct RAA *r, raaindex posn, int64_t value);
|
||||
struct RAA * never_null raa_write_ptr(struct RAA *r, raaindex posn, void *value);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,27 +70,27 @@ struct rbtree *rb_insert(struct rbtree *, struct rbtree *);
|
|||
* Find a node in the tree corresponding to the key immediately
|
||||
* <= the passed-in key value.
|
||||
*/
|
||||
struct rbtree *rb_search(const struct rbtree *, uint64_t);
|
||||
struct rbtree * pure_func rb_search(const struct rbtree *, uint64_t);
|
||||
|
||||
/*
|
||||
* Find a node in the tree exactly matching the key value.
|
||||
*/
|
||||
struct rbtree *rb_search_exact(const struct rbtree *, uint64_t);
|
||||
struct rbtree * pure_func rb_search_exact(const struct rbtree *, uint64_t);
|
||||
|
||||
/*
|
||||
* Return the immediately previous or next node in key order.
|
||||
* Returns NULL if this node is the end of the tree.
|
||||
* These operations are safe for complee (but not partial!)
|
||||
* These operations are safe for complete (but not partial!)
|
||||
* tree walk-with-destruction in key order.
|
||||
*/
|
||||
struct rbtree *rb_prev(const struct rbtree *);
|
||||
struct rbtree *rb_next(const struct rbtree *);
|
||||
struct rbtree * pure_func rb_prev(const struct rbtree *);
|
||||
struct rbtree * pure_func rb_next(const struct rbtree *);
|
||||
|
||||
/*
|
||||
* Return the very first or very last node in key order.
|
||||
*/
|
||||
struct rbtree *rb_first(const struct rbtree *);
|
||||
struct rbtree *rb_last(const struct rbtree *);
|
||||
struct rbtree * pure_func rb_first(const struct rbtree *);
|
||||
struct rbtree * pure_func rb_last(const struct rbtree *);
|
||||
|
||||
/*
|
||||
* Left and right nodes, if real. These operations are
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
|
|
@ -55,7 +55,7 @@ struct use_package {
|
|||
const unsigned char *macros;
|
||||
int index;
|
||||
};
|
||||
extern const struct use_package *nasm_find_use_package(const char *);
|
||||
extern const struct use_package * pure_func nasm_find_use_package(const char *);
|
||||
extern const int use_package_count;
|
||||
|
||||
/* --- From insns.dat via insns.pl: --- */
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@ extern const char nasm_compile_options[];
|
|||
|
||||
extern bool reproducible;
|
||||
|
||||
extern const char *nasm_comment(void);
|
||||
extern size_t nasm_comment_len(void);
|
||||
extern const char * pure_func nasm_comment(void);
|
||||
extern size_t pure_func nasm_comment_len(void);
|
||||
|
||||
extern const char *nasm_signature(void);
|
||||
extern size_t nasm_signature_len(void);
|
||||
extern const char * pure_func nasm_signature(void);
|
||||
extern size_t pure_func nasm_signature_len(void);
|
||||
|
||||
#endif /* NASM_VER_H */
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
fatal_func nasm_alloc_failed(void);
|
||||
|
||||
static inline void *validate_ptr(void *p)
|
||||
static inline void * pure_func validate_ptr(void *p)
|
||||
{
|
||||
if (unlikely(!p))
|
||||
nasm_alloc_failed();
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@
|
|||
* This is an inline, because most compilers can greatly simplify this
|
||||
* for a fixed string, like we have here.
|
||||
*/
|
||||
static inline bool ismatch(const char *charset, char ch)
|
||||
static inline bool pure_func ismatch(const char *charset, char ch)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ static inline bool ismatch(const char *charset, char ch)
|
|||
return false;
|
||||
}
|
||||
|
||||
static const char *first_filename_char(const char *path)
|
||||
static const char * pure_func first_filename_char(const char *path)
|
||||
{
|
||||
#ifdef separators
|
||||
const char *p = path + strlen(path);
|
||||
|
|
|
|||
|
|
@ -114,7 +114,8 @@ void raa_free(struct RAA *r)
|
|||
nasm_free(r);
|
||||
}
|
||||
|
||||
static const union intorptr *real_raa_read(struct RAA *r, raaindex posn)
|
||||
static const union intorptr * pure_func
|
||||
real_raa_read(struct RAA *r, raaindex posn)
|
||||
{
|
||||
nasm_assert(posn <= (~(raaindex)0 >> 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 1996-2020 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
|
|
@ -59,22 +59,22 @@ static const char * const _nasm_signature[2] = {
|
|||
"NASM"
|
||||
};
|
||||
|
||||
const char *nasm_comment(void)
|
||||
const char * pure_func nasm_comment(void)
|
||||
{
|
||||
return _nasm_comment[reproducible];
|
||||
}
|
||||
|
||||
size_t nasm_comment_len(void)
|
||||
size_t pure_func nasm_comment_len(void)
|
||||
{
|
||||
return strlen(nasm_comment());
|
||||
}
|
||||
|
||||
const char *nasm_signature(void)
|
||||
const char * pure_func nasm_signature(void)
|
||||
{
|
||||
return _nasm_signature[reproducible];
|
||||
}
|
||||
|
||||
size_t nasm_signature_len(void)
|
||||
size_t pure_func nasm_signature_len(void)
|
||||
{
|
||||
return strlen(nasm_signature());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ static const struct ofmt_alias ofmt_aliases[] = {
|
|||
#endif /* BUILD_DRIVERS_ARRAY */
|
||||
|
||||
const struct ofmt *ofmt_find(const char *name, const struct ofmt_alias **ofmt_alias);
|
||||
const struct dfmt *dfmt_find(const struct ofmt *, const char *);
|
||||
const struct dfmt * pure_func dfmt_find(const struct ofmt *, const char *);
|
||||
void ofmt_list(const struct ofmt *, FILE *);
|
||||
void dfmt_list(FILE *);
|
||||
extern const struct dfmt null_debug_form;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#ifndef HAVE_STRRCHRNUL
|
||||
|
||||
char *strrchrnul(const char *s, int c)
|
||||
char * pure_func strrchrnul(const char *s, int c)
|
||||
{
|
||||
char *p;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
;Testname=avx005; Arguments=-fbin -oavx005.bin -Ox; Files=stdout stderr avx005.bin
|
||||
|
||||
%define regxmm xmm0
|
||||
%define regymm ymm0
|
||||
%define mem [0]
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
|
|||
\331 norep not valid with 0xF2 or 0xF3 REP prefixes.
|
||||
\332 f2i REP prefix (0xF2 byte) used as opcode extension.
|
||||
\333 f3i REP prefix (0xF3 byte) used as opcode extension.
|
||||
\334 rex.l LOCK prefix used as REX.
|
||||
\334 rex.l LOCK prefix used as REX.R in 16/32-bit mode.
|
||||
\335 repe disassemble a rep (0xF3 byte) prefix as repe not rep.
|
||||
\340 resb reserve <operand 0> bytes of uninitialized storage.
|
||||
Operand 0 had better be a segmentless constant.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ if_("AR2", "SB, SW, SD applies to operand 2");
|
|||
if_("AR3", "SB, SW, SD applies to operand 3");
|
||||
if_("AR4", "SB, SW, SD applies to operand 4");
|
||||
# These must match the order of the BITSx flags in opflags.h
|
||||
# Are these obsolete?
|
||||
if_("SB", "Unsized operands can't be non-byte");
|
||||
if_("SW", "Unsized operands can't be non-word");
|
||||
if_("SD", "Unsized operands can't be non-dword");
|
||||
|
|
@ -26,10 +27,11 @@ if_("SO", "Unsized operands can't be non-oword");
|
|||
if_("SY", "Unsized operands can't be non-yword");
|
||||
if_("SZ", "Unsized operands can't be non-zword");
|
||||
# End BITSx order match requirement
|
||||
if_("SIZE", "Unsized operands must match the bitsize");
|
||||
if_("NWSIZE", "Operand size defaults to 64 in 64-bit mode");
|
||||
if_("OSIZE", "Unsized operands must match the default operand size");
|
||||
if_("ASIZE", "Unsized operands must match the address size");
|
||||
if_("ANYSIZE", "Ignore operand size even if explicit");
|
||||
if_("SX", "Unsized operands not allowed");
|
||||
if_("SX_W", "At least one sized SMx operand required");
|
||||
if_("SDWORD", "Strict sdword64 matching");
|
||||
if_break_ok();
|
||||
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ sub set_implied_flags($;$) {
|
|||
sub size_flag($) {
|
||||
my %sflags = ( 'SB' => 8, 'SW' => 16, 'SD' => 32, 'SQ' => 64,
|
||||
'ST' => 80, 'SO' => 128, 'SY' => 256, 'SZ' => 512,
|
||||
'SX' => 0, 'SIZE' => 0, 'ANYSIZE' => 0 );
|
||||
'SX' => 0, 'OSIZE' => 0, 'ASIZE' => 0, 'ANYSIZE' => 0 );
|
||||
my($flags) = @_;
|
||||
|
||||
foreach my $fl (keys(%sflags)) {
|
||||
|
|
@ -260,14 +260,14 @@ sub split_flags($) {
|
|||
|
||||
# Merge a flags field and strip flags with leading !
|
||||
sub merge_flags($;$) {
|
||||
my($flags, $merge) = @_;
|
||||
my($flags, $human) = @_;
|
||||
|
||||
clean_flags(\%flags);
|
||||
|
||||
my @flagslist = sort { $flag_byname{$a} <=> $flag_byname{$b} }
|
||||
grep { !/^(\s*|\!.*)$/ } keys(%$flags);
|
||||
|
||||
if ($merge) {
|
||||
if ($human) {
|
||||
# For possibe human consumption. Merge subsequent SM and AR
|
||||
# flags back into ranges.
|
||||
my @ofl = @flagslist;
|
||||
|
|
@ -309,7 +309,7 @@ sub merge_flags($;$) {
|
|||
}
|
||||
}
|
||||
|
||||
return scalar(@flagslist) ? join(',', @flagslist) : '0';
|
||||
return scalar(@flagslist) ? join(',', @flagslist) : $human ? 'ignore' : '0';
|
||||
}
|
||||
|
||||
# Compute the combinations of instruction flags actually used in templates
|
||||
|
|
|
|||
293
x86/insns.dat
293
x86/insns.dat
|
|
@ -76,8 +76,8 @@ NOP void [ osz norexb nof3 90] 8086
|
|||
NOP2 void [ norexb nof3 66 90] 386,ND
|
||||
$wdq NOP rm# [m: o# 0f 1f /0] P6
|
||||
|
||||
;# The basic 8 arithmetic operations
|
||||
$arith ADD OR ADC SBB AND SUB XOR -zu,-lock,-hle,!apx,CMP
|
||||
;# The basic 7 arithmetic operations
|
||||
$arith ADD OR ADC SBB AND SUB XOR
|
||||
|
||||
;# The basic shift and rotate operations
|
||||
$shift !x,xs="0f38 f7" ROL x=f3,xs="0f3a f0",ROR RCL RCR x=66,SHL,SAL x=f2,SHR - x=f3,SAR
|
||||
|
|
@ -194,88 +194,54 @@ $bwdq XCHG reg#,rm# [rm: hlenl o16 87 /r] 8086,SM,LOCK1,ND
|
|||
|
||||
;# Jumps
|
||||
; Call/jmp near imm/reg/mem is always 64-bit in long mode.
|
||||
JMP imm|short [i: nw eb rel8] 8086,NOAPX,SX
|
||||
JMP imm8 [i: nw eb rel8] 8086,NOAPX,SX
|
||||
JMP imm8|short [i: nw eb rel8] 8086,NOAPX,SX
|
||||
JMP imm [i: jmp8 nw eb rel8] 8086,SX,ND,NOAPX
|
||||
JMP imm [i: nw odf e9 rel] 8086,SX,BND,NOAPX
|
||||
JMP imm|near [i: nw odf e9 rel] 8086,SX,ND,BND,NOAPX
|
||||
JMP imm|far [i: odf ea iwd seg] 8086,SX,ND,NOLONG
|
||||
JMP imm16 [i: o16 e9 rel] 8086,SX,NOLONG,BND
|
||||
JMP imm16|near [i: o16 e9 rel] 8086,SX,ND,NOLONG,BND
|
||||
JMP imm16|far [i: o16 ea iwd seg] 8086,SX,ND,NOLONG
|
||||
JMP imm32 [i: o32 e9 rel] 386,SX,NOLONG,BND
|
||||
JMP imm32|near [i: o32 e9 rel] 386,SX,ND,NOLONG,BND
|
||||
JMP imm32|far [i: o32 ea iwd seg] 386,SX,ND,NOLONG
|
||||
JMP imm64 [i: o64nw e9 rel] X86_64,SX,LONG,BND,NOAPX
|
||||
JMP imm64|near [i: o64nw e9 rel] X86_64,SX,LONG,ND,BND,NOAPX
|
||||
JMP imm:imm [ji: odf ea iwd iw] 8086,NOLONG
|
||||
JMP imm16:imm [ji: o16 ea iw iw] 8086,SX,AR0,NOLONG
|
||||
JMP imm:imm16 [ji: o16 ea iw iw] 8086,SX,AR1,NOLONG
|
||||
JMP imm32:imm [ji: o32 ea id iw] 386,SX,AR0,NOLONG
|
||||
JMP imm:imm32 [ji: o32 ea id iw] 386,SX,AR1,NOLONG
|
||||
JMP mem|far [m: odf ff /5] 8086,SX,NOLONG
|
||||
JMP mem|far [m: o64 ff /5] X86_64,SX,LONG
|
||||
JMP mem16|far [m: o16 ff /5] 8086,SX
|
||||
JMP mem32|far [m: o32 ff /5] 386,SX
|
||||
JMP mem64|far [m: o64 ff /5] X86_64,LONG,SX
|
||||
JMP mem|near [m: odf ff /4] 8086,ND,BND,SX
|
||||
JMP rm16|near [m: o16 ff /4] 8086,NOLONG,ND,SX,BND
|
||||
JMP rm32|near [m: o32 ff /4] 386,NOLONG,ND,SX,BND
|
||||
JMP rm64|near [m: o64nw ff /4] X86_64,LONG,ND,SX,BND
|
||||
JMP mem [m: odf ff /4] 8086,BND
|
||||
JMP rm16 [m: o16 ff /4] 8086,NOLONG,BND
|
||||
JMP rm32 [m: o32 ff /4] 386,NOLONG,BND
|
||||
JMP rm64 [m: o64nw ff /4] X86_64,LONG,BND
|
||||
JMP imm8|short [i: nw eb rel8] 8086,NOAPX
|
||||
JMP imm [i: jmp8 nw eb rel8] 8086,SX,ND,NOAPX
|
||||
$wdq JMP imm#|near [i: nw o# e9 rel] 8086,OSIZE,ND,BND,NOLONG16
|
||||
$wdq JMP rm#|near [m: nw o# ff /4] 8086,OSIZE,BND,NOLONG16
|
||||
$wd JMP imm#|far [i: o# ea iwd seg] 8086,OSIZE,ND,NOLONG
|
||||
$wd JMP imm16:imm# [ji: o# ea iwd iw] 8086,OSIZE,AR1,NOLONG
|
||||
$wd JMP imm16:imm#|far [ji: o# ea iwd iw] 8086,OSIZE,AR1,NOLONG,ND
|
||||
$wdq JMP mem#|far [m: o# ff /5] 8086,OSIZE
|
||||
|
||||
; APX absolute 64-bit jmp
|
||||
JMP imm|abs [i: a64 np rex2 a1 iq ] APX
|
||||
JMP imm64|abs [i: a64 np rex2 a1 iq ] APX,ND
|
||||
JMPABS imm [i: a64 np rex2 a1 iq ] APX,ND
|
||||
JMPABS imm64 [i: a64 np rex2 a1 iq ] APX,ND
|
||||
JMP imm64|abs [i: a64 np rex2 a1 iq ] APX
|
||||
JMPABS imm64 [i: a64 np rex2 a1 iq ] APX,ND
|
||||
JMPABS imm64|abs [i: a64 np rex2 a1 iq ] APX,ND
|
||||
|
||||
Jcc imm|near [i: odf 0f 80+c rel] 386,BND,SX,NOAPX
|
||||
Jcc imm16|near [i: o16 0f 80+c rel] 386,NOLONG,SX,BND
|
||||
Jcc imm32|near [i: o32 0f 80+c rel] 386,NOLONG,SX,BND
|
||||
Jcc imm64|near [i: o64nw 0f 80+c rel] X86_64,LONG,SX,BND,NOAPX
|
||||
Jcc imm|short [i: nw 70+c rel8] 8086,ND,BND,SX,NOAPX
|
||||
Jcc imm8 [i: nw 70+c rel8] 8086,ND,BND,SX,NOAPX
|
||||
Jcc imm [i: jcc8 nw 70+c rel8] 8086,BND,NOAPX
|
||||
Jcc imm [i: nw 0f 80+c rel] 386,ND,BND,NOAPX
|
||||
Jcc imm [i: nw 71+c jlen e9 rel] 8086,ND,NOAPX
|
||||
Jcc imm8|short [i: nw 70+c rel8] 8086,ND,BND,SX,NOAPX
|
||||
Jcc imm [i: jcc8 nw 70+c rel8] 8086,BND,SX,NOAPX
|
||||
$zwdq Jcc imm#|near [i: o# 0f 80+c rel] 386,BND,NOAPX,NOLONGwd
|
||||
; Jump-over emulation of Jcc on < 386
|
||||
Jcc imm16|near [i: nw 71+c jlen e9 rel] 8086,ND,NOAPX,NOLONG
|
||||
|
||||
JCXZ imm [i: a16 e3 rel8] 8086,NOLONG
|
||||
JECXZ imm [i: a32 e3 rel8] 386,NOAPX
|
||||
JRCXZ imm [i: a64 e3 rel8] X86_64,LONG,NOAPX
|
||||
; These only have short forms, hence imm8|near|short
|
||||
JCXZ imm8|near|short [i: a16 e3 rel8] 8086,NOLONG
|
||||
JECXZ imm8|near|short [i: a32 e3 rel8] 386,NOAPX
|
||||
JRCXZ imm8|near|short [i: a64 e3 rel8] X86_64,LONG,NOAPX
|
||||
$wdq JCXZ imm8|near|short,cx# [i-: a# e3 rel8] 8086,ND
|
||||
|
||||
$z LOOP% imm [i: a# nw e2 rel8] 8086,NOAPX
|
||||
$z LOOPE% imm [i: a# nw e1 rel8] 8086,NOAPX
|
||||
$z LOOPNE% imm [i: a# nw e0 rel8] 8086,NOAPX
|
||||
$z LOOPZ% imm [i: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$z LOOPNZ% imm [i: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOP imm,cx# [i-: a# nw e2 rel8] 8086,NOAPX
|
||||
$wdq LOOPE imm,cx# [i-: a# nw e1 rel8] 8086,NOAPX
|
||||
$wdq LOOPNE imm,cx# [i: a# nw e0 rel8] 8086,NOAPX
|
||||
$wdq LOOPZ imm,cx# [i-: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPNZ imm,cx# [i: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOP% imm [i: a# nw e2 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPE% imm [i: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPNE% imm [i: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPZ% imm [i: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPNZ% imm [i: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
$zwdq LOOP% imm8|near|short [i: a# nw e2 rel8] 8086,NOAPX,(wdq:ND)
|
||||
$zwdq LOOPE% imm8|near|short [i: a# nw e1 rel8] 8086,NOAPX,(wdq:ND)
|
||||
$zwdq LOOPNE% imm8|near|short [i: a# nw e0 rel8] 8086,NOAPX,(wdq:ND)
|
||||
$zwdq LOOPZ% imm8|near|short [i: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$zwdq LOOPNZ% imm8|near|short [i: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOP imm8|near|short,cx# [i-: a# nw e2 rel8] 8086,NOAPX
|
||||
$wdq LOOPE imm8|near|short,cx# [i-: a# nw e1 rel8] 8086,NOAPX
|
||||
$wdq LOOPNE imm8|near|short,cx# [i-: a# nw e0 rel8] 8086,NOAPX
|
||||
$wdq LOOPZ imm8|near|short,cx# [i-: a# nw e1 rel8] 8086,NOAPX,ND
|
||||
$wdq LOOPNZ imm8|near|short,cx# [i-: a# nw e0 rel8] 8086,NOAPX,ND
|
||||
|
||||
; JMPE is obsolete, but seems to be used by a fair number of virtual environments?
|
||||
JMPE imm [i: nw odf 0f b8 rel] IA64,SIZE
|
||||
$wdq JMPE imm# [i: nw o# 0f b8 rel] IA64
|
||||
$zwdq JMPE imm#|near [i: nw o# 0f b8 rel] IA64
|
||||
; 0f 00 /6 with a prefix has been repurposed in long mode
|
||||
$wdq JMPE rm# [m: o# np 0f 00 /6] IA64
|
||||
$wd JMPE rm# [m: o# 0f 00 /6] IA64,NOLONG
|
||||
$wdq JMPE rm#|near [m: nw o# np 0f 00 /6] IA64
|
||||
$wd JMPE rm#|near [m: o# 0f 00 /6] IA64,NOLONG
|
||||
|
||||
;# Call and return
|
||||
CALL imm [i: odf e8 rel] 8086,BND,NOAPX,SIZE
|
||||
CALL imm|near [i: odf e8 rel] 8086,ND,BND,NOAPX,SIZE
|
||||
CALL imm|far [i: odf 9a iwd seg] 8086,ND,NOLONG,SIZE
|
||||
CALL imm:imm [ji: odf 9a iwd iw] 8086,NOLONG,SIZE,AR1
|
||||
CALL imm [i: odf e8 rel] 8086,BND,NOAPX,OSIZE
|
||||
CALL imm|near [i: odf e8 rel] 8086,ND,BND,NOAPX,OSIZE
|
||||
CALL imm|far [i: odf 9a iwd seg] 8086,ND,NOLONG,OSIZE
|
||||
CALL imm:imm [ji: odf 9a iwd iw] 8086,NOLONG,OSIZE,AR1
|
||||
; Call/jmp near imm/reg/mem is always 64-bit in long mode.
|
||||
CALL imm16 [i: o16 e8 rel] 8086,NOLONG,BND,SX
|
||||
CALL imm16|near [i: o16 e8 rel] 8086,ND,NOLONG,BND,SX,ND
|
||||
|
|
@ -298,7 +264,7 @@ CALL mem|near [m: odf ff /2] 8086,ND,BND,SX
|
|||
CALL rm16|near [m: o16 ff /2] 8086,NOLONG,ND,BND,SX
|
||||
CALL rm32|near [m: o32 ff /2] 386,NOLONG,ND,BND,SX
|
||||
CALL rm64|near [m: o64nw ff /2] X86_64,LONG,ND,BND,SX
|
||||
CALL mem [m: odf ff /2] 8086,BND,SIZE
|
||||
CALL mem [m: odf ff /2] 8086,BND,OSIZE
|
||||
CALL rm16 [m: o16 ff /2] 8086,NOLONG,BND
|
||||
CALL rm32 [m: o32 ff /2] 386,NOLONG,BND
|
||||
CALL rm64 [m: o64nw ff /2] X86_64,LONG,BND
|
||||
|
|
@ -387,8 +353,8 @@ WBNOINVD void [ f3 0f 09] WBNOINVD,FUTURE,PRIV
|
|||
INVPCID reg32,mem128 [rm: 66 0f38 82 /r] FUTURE,INVPCID,PRIV,NOLONG
|
||||
INVPCID reg64,mem128 [rm: 66 0f38 82 /r] FUTURE,INVPCID,PRIV,LONG
|
||||
INVLPG mem [m: 0f 01 /7] 486,PRIV
|
||||
INVLPGA void [ adf 0f 01 df] X86_64,AMD
|
||||
$wdq INVLPGA ax#,reg_ecx [--: a# 0f 01 df] X86_64,AMD,NOLONG
|
||||
$wdq INVLPGA ax#,reg_ecx [--: a# 0f 01 df] X86_64,AMD
|
||||
INVLPGA void [ adf 0f 01 df] X86_64,AMD,ND
|
||||
|
||||
;# Special reads: timestamp, CPU number, performance counters, randomness
|
||||
RDPMC void [ 0f 33] P6,NOAPX
|
||||
|
|
@ -402,30 +368,26 @@ $dq RDPID reg# [m: o# f3 0f c7 /7] FUTURE
|
|||
;# Machine control and management instructions
|
||||
CLTS void [ 0f 06] 286,PRIV
|
||||
CPUID void [ 0f a2] PENT
|
||||
LMSW mem [m: 0f 01 /6] 286,PRIV
|
||||
LMSW mem16 [m: 0f 01 /6] 286,PRIV
|
||||
LMSW reg16 [m: 0f 01 /6] 286,PRIV
|
||||
SMSW mem [m: 0f 01 /4] 286
|
||||
SMSW mem16 [m: 0f 01 /4] 286
|
||||
SMSW reg16 [m: o16 0f 01 /4] 286
|
||||
SMSW reg32 [m: o32 0f 01 /4] 386
|
||||
SMSW reg64 [m: o64 0f 01 /4] X86_64,LONG
|
||||
MOV reg32,reg_creg [mr: rex.l 0f 20 /r] 386,PRIV,NOLONG
|
||||
MOV reg64,reg_creg [mr: o64nw 0f 20 /r] X86_64,LONG,PRIV
|
||||
MOV reg_creg,reg32 [rm: rex.l 0f 22 /r] 386,PRIV,NOLONG
|
||||
MOV reg_creg,reg64 [rm: o64nw 0f 22 /r] X86_64,LONG,PRIV
|
||||
MOV reg32,reg_dreg [mr: 0f 21 /r] 386,PRIV,NOLONG
|
||||
MOV reg64,reg_dreg [mr: o64nw 0f 21 /r] X86_64,LONG,PRIV
|
||||
MOV reg_dreg,reg32 [rm: 0f 23 /r] 386,PRIV,NOLONG
|
||||
MOV reg_dreg,reg64 [rm: o64nw 0f 23 /r] X86_64,LONG,PRIV
|
||||
MOV reg32,reg_treg [mr: 0f 24 /r] 386,NOLONG,ND,OBSOLETE
|
||||
MOV reg_treg,reg32 [rm: 0f 26 /r] 386,NOLONG,ND,OBSOLETE
|
||||
LMSW rm16 [m: 0f 01 /6] 286,PRIV
|
||||
SMSW rm16 [m: 0f 01 /4] 286
|
||||
$wdq SMSW reg# [m: o# 0f 01 /4] 286
|
||||
|
||||
$dq MOV reg#,reg_creg [mr: nw w# rex.l 0f 20 /r] 386,PRIV
|
||||
$dq MOV reg_creg,reg# [rm: nw w# rex.l 0f 22 /r] 386,PRIV
|
||||
$dq MOV reg#,reg_dreg [mr: nw w# 0f 21 /r] 386,PRIV
|
||||
$dq MOV reg_dreg,reg# [rm: nw w# 0f 23 /r] 386,PRIV,NOLONG
|
||||
MOV reg32,reg_treg [mr: 0f 24 /r] 386,NOLONG,ND,OBSOLETE
|
||||
MOV reg_treg,reg32 [rm: 0f 26 /r] 386,NOLONG,ND,OBSOLETE
|
||||
|
||||
WRMSR void [ 0f 30] PENT,PRIV,NOAPX
|
||||
RDMSR void [ 0f 32] PENT,PRIV,NOAPX
|
||||
WRMSRNS void [ np 0f 01 c6 ] WRMSRNS,FUTURE,PRIV,LONG
|
||||
RDMSRLIST void [ f2 0f 01 c6 ] MSRLIST,FUTURE,PRIV,LONG
|
||||
WRMSRLIST void [ f3 0f 01 c6 ] MSRLIST,FUTURE,PRIV,LONG
|
||||
|
||||
$bwd UMOV rm#,reg# [mr: np o# 0f 10# /r] 386,UNDOC,SM,ND,NOLONG,OBSOLETE
|
||||
$bwd UMOV reg#,rm# [rm: np o# 0f 12# /r] 386,UNDOC,SM,ND,NOLONG,OBSOLETE
|
||||
|
||||
; Machine control instructions from old Cyrix machines, probably obsolete
|
||||
BB0_RESET void [ m1 3a] PENT,CYRIX,NOLONG,OBSOLETE,ND
|
||||
BB1_RESET void [ m1 3b] PENT,CYRIX,NOLONG,OBSOLETE,ND
|
||||
|
|
@ -735,12 +697,8 @@ $wdq LSL reg#,rm16 [rm: o# 0f 03 /r] 286,PROT
|
|||
$wdq LSL reg#,reg32 [rm: o# 0f 03 /r] 386,PROT
|
||||
$wdq LSL reg#,reg64 [rm: o# 0f 03 /r] X86_64,LONG,PROT
|
||||
|
||||
VERR mem [m: 0f 00 /4] 286,PROT
|
||||
VERR mem16 [m: 0f 00 /4] 286,PROT
|
||||
VERR reg16 [m: 0f 00 /4] 286,PROT
|
||||
VERW mem [m: 0f 00 /5] 286,PROT
|
||||
VERW mem16 [m: 0f 00 /5] 286,PROT
|
||||
VERW reg16 [m: 0f 00 /5] 286,PROT
|
||||
VERR rm16 [m: 0f 00 /4] 286,PROT
|
||||
VERW rm16 [m: 0f 00 /5] 286,PROT
|
||||
|
||||
; The privileged ones...
|
||||
SWAPGS void [ 0f 01 f8] X86_64,LONG
|
||||
|
|
@ -754,22 +712,22 @@ LLDT mem16 [m: 0f 00 /2] 286,PROT,PRIV
|
|||
LLDT reg16 [m: 0f 00 /2] 286,PROT,PRIV
|
||||
LTR rm16 [m: 0f 00 /3] 286,PROT,PRIV
|
||||
|
||||
$wdq SGDT mem# [m: nw o# 0f 01 /0] 286,SIZE
|
||||
$wdq SIDT mem# [m: nw o# 0f 01 /1] 286,SIZE
|
||||
SLDT reg64 [m: o64nw 0f 00 /0] X86_64,LONG,ND
|
||||
$wdq SLDT reg# [m: o# 0f 00 /0] 286
|
||||
SLDT mem16 [m: osz 0f 00 /0] 286
|
||||
STR reg64 [m: o64nw 0f 00 /1] X86_64,LONG,ND
|
||||
$wdq STR reg# [m: o# 0f 00 /1] 286
|
||||
STR mem16 [m: osz 0f 00 /1] 286
|
||||
$wdq SGDT mem# [m: nw o# 0f 01 /0] 286,OSIZE
|
||||
$wdq SIDT mem# [m: nw o# 0f 01 /1] 286,OSIZE
|
||||
SLDT reg64 [m: o64nw 0f 00 /0] X86_64,LONG,ND
|
||||
$wdq SLDT reg# [m: o# 0f 00 /0] 286
|
||||
SLDT mem16 [m: osz 0f 00 /0] 286
|
||||
STR reg64 [m: o64nw 0f 00 /1] X86_64,LONG,ND
|
||||
$wdq STR reg# [m: o# 0f 00 /1] 286
|
||||
STR mem16 [m: osz 0f 00 /1] 286
|
||||
|
||||
STR mem16 [m: 0f 00 /1] 286,PROT
|
||||
STR reg16 [m: o16 0f 00 /1] 286,PROT
|
||||
STR reg32 [m: o32 0f 00 /1] 386,PROT
|
||||
STR reg64 [m: o64 0f 00 /1] X86_64,LONG
|
||||
|
||||
$wdq LEA reg#,mem [rm: o# 8d /r] 8086
|
||||
$wdq LEA reg#,imm# [rm: o# 8d /r] 8086,ND
|
||||
$wdq LEA reg#,mem [rm: o# 8d /r] 8086
|
||||
$wdq LEA reg#,imm# [rm: o# 8d /r] 8086,ND
|
||||
|
||||
LOADALL void [ 0f 07] 386,UNDOC,ND,OBSOLETE
|
||||
LOADALL286 void [ 0f 05] 286,UNDOC,ND,OBSOLETE
|
||||
|
|
@ -780,37 +738,26 @@ MONITORX void [ 0f 01 fa] AMD
|
|||
MONITORX reg_rax,reg_ecx,reg_edx [---: 0f 01 fa] X86_64,LONG,AMD,ND
|
||||
MONITORX reg_eax,reg_ecx,reg_edx [---: 0f 01 fa] AMD,ND
|
||||
MONITORX reg_ax,reg_ecx,reg_edx [---: 0f 01 fa] AMD,ND
|
||||
$bwdq MOV ax#,mem_offs [-i: o# a0# iwdq] 8086,SM,NOAPX
|
||||
$bwdq MOV mem_offs,ax# [i-: o# a2# iwdq] 8086,SM,NOHLE,NOAPX
|
||||
MOV mem8,reg8 [mr: hlexr 88 /r] 8086,SM
|
||||
MOV reg8,reg8 [mr: 88 /r] 8086
|
||||
MOV mem16,reg16 [mr: hlexr o16 89 /r] 8086,SM
|
||||
MOV reg16,reg16 [mr: o16 89 /r] 8086
|
||||
MOV mem32,reg32 [mr: hlexr o32 89 /r] 386,SM
|
||||
MOV reg32,reg32 [mr: o32 89 /r] 386
|
||||
MOV mem64,reg64 [mr: hlexr o64 89 /r] X86_64,LONG,SM
|
||||
MOV reg64,reg64 [mr: o64 89 /r] X86_64,LONG
|
||||
MOV reg8,mem8 [rm: 8a /r] 8086,SM
|
||||
MOV reg8,reg8 [rm: 8a /r] 8086
|
||||
MOV reg16,rm16 [rm: o16 8b /r] 8086,SM
|
||||
MOV reg32,rm32 [rm: o32 8b /r] 386,SM
|
||||
MOV reg64,rm64 [rm: o64 8b /r] X86_64,LONG,SM
|
||||
MOV reg8,imm8 [ri: b0+r ib] 8086,SM
|
||||
MOV reg16,imm16 [ri: o16 b8+r iw] 8086,SM
|
||||
MOV reg32,imm32 [ri: o32 b8+r id] 386,SM
|
||||
MOV reg64,udword64 [ri: o64nw b8+r id] X86_64,LONG,SM,OPT,ND
|
||||
MOV reg64,sdword64 [mi: o64 c7 /0 id,s] X86_64,LONG,SM,OPT,SDWORD,ND
|
||||
MOV reg64,imm64 [ri: o64 b8+r iq] X86_64,LONG,SM
|
||||
MOV rm8,imm8 [mi: hlexr c6 /0 ib] 8086,SM
|
||||
MOV rm16,imm16 [mi: hlexr o16 c7 /0 iw] 8086,SM
|
||||
MOV rm32,imm32 [mi: hlexr o32 c7 /0 id] 386,SM
|
||||
MOV rm64,sdword64 [mi: hlexr o64 c7 /0 id,s] X86_64,LONG,SM
|
||||
MOVD mmxreg,rm32 [rm: np 0f 6e /r] PENT,MMX,SD
|
||||
MOVD rm32,mmxreg [mr: np 0f 7e /r] PENT,MMX,SD
|
||||
MOVD mmxreg,rm64 [rm: np o64 0f 6e /r] X86_64,LONG,MMX,SX,ND
|
||||
MOVD rm64,mmxreg [mr: np o64 0f 7e /r] X86_64,LONG,MMX,SX,ND
|
||||
MOVQ mmxreg,mmxrm [rm: np 0f 6f /r] PENT,MMX,SQ
|
||||
MOVQ mmxrm,mmxreg [mr: np 0f 7f /r] PENT,MMX,SQ
|
||||
$bwdq MOV ax#,mem_offs [-i: o# a0# iwdq] 8086,SM,NOAPX
|
||||
$bwdq MOV mem_offs,ax# [i-: o# a2# iwdq] 8086,SM,NOHLE,NOAPX
|
||||
$bwdq MOVABS ax#,mem_offs [-i: o# a0# iwdq] 8086,SM,NOAPX,ND
|
||||
$bwdq MOVABS mem_offs,ax# [i-: o# a2# iwdq] 8086,SM,NOHLE,NOAPX,ND
|
||||
$bwdq MOV rm#,reg# [mr: hlexr o# 88# /r] 8086,SM
|
||||
$bwdq MOV reg#,rm# [rm: o# 8a# /r] 8086,SM
|
||||
$bwd MOV reg#,imm# [ri: o# b0+r# i#] 8086,SM
|
||||
MOV reg64,udword64 [ri: o32 b8+r id] X86_64,LONG,SM,OPT,ND
|
||||
MOV reg64,sdword64 [mi: o64 c7 /0 id,s] X86_64,LONG,SM,OPT,SDWORD,ND
|
||||
MOV reg64,imm64 [ri: o64 b8+r iq] X86_64,LONG,SM
|
||||
MOV reg64,imm64|abs [ri: o64 b8+r iq] X86_64,LONG,ND
|
||||
$bwd MOVABS reg#,imm# [ri: o64 b8+r iq] 8086,SM
|
||||
MOVABS reg64,imm64 [ri: o64 b8+r iq] X86_64,LONG,SM,ND
|
||||
$bwdq MOV rm#,imm# [mi: hlexr o# c6# /0 i#] 8086,SM
|
||||
MOVD mmxreg,rm32 [rm: np 0f 6e /r] PENT,MMX
|
||||
MOVD rm32,mmxreg [mr: np 0f 7e /r] PENT,MMX
|
||||
MOVD mmxreg,rm64 [rm: np o64 0f 6e /r] X86_64,LONG,MMX,ND
|
||||
MOVD rm64,mmxreg [mr: np o64 0f 7e /r] X86_64,LONG,MMX,ND
|
||||
MOVQ mmxreg,mmxrm64 [rm: np 0f 6f /r] PENT,MMX
|
||||
MOVQ mmxrm64,mmxreg [mr: np 0f 7f /r] PENT,MMX
|
||||
MOVQ mmxreg,rm64 [rm: np o64 0f 6e /r] X86_64,LONG,MMX
|
||||
MOVQ rm64,mmxreg [mr: np o64 0f 7e /r] X86_64,LONG,MMX
|
||||
MWAIT void [ 0f 01 c9] PRESCOTT
|
||||
|
|
@ -906,10 +853,10 @@ PUNPCKLWD mmxreg,mmxrm [rm: np 0f 61 /r] PENT,MMX,SQ
|
|||
|
||||
;# Stack operations
|
||||
$wdq PUSH reg# [r: nw o# 50+r] 8086
|
||||
$wdq PUSH rm# [m: nw o# ff /6] 8086,SIZE
|
||||
$wdq PUSH rm# [m: nw o# ff /6] 8086,OSIZE
|
||||
PUSH imm8 [i: nw osz 6a ib,s] 186,SX,ND
|
||||
$wdq PUSH sbyte# [i: nw o# 6a ib,s] 186,SIZE
|
||||
$wdq PUSH imm# [i: nw o# 68 i#] 186,SIZE
|
||||
$wdq PUSH sbyte# [i: nw o# 6a ib,s] 186,OSIZE
|
||||
$wdq PUSH imm# [i: nw o# 68 i#] 186,OSIZE
|
||||
|
||||
$wdq POP reg# [r: nw o# 58+r] 8086
|
||||
$wdq POP rm# [m: nw o# 8f /0] 8086
|
||||
|
|
@ -969,29 +916,6 @@ SHRD reg32,reg32,reg_cl [mr-: o32 0f ad /r] 386
|
|||
SHRD mem,reg64,reg_cl [mr-: o64 0f ad /r] X86_64,LONG,SM
|
||||
SHRD reg64,reg64,reg_cl [mr-: o64 0f ad /r] X86_64,LONG
|
||||
SKINIT void [ 0f 01 de] X86_64,LONG
|
||||
TEST mem,reg8 [mr: 84 /r] 8086,SM
|
||||
TEST reg8,reg8 [mr: 84 /r] 8086
|
||||
TEST mem,reg16 [mr: o16 85 /r] 8086,SM
|
||||
TEST reg16,reg16 [mr: o16 85 /r] 8086
|
||||
TEST mem,reg32 [mr: o32 85 /r] 386,SM
|
||||
TEST reg32,reg32 [mr: o32 85 /r] 386
|
||||
TEST mem,reg64 [mr: o64 85 /r] X86_64,LONG,SM
|
||||
TEST reg64,reg64 [mr: o64 85 /r] X86_64,LONG
|
||||
TEST reg8,mem [rm: 84 /r] 8086,SM
|
||||
TEST reg16,mem [rm: o16 85 /r] 8086,SM
|
||||
TEST reg32,mem [rm: o32 85 /r] 386,SM
|
||||
TEST reg64,mem [rm: o64 85 /r] X86_64,LONG,SM
|
||||
TEST reg_al,imm [-i: a8 ib] 8086,SM,NOAPX
|
||||
TEST reg_ax,imm [-i: o16 a9 iw] 8086,SM,NOAPX
|
||||
TEST reg_eax,imm [-i: o32 a9 id] 386,SM,NOAPX
|
||||
TEST reg_rax,imm [-i: o64 a9 id,s] X86_64,LONG,SM,NOAPX
|
||||
TEST rm8,imm [mi: f6 /0 ib] 8086,SM
|
||||
TEST rm16,imm [mi: o16 f7 /0 iw] 8086,SM
|
||||
TEST rm32,imm [mi: o32 f7 /0 id] 386,SM
|
||||
TEST rm64,imm [mi: o64 f7 /0 id,s] X86_64,LONG,SM
|
||||
TEST mem,imm8 [mi: f6 /0 ib] 8086,SM
|
||||
TEST mem,imm16 [mi: o16 f7 /0 iw] 8086,SM
|
||||
TEST mem,imm32 [mi: o32 f7 /0 id] 386,SM
|
||||
UD0 void [ 0f ff] 186,OBSOLETE
|
||||
UD0 reg16,rm16 [rm: o16 0f ff /r] 186
|
||||
UD0 reg32,rm32 [rm: o32 0f ff /r] 186
|
||||
|
|
@ -1006,23 +930,27 @@ UD2B reg32,rm32 [rm: o32 0f b9 /r] 186,ND
|
|||
UD2B reg64,rm64 [rm: o64 0f b9 /r] 186,ND
|
||||
UD2 void [ 0f 0b] 186
|
||||
UD2A void [ 0f 0b] 186,ND
|
||||
UMOV mem,reg8 [mr: np 0f 10 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg8,reg8 [mr: np 0f 10 /r] 386,UNDOC,ND
|
||||
UMOV mem,reg16 [mr: np o16 0f 11 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg16,reg16 [mr: np o16 0f 11 /r] 386,UNDOC,ND
|
||||
UMOV mem,reg32 [mr: np o32 0f 11 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg32,reg32 [mr: np o32 0f 11 /r] 386,UNDOC,ND
|
||||
UMOV reg8,mem [rm: np 0f 12 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg8,reg8 [rm: np 0f 12 /r] 386,UNDOC,ND
|
||||
UMOV reg16,mem [rm: np o16 0f 13 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg16,reg16 [rm: np o16 0f 13 /r] 386,UNDOC,ND
|
||||
UMOV reg32,mem [rm: np o32 0f 13 /r] 386,UNDOC,SM,ND
|
||||
UMOV reg32,reg32 [rm: np o32 0f 13 /r] 386,UNDOC,ND
|
||||
FWAIT void [ wait] 8086
|
||||
|
||||
XLATB void [ d7] 8086
|
||||
XLAT void [ d7] 8086,ND
|
||||
|
||||
;# Comparing and testing
|
||||
$bwdq CMP rm#,reg# [mr: o# 38# /r ] 8086,SM
|
||||
$bwdq CMP reg#,rm# [rm: o# 3a# /r ] 8086,SM
|
||||
$wdq CMP rm#,sbyte# [mi: o# 83 /7 ib,s ] 8086,SM
|
||||
$bwdq CMP ax#,imm# [mi: o# 3c# i# ] 8086,SM
|
||||
$bwdq CMP rm#,imm# [mi: o# 80# /7 i# ] 8086,SM
|
||||
|
||||
$bwdq TEST rm#,reg# [mr: o# 84# /r ] 8086,SM
|
||||
$bwdq TEST ax#,imm# [-i: o# a8# i# ] 8086,SM,NOAPX
|
||||
$bwdq TEST rm#,imm# [mi: o# f6# /0 i# ] 8086,SM
|
||||
|
||||
$bwdq CCMPscc spec4,rm#,reg# [vmr: evex.scc.dfv.l0.np.m4.o# 38# /r ] APX,SM1-2
|
||||
$bwdq CCMPscc spec4,reg#,rm# [vrm: evex.scc.dfv.l0.np.m4.o# 3a# /r ] APX,SM1-2
|
||||
$wdq CCMPscc spec4,rm#,sbyte# [vmi: evex.scc.dfv.l0.66.m4.o# 83 /7 ib,s ] APX,SM1-2
|
||||
$bwdq CCMPscc spec4,rm#,imm# [vmi: evex.scc.dfv.l0.np.m4.o# 80# /7 ib ] APX,SM1-2
|
||||
|
||||
;# Conditional instructions
|
||||
$wdq CMOVcc reg#,rm# [rm: o# 0f 40+c /r] P6,SM
|
||||
|
||||
|
|
@ -1034,11 +962,6 @@ SETccZU reg32 [m: evex.nd1.l0.f2.m4.wig 40+c /0 ] APX,ZU,ND
|
|||
SETcc rm8 [m: evex.zu.l0.f2.m4.wig 40+c /0 ] APX
|
||||
SETccZU rm8 [m: evex.nd1.l0.f2.m4.wig 40+c /0 ] APX,ZU,ND
|
||||
|
||||
$bwdq CCMPscc spec4,rm#,reg# [vmr: evex.scc.dfv.l0.np.m4.o# 38# /r ] APX,SM1-2
|
||||
$bwdq CCMPscc spec4,reg#,rm# [vrm: evex.scc.dfv.l0.np.m4.o# 3a# /r ] APX,SM1-2
|
||||
$wdq CCMPscc spec4,rm#,sbyte# [vmi: evex.scc.dfv.l0.66.m4.o# 83 /7 ib,s ] APX,SM1-2
|
||||
$bwdq CCMPscc spec4,rm#,imm# [vmi: evex.scc.dfv.l0.np.m4.o# 80# /7 ib ] APX,SM1-2
|
||||
|
||||
;# Katmai Streaming SIMD instructions (SSE -- a.k.a. KNI, XMM, MMX2)
|
||||
ADDPS xmmreg,xmmrm128 [rm: np 0f 58 /r] KATMAI,SSE
|
||||
ADDSS xmmreg,xmmrm32 [rm: f3 0f 58 /r] KATMAI,SSE
|
||||
|
|
|
|||
|
|
@ -990,8 +990,6 @@ sub byte_code_compile($$$) {
|
|||
'odf' => 0322, # Operand size is default
|
||||
'o64' => 0324, # 64-bit operand size requiring REX.W
|
||||
'w1' => 0324,
|
||||
'o64nw' => 0323, # Implied 64-bit operand size (no REX.W)
|
||||
'nw' => 0327, # REX.W not needed
|
||||
'a16' => 0310,
|
||||
'a32' => 0311,
|
||||
'adf' => 0312, # Address size is default (disassembly)
|
||||
|
|
@ -1070,6 +1068,9 @@ sub byte_code_compile($$$) {
|
|||
# Plain code
|
||||
my $pc = $plain_codes{$op};
|
||||
push(@codes, $pc) if (defined($pc));
|
||||
} elsif ($op =~ /^(o64)?(nw)$/) {
|
||||
push(@codes, $1 eq '' ? 0327 : 0323);
|
||||
$flags->{'NWSIZE'}++;
|
||||
} elsif ($prefix_ok && $op =~ /^(66|f2|f3)$/) {
|
||||
# 66/F2/F3 prefix used as an opcode extension
|
||||
if ($op eq '66') {
|
||||
|
|
|
|||
140
x86/preinsns.pl
140
x86/preinsns.pl
|
|
@ -18,7 +18,7 @@ require 'x86/insns-iflags.ph';
|
|||
our %macros;
|
||||
our($macro, $outfile, $infile, $line); # Public for error messages
|
||||
|
||||
# Common pattern for the basic 8 arithmetric functions
|
||||
# Common pattern for the basic 7 arithmetric functions
|
||||
$macros{'arith'} = {
|
||||
'def' => *def_eightfold,
|
||||
'txt' => <<'EOL'
|
||||
|
|
@ -68,27 +68,62 @@ for (my $i = 1; $i <= 31; $i++) {
|
|||
sub func_multisize($$$) {
|
||||
my($mac, $args, $rawargs) = @_;
|
||||
my @sbyte = ('imm8', 'imm8', 'sbyteword16', 'sbytedword32', 'sbytedword64');
|
||||
my $long = 0; # 1 for LONG, 2 for NOLONG, 3 for invalid
|
||||
|
||||
my @ol;
|
||||
my $mask = $mac->{'mask'};
|
||||
|
||||
for (my $i = 0; $i < scalar(@sizename); $i++) {
|
||||
next unless ($mask & (1 << $i));
|
||||
my $s = ($i > 0) ? 4 << $i : 'sz';
|
||||
my $s = ($i > 0) ? 4 << $i : '';
|
||||
my $sn = $sizename[$i];
|
||||
my $sz = $s || 'sz';
|
||||
my $o;
|
||||
my $ins = join("\t", @$rawargs);
|
||||
while ($ins =~ /^(.*?)((?:\b[0-9a-f]{2}|\bsbyte|\bimm|\bi|\b(?:reg_)?[abcd]x|\bw)?\#|\%)(.*)$/) {
|
||||
|
||||
# Conditional pattern inclusions
|
||||
# Syntax: (which1:text1/which2:text2/text3)
|
||||
# ... where "which" is a combination of sizename letters.
|
||||
# No colon means unconditional ("else" clause)
|
||||
while ($ins =~ /^(.*?)\(([^\)]+)\)(.*)$/) {
|
||||
$o .= $1;
|
||||
my @cpp = split(/\//, $2);
|
||||
$ins = $3;
|
||||
|
||||
my $found;
|
||||
foreach my $cp (@cpp) {
|
||||
if ($cp =~ /^([a-z]+)\:(.*)$/) {
|
||||
$cp = $2;
|
||||
$found = $1 =~ /$sn/;
|
||||
} else {
|
||||
$found = 1;
|
||||
}
|
||||
if ($found) {
|
||||
$o .= $cp;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ins = $o.$ins;
|
||||
$o = '';
|
||||
|
||||
while ($ins =~ /^(.*?)((?:\b[0-9a-f]{2}(?:\+r)?|\bsbyte|\bimm|\b[ioa]|\b(?:reg_)?[abcd]x|\breg|\brm|\bw)?\#|\b(?:reg|rm)64\b|\b(?:o64)?nw\b|\b(?:NO)?LONG\w+\b|\%)(.*)$/) {
|
||||
$o .= $1;
|
||||
my $mw = $2;
|
||||
$ins = $3;
|
||||
if ($mw eq '%') {
|
||||
$o .= uc($sizename[$i]) if ($i);
|
||||
} elsif ($mw =~ /^([0-9a-f]{2})\#$/) {
|
||||
$o .= sprintf('%02x', hex($1) | ($s != 8));
|
||||
$o .= uc($sn) if ($i);
|
||||
} elsif ($mw =~ /^([0-9a-f]{2})(\+r)?\#$/) {
|
||||
$o .= sprintf('%02x%s', hex($1) |
|
||||
(($s == 8) ? 0 :
|
||||
($2 eq '') ? 1 : 8), $2);
|
||||
} elsif ($mw eq 'sbyte#') {
|
||||
$o .= $sbyte[$i];
|
||||
} elsif ($mw eq 'imm#') {
|
||||
$o .= !$i ? 'imm' : ($s >= 64) ? "sdword$s" : "imm$s";
|
||||
} elsif ($mw =~ '^([ao])\#$') {
|
||||
$o .= $1 . $sz;
|
||||
} elsif ($mw eq 'i#') {
|
||||
$o .= !$i ? 'iwd' : ($s >= 64) ? 'id,s' : 'i'.$sizename[$i];
|
||||
} elsif ($mw =~ /^(?:reg_)?([abcd])x\#$/) {
|
||||
|
|
@ -100,28 +135,38 @@ sub func_multisize($$$) {
|
|||
$o .= "reg_e${1}x";
|
||||
} elsif ($i == 4) {
|
||||
$o .= "reg_r${1}x";
|
||||
$long |= 1;
|
||||
} else {
|
||||
die "$0:$infile:$line: register cannot be used with z\n";
|
||||
}
|
||||
} elsif ($mw =~ /^(o64)?nw$/) {
|
||||
$long |= 2 if ($i == 32); # nw = 32 bits not encodable in long mode
|
||||
$o .= $mw;
|
||||
} elsif ($mw =~ /^(reg|rm)(\#|[0-9]+)$/) {
|
||||
# (Possible) GPR reference
|
||||
$o .= $1;
|
||||
my $n = ($2 eq '#') ? $s : $2;
|
||||
$o .= $n;
|
||||
$long |= 1 if ($n >= 64);
|
||||
} elsif ($mw =~ /^(NO)?LONG(\w+)$/) {
|
||||
my $longflag = $1 ? 2 : 1;
|
||||
$long |= $longflag if ($2 =~ /$sn/i);
|
||||
# Drop
|
||||
} elsif ($mw eq 'w#') {
|
||||
$o .= !$i ? 'ww' : ($s >= 64) ? 'w1' : 'w0';
|
||||
} else {
|
||||
} elsif ($mw eq '#') {
|
||||
$o .= $s;
|
||||
} else {
|
||||
die "$0:$infile:$line: unknown sequence \"$mw\" should not match regexp\n";
|
||||
}
|
||||
}
|
||||
$o .= $ins;
|
||||
$o =~ s/\bNOLONG${i}\b/NOLONG/;
|
||||
$o =~ s/\bNOLONG[0-9]+\b//;
|
||||
if ($o =~ /\[[^\]]*\bnw\b[^\]]*\bo32\b[^\]]*\]/) {
|
||||
# nw o32 -> NOLONG
|
||||
$o .= ',NOLONG';
|
||||
}
|
||||
if ($i >= 64) {
|
||||
next if ($o =~ /\bNOLONG\b/);
|
||||
$o .= ',X86_64,LONG';
|
||||
} elsif ($i >= 32) {
|
||||
$o .= ',386';
|
||||
}
|
||||
|
||||
$o .= ',LONG' if ($long & 1);
|
||||
$o .= ',NOLONG' if ($long & 2);
|
||||
|
||||
$o .= ',386' if ($s >= 32 && $o !~ /\B\!386\b/);
|
||||
|
||||
push(@ol, $o);
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +367,7 @@ sub has_flag($@) {
|
|||
return undef;
|
||||
}
|
||||
|
||||
sub adjust_instruction_flags(@) {
|
||||
sub adjust_fl_zu(@) {
|
||||
my($opcode, $operands, $encoding, $flags) = @_;
|
||||
|
||||
# Flag-changing instructions
|
||||
|
|
@ -347,20 +392,25 @@ sub adjust_instruction_flags(@) {
|
|||
add_flag($flags, 'ZU');
|
||||
}
|
||||
|
||||
return ($opcode, $operands, $encoding, $flags);
|
||||
return $flags;
|
||||
}
|
||||
|
||||
sub adjust_instruction(@) {
|
||||
sub adjust_instruction_flags(@) {
|
||||
my @i = @_;
|
||||
|
||||
@i = adjust_instruction_flags(@i);
|
||||
$i[3] = adjust_fl_zu(@i);
|
||||
|
||||
return undef unless (@i);
|
||||
return undef unless (defined($i[3]));
|
||||
|
||||
if ($i[0] =~ /\bKILL\b/ || $i[1] =~ /\bKILL\b/ ||
|
||||
$i[2] =~ /\bKILL\b/ || has_flag($i[3], 'KILL')) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
if ($i[2] =~ /\ba16\b/) {
|
||||
add_flag($i[3], 'NOLONG');
|
||||
}
|
||||
if ($i[2] =~ /\b(o64(nw)?\b|w1\b|rex2?|a64\b)/) {
|
||||
if ($i[2] =~ /\b(o64(nw)?\b|rex2?|a64\b)/) {
|
||||
add_flag($i[3], 'LONG');
|
||||
}
|
||||
if (has_flag($i[3], 'NOLONG') && has_flag($i[3], 'LONG')) {
|
||||
|
|
@ -368,39 +418,45 @@ sub adjust_instruction(@) {
|
|||
return undef;
|
||||
}
|
||||
|
||||
if ($i[0] =~ /\bKILL\b/ || $i[1] =~ /\bKILL\b/ ||
|
||||
$i[2] =~ /\bKILL\b/ || has_flag($i[3], 'KILL')) {
|
||||
return undef;
|
||||
if (has_flag($i[3], 'LONG')) {
|
||||
add_flag($i[3], 'X86_64');
|
||||
}
|
||||
|
||||
return @i;
|
||||
return $i[3];
|
||||
}
|
||||
|
||||
sub process_insn($$) {
|
||||
my($out, $l) = @_;
|
||||
|
||||
if ($l !~ /^(\s*)([^\s\;]+)(\s+)([^\s\;]+)(\s+)([^\s\;]+|\[[^\;]*\])(\s+)([^\s\;]+)(\s*(\;.*)?)$/) {
|
||||
if ($l !~ /^\s*([^\s\;]+)\s+([^\s\;]+)\s+([^\s\;]+|\[[^\;]*?\])\s+([^\s\;]+)\s*(\;.*?)?\s*$/) {
|
||||
print $out $l, "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# Opcode = $f[1]
|
||||
# Operands = $f[3]
|
||||
# Encoding = $f[5]
|
||||
# Flags = $f[7]
|
||||
my @f = ($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
print $out $5, "\n" unless ($5 eq ''); # Comment
|
||||
|
||||
my $nopr = ($f[3] =~ /^(void|ignore)$/) ? 0 :
|
||||
scalar(split(/[\,\:]/, $f[3]));
|
||||
my $opcode = $1;
|
||||
my $operands = $2;
|
||||
my $encoding = $3;
|
||||
my $flagstr = $4;
|
||||
|
||||
my $nopr = ($operands =~ /^(void|ignore)$/) ? 0 : scalar(split(/[\,\:]/, $operands));
|
||||
|
||||
# Modify the instruction flags
|
||||
my %flags = split_flags($f[7]);
|
||||
set_implied_flags(\%flags, $nopr);
|
||||
my $flags = {split_flags($flagstr)};
|
||||
set_implied_flags($flags, $nopr);
|
||||
|
||||
next unless (adjust_instruction($f[1], $f[3], $f[5], \%flags));
|
||||
$flags = adjust_instruction_flags($opcode, $operands, $encoding, $flags);
|
||||
return unless (defined($flags));
|
||||
$flagstr = merge_flags($flags, 1);
|
||||
|
||||
$f[7] = merge_flags(\%flags, 1);
|
||||
print $out @f, "\n";
|
||||
# Tidy up the encoding for readability
|
||||
$encoding =~ s/\s+/ /g;
|
||||
if ($encoding =~ /^\s*\[\s*(.*?\:)?\s*([^\:]*?)\s*\]\s*$/) {
|
||||
$encoding = sprintf('[%-10s%-34s]', $1, $2);
|
||||
}
|
||||
|
||||
print $out sprintf("%-23s %-39s %-47s %s\n", $opcode, $operands, $encoding, $flagstr);
|
||||
}
|
||||
|
||||
open(my $in, '<', $infile) or die "$0:$infile: $!\n";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue