Skip to content

Commit

Permalink
Reworked REX2 handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mappzor committed Nov 8, 2024
1 parent 6241bfb commit 9f29242
Show file tree
Hide file tree
Showing 3 changed files with 9,878 additions and 9,913 deletions.
21 changes: 20 additions & 1 deletion include/Zydis/Internal/EncoderData.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,25 @@ typedef enum ZydisSizeHint_
ZYDIS_SIZE_HINT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SIZE_HINT_MAX_VALUE)
} ZydisSizeHint;

/**
* Used in encoder's table to indicate `REX2` prefix support type.
*/
typedef enum ZydisRex2Type_
{
ZYDIS_REX2_TYPE_FORBIDDEN,
ZYDIS_REX2_TYPE_ALLOWED,
ZYDIS_REX2_TYPE_MANDATORY,

/**
* Maximum value of this enum.
*/
ZYDIS_REX2_TYPE_MAX_VALUE = ZYDIS_REX2_TYPE_MANDATORY,
/**
* The minimum number of bits required to represent all values of this enum.
*/
ZYDIS_REX2_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REX2_TYPE_MAX_VALUE)
} ZydisRex2Type;

/**
* Used in encoder's primary lookup table which allows to access a set of instruction definitions
* for specified mnemonic in constant time.
Expand Down Expand Up @@ -183,7 +202,7 @@ typedef struct ZydisEncodableInstruction_
/**
* True if `REX2` prefix is required for this definition.
*/
ZyanU8 rex2 ZYAN_BITFIELD(1);
ZyanU8 rex2 ZYAN_BITFIELD(ZYDIS_REX2_TYPE_REQUIRED_BITS);
/**
* True if `EEVEX.ND` is required for this definition.
*/
Expand Down
60 changes: 3 additions & 57 deletions src/Encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,59 +721,6 @@ static ZyanBool ZydisCheckAsz(ZydisEncoderInstructionMatch *match, ZydisRegister
return match->easz == (ZyanU8)reg_width ? ZYAN_TRUE : ZYAN_FALSE;
}

/**
* Checks if opcode is allowed to use `REX2` prefix.
*
* @param match A pointer to `ZydisEncoderInstructionMatch` struct.
*
* @return True if `REX2` prefix can be used, false otherwise.
*/
static ZyanBool ZydisIsRex2Allowed(ZydisEncoderInstructionMatch *match)
{
// TODO: Remove this function, use `no_rex2` filter
const ZydisOpcodeMap opcode_map = match->definition->opcode_map;
if ((opcode_map != ZYDIS_OPCODE_MAP_DEFAULT) &&
(opcode_map != ZYDIS_OPCODE_MAP_0F))
{
return ZYAN_FALSE;
}
switch (match->request->mnemonic)
{
case ZYDIS_MNEMONIC_XRSTOR:
case ZYDIS_MNEMONIC_XRSTOR64:
case ZYDIS_MNEMONIC_XRSTORS:
case ZYDIS_MNEMONIC_XRSTORS64:
case ZYDIS_MNEMONIC_XSAVE:
case ZYDIS_MNEMONIC_XSAVE64:
case ZYDIS_MNEMONIC_XSAVEC:
case ZYDIS_MNEMONIC_XSAVEC64:
case ZYDIS_MNEMONIC_XSAVEOPT:
case ZYDIS_MNEMONIC_XSAVEOPT64:
case ZYDIS_MNEMONIC_XSAVES:
case ZYDIS_MNEMONIC_XSAVES64:
return ZYAN_FALSE;
default:
break;
}
static const ZyanBool is_rex2_allowed[2][16] =
{
{
ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE,
ZYAN_FALSE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_FALSE,
ZYAN_TRUE, ZYAN_TRUE, ZYAN_FALSE, ZYAN_TRUE,
ZYAN_TRUE, ZYAN_TRUE, ZYAN_FALSE, ZYAN_TRUE,
},
{
ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_FALSE,
ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE,
ZYAN_FALSE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE,
ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE,
},
};
const ZyanU8 row = (match->definition->opcode & 0xF0) >> 4;
return is_rex2_allowed[opcode_map][row];
}

/**
* Returns the id of the specified register as used in physical encoding.
*
Expand Down Expand Up @@ -833,7 +780,7 @@ static ZyanBool ZydisIsRegisterAllowed(ZydisEncoderInstructionMatch *match, Zydi
case ZYDIS_REGCLASS_GPR16:
case ZYDIS_REGCLASS_GPR32:
case ZYDIS_REGCLASS_GPR64:
return ZydisIsRex2Allowed(match) ||
return (match->definition->rex2 != ZYDIS_REX2_TYPE_FORBIDDEN) ||
(ZydisGetPhysicalId(reg, reg_class) < 16);
default:
return reg_id < 16;
Expand Down Expand Up @@ -989,8 +936,7 @@ static ZyanBool ZydisIsValidAddressingClass(ZydisEncoderInstructionMatch *match,
switch (match->definition->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
result &=
ZydisIsRex2Allowed(match);
result &= (match->definition->rex2 != ZYDIS_REX2_TYPE_FORBIDDEN);
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
break;
Expand Down Expand Up @@ -4157,7 +4103,7 @@ static ZyanStatus ZydisBuildInstruction(ZydisEncoderInstructionMatch *match,
{
instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
}
if (match->definition->rex2)
if (match->definition->rex2 == ZYDIS_REX2_TYPE_MANDATORY)
{
instruction->attributes |= ZYDIS_ATTRIB_HAS_REX2;
}
Expand Down
Loading

0 comments on commit 9f29242

Please sign in to comment.