x86: fix JO/JNO operand size in 64-bit mode by adding Intel/AMD mode flags (#3067)

* x86: fix JO/JNO operand size in 64-bit mode
* x86: add explicit Intel/AMD near-Jcc decoding modes

---------

Co-authored-by: Rot127 <[email protected]>
This commit is contained in:
raaller
2026-09-18 12:29:39 +00:00
committed by GitHub
co-authored by Rot127
parent 59eec7ec25
commit b871849b6c
15 changed files with 383 additions and 59 deletions
+14 -8
View File
@@ -75,7 +75,7 @@ static void set_mem_access(MCInst *MI, bool status)
static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
{
switch (MI->csh->mode) {
switch (x86_get_bit_mode(MI->csh->mode)) {
case CS_MODE_16:
switch (MI->flat_insn->id) {
default:
@@ -185,7 +185,7 @@ static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
case X86_FSTENVm:
case X86_FLDENVm:
// TODO: fix this in tablegen instead
switch (MI->csh->mode) {
switch (x86_get_bit_mode(MI->csh->mode)) {
default: // never reach
break;
case CS_MODE_16:
@@ -438,7 +438,7 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
}
// DI accesses are always ES-based on non-64bit mode
if (MI->csh->mode != CS_MODE_64) {
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
SStream_concat0(O, "%es:(");
if (MI->csh->detail_opt) {
MI->flat_insn->detail->x86
@@ -562,8 +562,10 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
.operands[MI->flat_insn->detail->x86.op_count]
.mem.disp = imm;
if (imm < 0) {
SStream_concat(O, "0x%" PRIx64,
arch_masks[MI->csh->mode] & imm);
SStream_concat(
O, "0x%" PRIx64,
arch_masks[x86_get_bit_mode(MI->csh->mode)] &
imm);
} else {
if (imm > HEX_THRESHOLD)
SStream_concat(O, "0x%" PRIx64, imm);
@@ -635,8 +637,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
MI->address;
// truncate imm for non-64bit
if (MI->csh->mode != CS_MODE_64) {
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
imm = imm & 0xffffffff;
} else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) &&
MI->imm_size == 2) {
imm &= 0xffff;
}
if (imm < 0) {
@@ -937,7 +942,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
if (DispVal < 0) {
SStream_concat(
O, "0x%" PRIx64,
arch_masks[MI->csh->mode] &
arch_masks[x86_get_bit_mode(
MI->csh->mode)] &
DispVal);
} else {
if (DispVal > HEX_THRESHOLD)
@@ -1049,7 +1055,7 @@ void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
// TODO: Probably this hack should be redesigned via InstAlias in
// InstrInfo.td as soon as Requires clause is supported properly
// for InstAlias.
if (MI->csh->mode == CS_MODE_64 &&
if ((x86_has_feature(MI->csh->mode, CS_MODE_64)) &&
MCInst_getOpcode(MI) == X86_CALLpcrel32) {
SStream_concat0(OS, "callq\t");
MCInst_setOpcodePub(MI, X86_INS_CALL);
+1 -9
View File
@@ -1347,15 +1347,7 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len,
//memset(instr->flat_insn->detail, 0, offsetof(cs_detail, x86)+offsetof(cs_x86, operands));
}
if (handle->mode & CS_MODE_16)
ret = decodeInstruction(&insn, reader, &info, address,
MODE_16BIT);
else if (handle->mode & CS_MODE_32)
ret = decodeInstruction(&insn, reader, &info, address,
MODE_32BIT);
else
ret = decodeInstruction(&insn, reader, &info, address,
MODE_64BIT);
ret = decodeInstruction(&insn, reader, &info, address, handle->mode);
if (ret) {
// *size = (uint16_t)(insn.readerCursor - address);
+33 -10
View File
@@ -1139,7 +1139,7 @@ static uint16_t resolveMandatoryPrefixConflict(struct InternalInstruction *insn,
* @return - 0 if the ModR/M could be read when needed or was not needed;
* nonzero otherwise.
*/
static int getID(struct InternalInstruction *insn)
static int getID(struct InternalInstruction *insn, cs_mode mode)
{
uint16_t attrMask;
uint16_t instructionID;
@@ -1273,8 +1273,8 @@ static int getID(struct InternalInstruction *insn)
attrMask ^= ATTR_ADSIZE;
/*
* In 64-bit mode all f64 superscripted opcodes ignore opcode size prefix
* CALL/JMP/JCC instructions need to ignore 0x66 and consume 4 bytes
* CALL/JMP ignore 66 in 64-bit mode. Near Jcc preserve their previous
* behavior unless an Intel or AMD mode is selected.
*/
if ((insn->mode == MODE_64BIT) && insn->hasOpSize) {
switch (insn->opcode) {
@@ -1287,6 +1287,8 @@ static int getID(struct InternalInstruction *insn)
insn->displacementSize = 4;
}
break;
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
@@ -1302,7 +1304,25 @@ static int getID(struct InternalInstruction *insn)
case 0x8E:
case 0x8F:
// Take care of lea and three byte ops.
if (insn->opcodeType == TWOBYTE) {
if (insn->opcodeType != TWOBYTE)
break;
if ((x86_has_feature(mode, CS_MODE_X86_INTEL) ||
x86_has_feature(mode, CS_MODE_X86_AMD)) &&
insn->vectorExtensionType == TYPE_NO_VEX_XOP) {
if ((x86_has_feature(mode, CS_MODE_X86_AMD)) &&
!wFromREX(insn->rexPrefix)) {
attrMask |= ATTR_OPSIZE;
insn->immediateSize = 2;
insn->displacementSize = 2;
insn->immSize = 2;
} else {
attrMask &= ~ATTR_OPSIZE;
insn->immediateSize = 4;
insn->displacementSize = 4;
insn->immSize = 8;
}
} else if (insn->opcode >= 0x82) {
attrMask ^= ATTR_OPSIZE;
insn->immediateSize = 4;
insn->displacementSize = 4;
@@ -2507,22 +2527,25 @@ static bool checkPrefix(struct InternalInstruction *insn)
* any internal state.
* @param startLoc - The address (in the reader's address space) of the first
* byte in the instruction.
* @param mode - The mode (real mode, IA-32e, or IA-32e in 64-bit mode) to
* decode the instruction in.
* @param mode - Capstone mode flags.
* @return - 0 if instruction is valid; nonzero if not.
*/
int decodeInstruction(struct InternalInstruction *insn, byteReader_t reader,
const void *readerArg, uint64_t startLoc,
DisassemblerMode mode)
const void *readerArg, uint64_t startLoc, cs_mode mode)
{
insn->reader = reader;
insn->readerArg = readerArg;
insn->startLocation = startLoc;
insn->readerCursor = startLoc;
insn->mode = mode;
if (x86_has_feature(mode, CS_MODE_16))
insn->mode = MODE_16BIT;
else if (x86_has_feature(mode, CS_MODE_32))
insn->mode = MODE_32BIT;
else
insn->mode = MODE_64BIT;
insn->numImmediatesConsumed = 0;
if (readPrefixes(insn) || readOpcode(insn) || getID(insn) ||
if (readPrefixes(insn) || readOpcode(insn) || getID(insn, mode) ||
insn->instructionID == 0 || checkPrefix(insn) || readOperands(insn))
return -1;
+3 -3
View File
@@ -25,6 +25,7 @@
#include <stdio.h>
#endif
#include "../../include/capstone/capstone.h"
#include "X86DisassemblerDecoderCommon.h"
/*
@@ -700,12 +701,11 @@ typedef struct InternalInstruction {
* specific to the logger. May be NULL.
* @param startLoc - The address (in the reader's address space) of the first
* byte in the instruction.
* @param mode - The mode (16-bit, 32-bit, 64-bit) to decode in.
* @param mode - Capstone mode flags.
* @return - Nonzero if there was an error during decode, 0 otherwise.
*/
int decodeInstruction(struct InternalInstruction *insn, byteReader_t reader,
const void *readerArg, uint64_t startLoc,
DisassemblerMode mode);
const void *readerArg, uint64_t startLoc, cs_mode mode);
//const char *x86DisassemblerGetInstrName(unsigned Opcode, const void *mii);
+14 -7
View File
@@ -93,7 +93,7 @@ static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
break;
}
switch (MI->csh->mode) {
switch (x86_get_bit_mode(MI->csh->mode)) {
case CS_MODE_16:
switch (MI->flat_insn->id) {
default:
@@ -209,7 +209,7 @@ static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
case X86_FSTENVm:
case X86_FLDENVm:
// TODO: fix this in tablegen instead
switch (MI->csh->mode) {
switch (x86_get_bit_mode(MI->csh->mode)) {
default: // never reach
break;
case CS_MODE_16:
@@ -564,7 +564,7 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
}
// DI accesses are always ES-based on non-64bit mode
if (MI->csh->mode != CS_MODE_64) {
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
SStream_concat0(O, "es:[");
if (MI->csh->detail_opt) {
MI->flat_insn->detail->x86
@@ -700,7 +700,10 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
.mem.disp = imm;
if (imm < 0)
printImm(MI, O, arch_masks[MI->csh->mode] & imm, true);
printImm(MI, O,
arch_masks[x86_get_bit_mode(MI->csh->mode)] &
imm,
true);
else
printImm(MI, O, imm, true);
}
@@ -865,8 +868,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
uint8_t opsize = X86_immediate_size(MI->Opcode, NULL);
// truncate imm for non-64bit
if (MI->csh->mode != CS_MODE_64) {
if (!(x86_has_feature(MI->csh->mode, CS_MODE_64))) {
imm = imm & 0xffffffff;
} else if ((x86_has_feature(MI->csh->mode, CS_MODE_X86_AMD)) &&
MI->imm_size == 2) {
imm &= 0xffff;
}
printImm(MI, O, imm, true);
@@ -1205,11 +1211,12 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
}
} else {
// memory reference to an immediate address
if (MI->csh->mode == CS_MODE_64)
if (x86_has_feature(MI->csh->mode, CS_MODE_64))
MI->op1_size = 8;
if (DispVal < 0) {
printImm(MI, O,
arch_masks[MI->csh->mode] &
arch_masks[x86_get_bit_mode(
MI->csh->mode)] &
DispVal,
true);
} else {
+19 -18
View File
@@ -715,9 +715,9 @@ const char *X86_reg_name(csh handle, unsigned int reg)
return NULL;
if (reg == X86_REG_EFLAGS) {
if (ud->mode & CS_MODE_32)
if (x86_has_feature(ud->mode, CS_MODE_32))
return "eflags";
if (ud->mode & CS_MODE_64)
if (x86_has_feature(ud->mode, CS_MODE_64))
return "rflags";
}
@@ -900,6 +900,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
if (h->detail_opt) {
#ifndef CAPSTONE_DIET
cs_mode mode = x86_get_bit_mode(h->mode);
memcpy(insn->detail->regs_read, insns[i].regs_use,
sizeof(insns[i].regs_use));
insn->detail->regs_read_count =
@@ -916,7 +917,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insns[i].regs_mod);
break;
case X86_RDTSC:
if (h->mode == CS_MODE_64) {
if (mode == CS_MODE_64) {
memcpy(insn->detail->regs_write,
insns[i].regs_mod,
sizeof(insns[i].regs_mod));
@@ -932,7 +933,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
}
break;
case X86_RDTSCP:
if (h->mode == CS_MODE_64) {
if (mode == CS_MODE_64) {
memcpy(insn->detail->regs_write,
insns[i].regs_mod,
sizeof(insns[i].regs_mod));
@@ -958,7 +959,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_LOOPE:
case X86_INS_LOOPNE:
// The instruction pointer register follows the mode.
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1012,7 +1013,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_LODSD:
case X86_INS_LODSQ:
case X86_INS_LODSW:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1046,7 +1047,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_STOSD:
case X86_INS_STOSQ:
case X86_INS_STOSW:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1080,7 +1081,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_MOVSW:
case X86_INS_MOVSD:
case X86_INS_MOVSQ:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1124,7 +1125,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_ENTER:
case X86_INS_LEAVE:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1168,7 +1169,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_INSB:
case X86_INS_INSW:
case X86_INS_INSD:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1197,7 +1198,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_OUTSB:
case X86_INS_OUTSW:
case X86_INS_OUTSD:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_64:
@@ -1239,7 +1240,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_OUTSB:
case X86_INS_OUTSW:
case X86_INS_OUTSD:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1254,7 +1255,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
case X86_INS_JMP:
case X86_INS_LJMP:
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1281,7 +1282,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
break;
case X86_INS_SYSENTER: {
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1308,7 +1309,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
break;
} break;
case X86_INS_SYSEXIT: {
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -1364,7 +1365,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
X86_GRP_JUMP;
insn->detail->groups_count++;
switch (h->mode) {
switch (mode) {
default:
break;
case CS_MODE_16:
@@ -2222,9 +2223,9 @@ static void add_cx(MCInst *MI)
if (MI->csh->detail_opt) {
x86_reg cx;
if (MI->csh->mode & CS_MODE_16)
if (x86_has_feature(MI->csh->mode, CS_MODE_16))
cx = X86_REG_CX;
else if (MI->csh->mode & CS_MODE_32)
else if (x86_has_feature(MI->csh->mode, CS_MODE_32))
cx = X86_REG_ECX;
else // 64-bit
cx = X86_REG_RCX;
+10
View File
@@ -104,4 +104,14 @@ void X86_build_lookup_tables(cs_struct *h);
void X86_postprinter(csh handle, cs_insn *insn, SStream *mnem, MCInst *mci);
static inline bool x86_has_feature(cs_mode mode, int flag)
{
return (mode & flag) == flag;
}
static inline int x86_get_bit_mode(cs_mode mode)
{
return mode & (CS_MODE_64 | CS_MODE_32 | CS_MODE_16);
}
#endif
+13 -3
View File
@@ -13,6 +13,10 @@
cs_err X86_global_init(cs_struct *ud)
{
MCRegisterInfo *mri;
if (x86_has_feature(ud->mode, CS_MODE_X86_AMD) &&
x86_has_feature(ud->mode, CS_MODE_X86_INTEL))
return CS_ERR_MODE;
mri = cs_mem_calloc(1, sizeof(*mri));
if (!mri)
return CS_ERR_MEM;
@@ -33,7 +37,7 @@ cs_err X86_global_init(cs_struct *ud)
ud->reg_access = X86_reg_access;
#endif
if (ud->mode == CS_MODE_64)
if (x86_has_feature(ud->mode, CS_MODE_64))
ud->regsize_map = regsize_map_64;
else
ud->regsize_map = regsize_map_32;
@@ -49,12 +53,18 @@ cs_err X86_option(cs_struct *handle, cs_opt_type type, size_t value)
default:
break;
case CS_OPT_MODE:
if (value == CS_MODE_64)
if ((x86_has_feature(value, CS_MODE_X86_INTEL) &&
x86_has_feature(value, CS_MODE_X86_AMD)))
return CS_ERR_OPTION;
if (x86_has_feature(value, CS_MODE_64))
handle->regsize_map = regsize_map_64;
else
handle->regsize_map = regsize_map_32;
handle->mode = (cs_mode)value;
handle->mode = (cs_mode)(value &
(CS_MODE_16 | CS_MODE_32 | CS_MODE_64 |
CS_MODE_X86_INTEL | CS_MODE_X86_AMD));
break;
case CS_OPT_SYNTAX:
switch (value) {
+4
View File
@@ -45,6 +45,8 @@ __all__ = [
"CS_MODE_16",
"CS_MODE_32",
"CS_MODE_64",
"CS_MODE_X86_INTEL",
"CS_MODE_X86_AMD",
"CS_MODE_ARM",
"CS_MODE_THUMB",
"CS_MODE_MCLASS",
@@ -353,6 +355,8 @@ CS_MODE_ARM = 0 # ARM mode
CS_MODE_16 = 1 << 1 # 16-bit mode (for X86)
CS_MODE_32 = 1 << 2 # 32-bit mode (for X86)
CS_MODE_64 = 1 << 3 # 64-bit mode (for X86, PPC)
CS_MODE_X86_INTEL = 1 << 4
CS_MODE_X86_AMD = 1 << 5
CS_MODE_THUMB = 1 << 4 # ARM's Thumb mode, including Thumb-2
CS_MODE_MCLASS = 1 << 5 # ARM's Cortex-M series
CS_MODE_V8 = 1 << 6 # ARMv8 A32 encodings for ARM
+1 -1
View File
@@ -123,7 +123,7 @@ typedef struct cs_arch_config {
X86_global_init, \
X86_option, \
~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | \
CS_MODE_16), \
CS_MODE_16 | CS_MODE_X86_INTEL | CS_MODE_X86_AMD), \
}
#define CS_ARCH_CONFIG_PPC \
{ \
+4
View File
@@ -285,6 +285,10 @@ Nonetheless, we hope this additional information is useful to you.
- Decoding of conflicting segment overrides was changed to match CPU behavior:
For instructions with both an FS/GS and a ES/CS/SS/DS overrides the FS/GS override now takes priority, regardless of prefix ordering.
- Decoding of instructions with multiple mandatory prefixes was fixed. (e.g., `shld` with a data size override and a redundant `F3` prefix, or `addss` with an additional `66` prefix)
- Added `CS_MODE_X86_INTEL` and `CS_MODE_X86_AMD` to select ISA specific quirks.
Currently this is only:
- How `66`-prefixed near conditional jumps are decoded in 64-bit mode (see flag documentation).
Without either flag, the previous LLVM behavior is preserved.
**BPF**
+7
View File
@@ -148,6 +148,13 @@ typedef enum cs_mode {
CS_MODE_16 = 1 << 1, ///< 16-bit mode (X86)
CS_MODE_32 = 1 << 2, ///< 32-bit mode (X86)
CS_MODE_64 = 1 << 3, ///< 64-bit mode (X86, PPC)
// X86
/// x86 Intel specific quirks:
/// - Ignore 66-prefix near Jcc in 64-bit mode.
CS_MODE_X86_INTEL = 1 << 4,
/// x86 AMD specific quirks:
/// - Honor 66-prefix near Jcc in 64-bit mode, unless REX.W overrides it.
CS_MODE_X86_AMD = 1 << 5,
// ARM
CS_MODE_THUMB = 1 << 4, ///< ARM's Thumb mode, including Thumb-2
CS_MODE_MCLASS = 1 << 5, ///< ARM's Cortex-M series
+2
View File
@@ -253,6 +253,8 @@ static const cs_enum_id_map test_mode_map[] = {
{ .str = "CS_MODE_TRICORE_180", .val = CS_MODE_TRICORE_180 },
{ .str = "CS_MODE_V8", .val = CS_MODE_V8 },
{ .str = "CS_MODE_V9", .val = CS_MODE_V9 },
{ .str = "CS_MODE_X86_AMD", .val = CS_MODE_X86_AMD },
{ .str = "CS_MODE_X86_INTEL", .val = CS_MODE_X86_INTEL },
{ .str = "CS_MODE_XTENSA_ESP32", .val = CS_MODE_XTENSA_ESP32 },
{ .str = "CS_MODE_XTENSA_ESP32S2", .val = CS_MODE_XTENSA_ESP32S2 },
{ .str = "CS_MODE_XTENSA_ESP32S3", .val = CS_MODE_XTENSA_ESP32S3 },
+236
View File
@@ -0,0 +1,236 @@
test_cases:
- input:
name: "Jcc DEFAULT: JO rel16"
bytes: [0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL]
address: 0
expected:
insns:
- asm_text: "jo 0xfffffffffffffad3"
size: 5
details:
x86:
enc_imm_offset: 3
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: -1325
size: 4
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
size: 1
- input:
name: "Jcc DEFAULT: JB rel32"
bytes: [0x66, 0x0f, 0x82, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL]
address: 0
expected:
insns:
- asm_text: "jb 0xffffffffd8a5fad5"
size: 7
details:
x86:
enc_imm_size: 4
operands:
- type: X86_OP_IMM
imm: -660210987
size: 4
- input:
name: "Jcc AMD: JO rel16 and following MOVSD"
bytes: [0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
address: 0x123450000
expected:
insns:
- asm_text: "jo 0xfad3"
size: 5
details:
x86:
enc_imm_offset: 3
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: 0xfad3
size: 2
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
size: 1
- input:
name: "Jcc AMD: JNO in AT&T syntax"
bytes: [0x66, 0x0f, 0x81, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD, CS_OPT_SYNTAX_ATT]
address: 0
expected:
insns:
- asm_text: "jno 0xfad3"
size: 5
details:
x86:
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: 0xfad3
size: 2
- asm_text: "movsl (%rsi), (%rdi)"
size: 1
- input:
name: "Jcc AMD: JB target wraparound"
bytes: [0x66, 0x0f, 0x82, 0x01, 0x00]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
address: 0xfffe
expected:
insns:
- asm_text: "jb 4"
size: 5
details:
x86:
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: 4
size: 2
- input:
name: "Jcc AMD: REX.W overrides 66"
bytes: [0x66, 0x48, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
address: 0
expected:
insns:
- asm_text: "jo 0xffffffffd8a5fad6"
size: 8
details:
x86:
enc_imm_offset: 4
enc_imm_size: 4
operands:
- type: X86_OP_IMM
imm: -660210986
size: 8
- input:
name: "Jcc AMD: 66 after REX.W"
bytes: [0x48, 0x66, 0x0f, 0x80, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
address: 0
expected:
insns:
- asm_text: "jo 0xfad4"
size: 6
details:
x86:
enc_imm_offset: 4
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: 0xfad4
size: 2
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
size: 1
- input:
name: "Jcc Intel: JG rel32"
bytes: [0x66, 0x0f, 0x8f, 0xce, 0xfa, 0xa5, 0xd8]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL]
address: 0
expected:
insns:
- asm_text: "jg 0xffffffffd8a5fad5"
size: 7
details:
x86:
enc_imm_size: 4
operands:
- type: X86_OP_IMM
imm: -660210987
size: 8
- input:
name: "Jcc AMD: JG rel16"
bytes: [0x66, 0x0f, 0x8f, 0xce, 0xfa]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_AMD]
address: 0
expected:
insns:
- asm_text: "jg 0xfad3"
size: 5
details:
x86:
enc_imm_size: 2
operands:
- type: X86_OP_IMM
imm: 0xfad3
size: 2
- input:
name: "Jcc Intel flag preserves 64-bit operands and registers"
bytes: [0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x48, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x31, 0xd9, 0x20, 0xa5, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc3]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_MODE_X86_INTEL, CS_OPT_DETAIL]
address: 0x100000000
expected:
insns:
- asm_text: "mov rax, 0xffffffffffffffff"
details:
x86:
operands:
- type: X86_OP_REG
reg: rax
size: 8
- type: X86_OP_IMM
imm: -1
size: 8
- asm_text: "movabs rax, qword ptr [0xffffffffffffffff]"
- asm_text: "rdtsc"
details:
regs_write: [rax, rdx]
- asm_text: "fldenv [rax]"
details:
x86:
operands:
- type: X86_OP_MEM
mem_base: rax
size: 28
- asm_text: "movsd dword ptr [rdi], dword ptr [rsi]"
details:
regs_read: [rdi, rsi, rflags]
regs_write: [rdi, rsi]
- asm_text: "call 0x10000001b"
- asm_text: "ret"
- input:
name: "Jcc AMD flag preserves 64-bit operands and registers in AT&T syntax"
bytes: [0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x48, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x31, 0xd9, 0x20, 0xa5, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc3]
arch: CS_ARCH_X86
options: [CS_MODE_64, CS_MODE_X86_AMD, CS_OPT_DETAIL, CS_OPT_SYNTAX_ATT]
address: 0x100000000
expected:
insns:
- asm_text: "movq $0xffffffffffffffff, %rax"
details:
x86:
operands:
- type: X86_OP_IMM
imm: -1
size: 8
- type: X86_OP_REG
reg: rax
size: 8
- asm_text: "movabsq 0xffffffffffffffff, %rax"
- asm_text: "rdtsc"
details:
regs_write: [rax, rdx]
- asm_text: "fldenv (%rax)"
details:
x86:
operands:
- type: X86_OP_MEM
mem_base: rax
size: 28
- asm_text: "movsl (%rsi), (%rdi)"
details:
regs_read: [rdi, rsi, rflags]
regs_write: [rdi, rsi]
- asm_text: "callq 0x10000001b"
- asm_text: "retq"
+22
View File
@@ -7207,3 +7207,25 @@ test_cases:
regs_read: [ rsp, ss ]
regs_write: [ rsp, rip ]
groups: [ ret, mode64 ]
-
input:
name: "issue 3037 x86-64 Intel JO ignores operand-size override"
bytes: [ 0x66,0x0f,0x80,0xce,0xfa,0xa5,0xd8 ]
arch: "CS_ARCH_X86"
options: [ CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL ]
address: 0x0
expected:
insns:
-
asm_text: "jo 0xffffffffd8a5fad5"
-
input:
name: "issue 3037 x86-64 Intel JNO ignores operand-size override"
bytes: [ 0x66,0x0f,0x81,0xce,0xfa,0xa5,0xd8 ]
arch: "CS_ARCH_X86"
options: [ CS_MODE_64, CS_OPT_DETAIL, CS_MODE_X86_INTEL ]
address: 0x0
expected:
insns:
-
asm_text: "jno 0xffffffffd8a5fad5"