Intel® X86 Encoder Decoder: Intel® XED command interface

Intel® X86 Encoder Decoder

Loading...
Searching...
No Matches
Intel® XED command interface

The command line tool called xed or xed.exe is built when you build the examples (Examples of using Intel® XED) that come with Intel® XED.

This tool is useful for encoding and decoding or even decoding-then-re-encoding a single instruction or all the instructions in the text segment of an ELF binary (32 or 64b). For decoding, just jump to the examples.

This section also explains a little language for writing the instructions for encode requests (-e option). This tool is constantly updated. The xed-enc (xed-enc.exe) example is just the encoder portion of the xed command line tool.

The SUPPRESSED operands emitted by the decoder are not used when encoding. They are ignored. They are not required to select an encoding.

The syntax for encodable strings is as follows:

Opcode[/width] [operand [operand]]

The width is a 8, 16, 32 or 64, indicating the effective operand width if it differs from the default. 8b operations generally require this. Or since most operations that default to 32b widths in 64b mode, it is required for 64b operation widths in 64b mode.

The operand specifier is one of the following.

- A register name such as EAX or R8B, etc. Case does not matter.
- An immediate specifier such as IMM:12ff
- A branch displacement specifier such as RELBR:0000001f for instructions that use relative offsets
- A branch displacement specifier such as ABSBR:0000001f0000001f for instructions that specify an absolute address
- A memory specifier that indicates the base register, index register, scale value, and displacement value. If one of the fields is not required, a - is necessary. The displacement is omittable. For example: MEM4:ESI,EAX,8,ff or MEM4:EBX. The first one specifies that the memory address 4 bytes and should be ESI + EAX * 8 + 0xff. The second one specifies that EBX should be used to access 4 bytes of memory; note the displacement is omitted. A segment override can be specified as follows: MEM4:GS:EAX by using a segment-name followed by a ":" before the base register. If there is no base register, you can use a "-", for example: MEM4:GS:-,-,11223344. One also needs to specify a memory operation width. This can be accomplished by indicating a number of bytes just after the MEM specifier. For example: MEM2:EAX indicates a 2 byte memory operation.
- An address generation specifer that has the same syntax as the above MEM: specifier, but is only used for LEA instructions. Example: AGEN:EAX,EBX,2,-

Here is the help message:

% xed -h
Usage: xed [options]
One of the following is required:
-i input_file (decode pecoff-format file)
-ir raw_input_file (decode a raw unformatted binary file)
-ih hex_input_file (decode a raw unformatted ASCII hex file)
-d hex-string (decode a sequence of bytes, must be last)
-j (just decode one instruction when using -d)
-F prefix (decode ascii hex bytes after prefix)
(running in filter mode from stdin)
-ide input_file (decode/encode file)
-e instruction (encode, must be last)
-f (encode force, skip encoder chip check)
-ie file-to-assemble (assemble the contents of the file)
-de hex-string (decode-then-encode, must be last)
Optional arguments:
-v N (0=quiet, 1=errors, 2=useful-info, 3=trace,
5=very verbose)
-xv N (XED engine verbosity, 0...99)
-chip-check CHIP (count instructions that are not valid for CHIP)
-chip-check-list (list the valid chips)
-s section (target section for file disassembly,
PECOFF and ELF formats only)
-n N (number of instructions to decode. Default 100M,
accepts K/M/G qualifiers)
-b addr (Base address offset, for DLLs/shared libraries.
Use 0x for hex addresses)
-as addr (Address to start disassembling.
Use 0x for hex addresses)
-ae addr (Address to end disassembling.
Use 0x for hex addresses)
-no-resync (Disable symbol-based resynchronization algorithm
for disassembly)
-ast (Show the AVX/SSE transition classfication)
-histo (Histogram decode times)
-I (Intel syntax for disassembly)
-A (ATT SYSV syntax for disassembly)
-isa-set (Emit the XED "ISA set" in dissasembly)
-xml (XML formatting)
-uc (upper case hex formatting)
-pmd (positive memory displacement formatting)
-nwm (Format AVX512 without curly braces for writemasks, include k0)
-emit-ignored-branch-hint (emit ignored branch hints during disassembly)
-emit (Output __emit statements for the Intel compiler)
-S file Read symbol table in "nm" format from file
-dot FN (Emit a register dependence graph file in dot format.
Best used with -as ADDR -ae ADDR to limit graph size.)
-r (for REAL_16 mode, 16b addressing (20b addresses),
16b default data size)
-r32 (for REAL_32 mode, 16b addressing (20b addresses),
32b default data size)
-16 (for LEGACY_16 mode, 16b addressing,
16b default data size)
-32 (for LEGACY_32 mode, 32b addressing,
32b default data size -- default)
-64 (for LONG_64 mode w/64b addressing
Optional on windows/linux)
-mpx (Turn on MPX mode for disassembly, default is off)
-cet (Turn on CET mode for disassembly, default is off)
-s32 (32b stack addressing, default, not in LONG_64 mode)
-s16 (16b stack addressing, not in LONG_64 mode)
-set OP VAL (Set a XED operands to some integer value, repeatable)
-version (The version message)
-help (This help message)

Here are a couple of examples:

% xed -d 0000
ICLASS: ADD
CATEGORY: BINARY
EXTENSION: BASE
IFORM: ADD_MEMb_GPR8
ISA_SET: I86
ATTRIBUTES: BYTEOP LOCKABLE
SHORT: add byte ptr [eax], al
% xed -e ADD EAX EBX
Request: ADD MODE:1, REG0:EAX, REG1:EBX, SMODE:1
OPERAND ORDER: REG0 REG1
Encodable! 01D8
.byte 0x01,0xd8
% xed -e ADD EAX MEM4:ESP,EBX,4
Request: ADD EASZ:2, MEM0:dword ptr [ESP+EBX*4], MEM_WIDTH:4, MODE:1, REG0:EAX, SMODE:1
OPERAND ORDER: REG0 MEM0
Encodable! 03049C
.byte 0x03,0x04,0x9c
% xed -d 6a00
ICLASS: PUSH
CATEGORY: PUSH
EXTENSION: BASE
IFORM: PUSH_IMMb
ISA_SET: I186
ATTRIBUTES: FIXED_BASE0 SCALABLE STACKPUSH0
SHORT: push 0x0
% xed -e MOV EAX MEM4:SS:ESP
Request: MOV EASZ:2, MEM0:dword ptr SS[ESP], MEM_WIDTH:4, MODE:1, REG0:EAX, SMODE:1
OPERAND ORDER: REG0 MEM0
Encodable! 8B0424
.byte 0x8b,0x04,0x24
% xed -64 -set DFV 14 -e CCMPB r8b r9b
Request: CCMPB DFV:14, MODE:2, REG0:R8B, REG1:R9B, SMODE:2
OPERAND ORDER: REG0 REG1
Encodable! 6254740238C8
.byte 0x62,0x54,0x74,0x02,0x38,0xc8

Or using the xed-enc example tool:

% obj/xed-enc
Usage: obj/xed-enc [-16|-32|-64] [-s16|-s32] encode-string

The -16, -32 or -64 are for specifying the major mode of the machine. The major mode of the machine determines the default data operand size and default addressing width. In 64b mode, the default data size is 32b and the default addressing mode is 64b addressing. In 32b mode, the default addressing width is 32b. In 16b mode, the default addressing width is 16b. In 32b mode or 16b mode, the stack addressing width must also be specified. Usually it matches the major mode. The -s16 option is for specifying 16b stack addressing in 32b mode. The -s32 is for specifying 32b stack addressing in 16 bit mode.

% obj/xed-enc -64 PUSH/64 RAX
Encode request:
PUSH EOSZ:3, MODE:2, REG0:RAX, SMODE:2
OPERAND ORDER: REG0
Encodable! 50
% obj/xed-enc MOV MEM4:EAX IMM:11223344
Encode request:
MOV EASZ:2, IMM0:0x11223344, IMM_WIDTH:32, MEM0:dword ptr [EAX], MEM_WIDTH:4, MODE:1, SMODE:1
OPERAND ORDER: MEM0 IMM0
Encodable! C70044332211

# An example of using the encoder

The encoder language file which is part of the xed command line tool shows how to build up instructions from scratch. The example uses a string to drive the creation of the instruction, but that is just an example. Look at the parse_encode_request function for the required pieces.

/* BEGIN_LEGAL
Copyright (c) 2026 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
END_LEGAL */
#include <assert.h>
#include <string.h>
#include <stdlib.h> // strtol, ...
#include "xed/xed-interface.h"
#include "xed-examples-util.h"
#include "xed-util-enc-lang.h"
#define BUF_LEN 50
static void upcase(char* s) {
(void)xed_upcase_buf(s);
}
xed_str_list_t*
tokenize(char const* const s,
char const* const delimiter)
{
xed_str_list_t* slist = xed_tokenize(s, delimiter);
return slist;
}
xed_bool_t is_empty_buf(char const* const buffer)
{
// indicate whether given buffer is empty by insuring first element is \0
if (*buffer == '\0')
return 1;
return 0;
}
void slash_split(char const* const src,
char* first, // output
char* second) //output
{
xed_str_list_t* sv = tokenize(src, "/");
xed_str_list_t* p = sv;
xed_uint_t i=0;
*first = 0;
*second = 0;
for(; p ; i++, p=p->next)
{
if (i==0) {
xed_strncpy(first, p->s, BUF_LEN-1);
}
else if (i==1) {
xed_strncpy(second, p->s, BUF_LEN-1);
}
}
xed_free_token_list(sv);
}
typedef struct {
xed_bool_t valid;
unsigned int width_bits;
xed_uint64_t immed_val;
} immed_parser_t;
static void immed_parser_init(immed_parser_t* self,
char const* const s,
char const* const tok0)
{
xed_str_list_t* sv = tokenize(s,":");
xed_uint_t sz = xed_str_list_size(sv);
self->valid = 0;
if (sz==2) {
xed_str_list_t* p = sv;
xed_uint_t i = 0;
for(; p ; i++, p=p->next)
{
if (i == 0 && strcmp(p->s,tok0) != 0)
{
break;
}
else if (i == 1) {
self->immed_val = convert_ascii_hex_to_int(p->s);
// nibbles to bits
self->width_bits = XED_CAST(unsigned int,strlen(p->s)*4);
self->valid = 1;
}
}
}
xed_free_token_list(sv);
}
typedef struct {
xed_bool_t valid;
xed_reg_enum_t segment_reg;
xed_uint_t segno;
} seg_parser_t;
static void seg_parser_init(seg_parser_t* self,
char const* const s)
{
xed_str_list_t* sv = tokenize(s,":");
xed_uint_t ntokens = xed_str_list_size(sv);
self->valid=0;
self->segment_reg= XED_REG_INVALID;
self->segno=0;
if (ntokens == 2)
{
xed_str_list_t* p = sv;
xed_uint_t i = 0;
xed_uint_t segid = 99;
for(; p ; i++, p=p->next)
{
if (i == 0)
{
if (strcmp(p->s,"SEG")==0 || strcmp(p->s,"SEG0")==0)
segid = 0;
else if (strcmp(p->s,"SEG1")==0)
segid = 1;
}
else if (i == 1 && segid < 2)
{
self->segno = segid;
self->segment_reg = str2xed_reg_enum_t(p->s);
if (self->segment_reg != XED_REG_INVALID &&
xed_reg_class(self->segment_reg) == XED_REG_CLASS_SR)
{
self->valid=1;
}
}
}
}
xed_free_token_list(sv);
}
static void
list2array(char** array, xed_str_list_t* sl, xed_uint_t n)
{
xed_uint_t i=0;
xed_str_list_t* p = sl;
for( ; p && i < n ; i++, p=p->next)
array[i] = p->s;
}
static xed_uint_t match(char const* const s, char const* const b)
{
if (strcmp(s,b)==0)
return 1;
return 0;
}
static xed_uint_t skip(char const* const s)
{
if (match(s,"-") || match(s,"NA"))
return 1;
return 0;
}
typedef struct
{
xed_bool_t valid;
xed_bool_t mem;
xed_bool_t agen;
xed_bool_t disp_valid;
char segment[BUF_LEN];
char base[BUF_LEN];
char indx[BUF_LEN];
char scale[BUF_LEN];
char disp[BUF_LEN]; //displacement
xed_reg_enum_t segment_reg;
xed_reg_enum_t base_reg;
xed_reg_enum_t index_reg;
xed_uint8_t scale_val;
xed_int64_t disp_val;
unsigned int disp_width_bits;
xed_uint_t mem_len;
} mem_bis_parser_t;
// parse: MEMlength:[segment:]base,index,scale[,displacement]
// parse: AGEN:base,index,scale[,displacement]
// The displacement is optional
// split on colons first
// MEM4:FS:EAX,EBX,4,223344 mem4 fs eax,ebx,4,22334455 -> 3 tokens
// MEM4:FS:EAX,EBX,4 mem4 fs eax,ebx,4 -> 3 tokens
// MEM4:EAX,EBX,4,223344 mem4 eax,ebx,4,223344.. -> 2 tokens
// MEM4:FS:EAX,EBX,4 mem4 fs eas,ebx,4 -> 3 tokens
static void mem_bis_parser_init(mem_bis_parser_t* self, char* s)
{
xed_str_list_t* sv=0;
xed_uint_t ntokens=0;
xed_uint_t n_addr_tokens=0;
char addr_token[BUF_LEN]={0};
char main_token[BUF_LEN]={0};
xed_uint_t i=0;
xed_str_list_t* p = 0;
xed_str_list_t* sa = 0;
char* astr[4];
self->valid = 0;
self->mem = 0;
self->agen = 0;
self->disp_valid = 0;
xed_strncpy(self->segment, "INVALID", BUF_LEN-1);
xed_strncpy(self->base, "INVALID", BUF_LEN-1);
xed_strncpy(self->indx, "INVALID", BUF_LEN-1);
xed_strncpy(self->scale, "1", BUF_LEN-1);
xed_strncpy(self->disp, "", BUF_LEN-1);
self->segment_reg = XED_REG_INVALID;
self->base_reg = XED_REG_INVALID;
self->index_reg = XED_REG_INVALID;
self->disp_val = 0;
self->disp_width_bits = 0;
self->mem_len = 0;
self->scale_val = 1;
upcase(s);
// split on colon first
sv = tokenize(s,":");
ntokens = xed_str_list_size(sv);
i=0;
p = sv;
if (ntokens !=2 && ntokens != 3)
{
xed_free_token_list(sv);
return;
}
for( ; p ; i++, p=p->next) {
if (i==0)
xed_strncpy(main_token, p->s, BUF_LEN-1);
else if (i==1 && ntokens == 3)
xed_strncpy(self->segment, p->s, BUF_LEN-1);
else if (i==1 && ntokens == 2)
xed_strncpy(addr_token, p->s, BUF_LEN-1);
else if (i==2)
xed_strncpy(addr_token, p->s, BUF_LEN-1);
}
xed_free_token_list(sv);
assert(!is_empty_buf(main_token));
if (strcmp(main_token,"AGEN")==0)
self->agen=1;
else if (strncmp(main_token,"MEM",3)==0)
self->mem = 1;
else
return;
if (self->mem && strlen(main_token) > 3) {
char* mlen = main_token+3;
self->mem_len = XED_STATIC_CAST(xed_uint_t,strtol(mlen,0,0));
}
if (self->agen && strcmp(self->segment,"INVALID")!=0)
xedex_derror("AGENs cannot have segment overrides");
sa = tokenize(addr_token,",");
n_addr_tokens = xed_str_list_size(sa);
if (n_addr_tokens == 0 || n_addr_tokens > 4)
xedex_derror("Bad addressing mode syntax for memop");
list2array(astr, sa, n_addr_tokens);
if (!skip(astr[0]))
xed_strncpy(self->base, astr[0], BUF_LEN-1);
if (n_addr_tokens >= 2)
if (!skip(astr[1]))
xed_strncpy(self->indx, astr[1], BUF_LEN-1);
if (n_addr_tokens > 2)
xed_strncpy(self->scale, astr[2], BUF_LEN-1);
if (skip(self->scale))
xed_strncpy(self->scale, "1", BUF_LEN-1);
if (match(self->scale,"1") || match(self->scale,"2") ||
match(self->scale,"4") || match(self->scale,"8") ) {
self->valid=1;
self->scale_val = XED_CAST(xed_uint8_t,strtol(self->scale, 0, 10));
self->segment_reg = str2xed_reg_enum_t(self->segment);
self->base_reg = str2xed_reg_enum_t(self->base);
self->index_reg = str2xed_reg_enum_t(self->indx);
// look for a displacement
if (n_addr_tokens == 4 && strcmp(astr[3], "-") != 0) {
xed_uint64_t unsigned64_disp=0;
unsigned int nibbles = 0;
xed_strncpy(self->disp, astr[3], BUF_LEN-1);
self->disp_valid = 1;
nibbles = xed_strlen(self->disp);
if (nibbles & 1)
xedex_derror("Displacement must have an even number of nibbles");
unsigned64_disp = convert_ascii_hex_to_int(self->disp);
self->disp_width_bits = nibbles*4; // nibbles to bits
switch (self->disp_width_bits){
case 8: self->disp_val = xed_sign_extend8_64((xed_int8_t)unsigned64_disp);
break;
case 16: self->disp_val = xed_sign_extend16_64((xed_int16_t)unsigned64_disp);
break;
case 32: self->disp_val = xed_sign_extend32_64((xed_int32_t)unsigned64_disp);
break;
case 64: self->disp_val = (xed_int64_t)unsigned64_disp;
break;
}
}
}
xed_free_token_list(sa);
}
static void find_vl(xed_reg_enum_t reg, xed_int_t* vl)
{
// This will "grow" bad user settings. So if you try to specify /128 on
// the instruction and it sees a YMM or ZMM register operand, then
// it'll grow the VL to the right observed size. The right observed
// size might still be wrong, that is too small (as it can be for
// "shrinking" converts (PD2PS, PD2DQ, etc.).
xed_int_t nvl = *vl;
xed_reg_class_enum_t rc = xed_reg_class(reg);
if (rc == XED_REG_CLASS_XMM && nvl == -1) // not set and see xmm
*vl = 0;
else if (rc == XED_REG_CLASS_YMM && nvl < 1) // not set, set to xmm and then see ymm
*vl = 1;
#if defined(XED_SUPPORTS_AVX512)
else if (rc == XED_REG_CLASS_ZMM && nvl < 2) // not set, set to xmm or ymm and then see zmm
*vl = 2;
#endif
}
static inline void find_64bit_eow(xed_reg_enum_t reg, xed_int_t* eow)
{
// set the effective operand width for 64bit registers.
xed_reg_class_enum_t rc = xed_gpr_reg_class(reg);
if (rc == XED_REG_CLASS_GPR64 && *eow < 64)
*eow = 64;
}
xed_encoder_request_t
parse_encode_request(ascii_encode_request_t areq)
{
unsigned int i;
xed_encoder_request_t req;
xed_str_list_t* tokens = 0;
char cfirst[BUF_LEN]={0};
char csecond[BUF_LEN]={0};
unsigned int token_index = 0;
xed_str_list_t* p = 0;
xed_uint_t memop = 0;
xed_uint_t regnum = 0;
xed_uint_t operand_index = 0;
xed_iclass_enum_t iclass = XED_ICLASS_INVALID;
xed_int_t vl = -1;
xed_int_t eow = -1;
xed_int_t uvl = -1; // take VL from cmd
xed_int_t ueow = -1; // take effective operand width from cmd
// this calls xed_encoder_request_zero()
xed_encoder_request_zero_set_mode(&req,&(areq.dstate));
/* This is the important function here. This encodes an instruction
from scratch.
You must set:
the machine mode (machine width, addressing widths)
the iclass
for some instructions you need to specify prefixes (like REP or LOCK).
the operands:
operand kind (XED_OPERAND_{AGEN,MEM0,MEM1,IMM0,IMM1,
RELBR,ABSBR,PTR,REG0...REG15}
operand order
xed_encoder_request_set_operand_order(&req,operand_index,
XED_OPERAND_*);
where the operand_index is a sequential index starting at zero.
operand details
FOR MEMOPS: base,segment,index,scale,
displacement for memops,
FOR REGISTERS: register name
FOR IMMEDIATES: immediate values
*/
tokens = tokenize(areq.command," ");
p = tokens;
if (p)
{
slash_split(p->s, cfirst, csecond);
if (! is_empty_buf(cfirst))
{
upcase(cfirst);
if (CLIENT_VERBOSE3)
printf("[%s][%s][%s]\n", p->s,
(!is_empty_buf(cfirst)?cfirst:"NULL"),
(!is_empty_buf(cfirst)?csecond:"NULL"));
p = p->next; // consumed token, advance
}
}
// we can attempt to override the mode
if (!is_empty_buf(csecond))
{
if (strcmp(csecond,"8")==0)
ueow = 8;
else if (strcmp(csecond,"16")==0)
ueow = 16;
else if (strcmp(csecond, "32")==0)
ueow = 32;
else if (strcmp(csecond,"64")==0)
ueow = 64;
else if (strcmp(csecond,"128")==0)
uvl = 0;
else if (strcmp(csecond,"256")==0)
uvl = 1;
else if (strcmp(csecond,"512")==0)
uvl = 2;
else {
fprintf(stderr,"[XED CLIENT ERROR] Bad operand width/vl: %s\n", csecond);
exit(1);
}
}
assert(!is_empty_buf(cfirst));
iclass = str2xed_iclass_enum_t(cfirst);
if (iclass == XED_ICLASS_INVALID) {
fprintf(stderr,"[XED CLIENT ERROR] Bad instruction name: %s\n",
cfirst);
exit(1);
}
xed_encoder_request_set_iclass(&req, iclass );
// put the operands in the request. Loop through tokens
// (skip the opcode iclass, handled above)
for( i=token_index; p ; i++, operand_index++, p=p->next ) {
mem_bis_parser_t mem_bis;
seg_parser_t seg_parser;
immed_parser_t imm;
immed_parser_t simm;
immed_parser_t imm2;
immed_parser_t disp;
immed_parser_t ptr_disp;
xed_reg_enum_t reg = XED_REG_INVALID;
xed_operand_enum_t r;
char cres_reg[BUF_LEN]={0};
char csecond_x[BUF_LEN]={0}; //FIXME: not used
slash_split(p->s, cres_reg, csecond_x);
if (is_empty_buf(cres_reg))
continue;
upcase(cres_reg);
// prune the AGEN or MEM(base,index,scale[,displacement]) text from
// cres_reg
// FIXME: add MEM(immed) for the OC1_A and OC1_O types????
mem_bis_parser_init(&mem_bis,cres_reg);
if (mem_bis.valid) {
xed_reg_class_enum_t rc = XED_REG_CLASS_INVALID;
xed_reg_class_enum_t rci = XED_REG_CLASS_INVALID;
if (mem_bis.mem) {
if (memop == 0) {
// Tell XED that we have a memory operand
xed_encoder_request_set_mem0(&req);
// Tell XED that the mem0 operand is the next operand:
xed_encoder_request_set_operand_order(
&req,operand_index, XED_OPERAND_MEM0);
}
else {
xed_encoder_request_set_mem1(&req);
// Tell XED that the mem1 operand is the next operand:
xed_encoder_request_set_operand_order(
&req,operand_index, XED_OPERAND_MEM1);
}
memop++;
}
else if (mem_bis.agen) {
// Tell XED we have an AGEN
xed_encoder_request_set_agen(&req);
// The AGEN is the next operand
xed_encoder_request_set_operand_order(
&req,operand_index, XED_OPERAND_AGEN);
}
else
assert(mem_bis.agen || mem_bis.mem);
rc = xed_gpr_reg_class(mem_bis.base_reg);
rci = xed_gpr_reg_class(mem_bis.index_reg);
if (mem_bis.base_reg == XED_REG_EIP)
xed_encoder_request_set_effective_address_size(&req, 32);
else if (rc == XED_REG_CLASS_GPR32 || rci == XED_REG_CLASS_GPR32)
xed_encoder_request_set_effective_address_size(&req, 32);
else if (rc == XED_REG_CLASS_GPR16 || rci == XED_REG_CLASS_GPR16)
xed_encoder_request_set_effective_address_size(&req, 16);
// fill in the memory fields
xed_encoder_request_set_base0(&req, mem_bis.base_reg);
xed_encoder_request_set_index(&req, mem_bis.index_reg);
xed_encoder_request_set_scale(&req, mem_bis.scale_val);
xed_encoder_request_set_seg0(&req, mem_bis.segment_reg);
find_vl(mem_bis.index_reg, &vl); // for scatter/gather
if (mem_bis.mem_len)
xed_encoder_request_set_memory_operand_length(
&req,
mem_bis.mem_len ); // BYTES
if (mem_bis.disp_valid)
xed_encoder_request_set_memory_displacement(
&req,
mem_bis.disp_val,
mem_bis.disp_width_bits/8);
continue;
}
seg_parser_init(&seg_parser,cres_reg);
if (seg_parser.valid) {
if (CLIENT_VERBOSE3)
printf("Setting segment to %s\n",
xed_reg_enum_t2str(seg_parser.segment_reg));
if (seg_parser.segno == 0)
xed_encoder_request_set_seg0(&req, seg_parser.segment_reg);
else
/* need SEG1 for MOVS[BWDQ]*/
xed_encoder_request_set_seg1(&req, seg_parser.segment_reg);
/* SEG/SEG0/SEG1 is NOT a normal operand. It is a setting, like
* the lock prefix. Normally the segment will be specified with
* normal memory operations. With memops without MODRM, or
* impliclit memops, we need a way of specifying the segment
* when it is not the default. This is the way. it does not
* change encoding forms. (When segments are "moved", they are
* REG operands, not SEG0/1, and are specified by name like EAX
* is.) */
continue;
}
immed_parser_init(&imm,cres_reg, "IMM");
if (imm.valid) {
if (CLIENT_VERBOSE3)
printf("Setting immediate value to " XED_FMT_LX "\n",
imm.immed_val);
xed_encoder_request_set_uimm0_bits(&req,
imm.immed_val,
imm.width_bits);
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_IMM0);
continue;
}
immed_parser_init(&simm,cres_reg, "SIMM");
if (simm.valid) {
if (CLIENT_VERBOSE3)
printf("Setting immediate value to " XED_FMT_LX "\n",
simm.immed_val);
xed_encoder_request_set_simm(
&req,
XED_STATIC_CAST(xed_int32_t,simm.immed_val),
simm.width_bits/8); //FIXME
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_IMM0);
continue;
}
immed_parser_init(&imm2,cres_reg, "IMM2");
if (imm2.valid) {
if (imm2.width_bits != 8)
xedex_derror("2nd immediate must be just 1 byte long");
xed_encoder_request_set_uimm1(&req, (xed_uint8_t)imm2.immed_val);
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_IMM1);
continue;
}
immed_parser_init(&disp,cres_reg, "RELBR");
if (disp.valid) {
if (CLIENT_VERBOSE3)
printf("Setting displacement value to " XED_FMT_LX "\n",
disp.immed_val);
xed_encoder_request_set_branch_displacement(
&req,
XED_STATIC_CAST(xed_int64_t,disp.immed_val),
disp.width_bits/8); //FIXME
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_RELBR);
xed_encoder_request_set_relbr(&req);
continue;
}
immed_parser_init(&disp,cres_reg, "ABSBR");
if (disp.valid) {
if (CLIENT_VERBOSE3)
printf("Setting displacement value to " XED_FMT_LX "\n",
disp.immed_val);
xed_encoder_request_set_branch_displacement(
&req,
XED_STATIC_CAST(xed_int64_t,disp.immed_val),
disp.width_bits/8); //FIXME
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_ABSBR);
xed_encoder_request_set_absbr(&req);
continue;
}
immed_parser_init(&ptr_disp,cres_reg, "PTR");
if (ptr_disp.valid) {
if (CLIENT_VERBOSE3)
printf("Setting pointer displacement value to " XED_FMT_LX "\n",
ptr_disp.immed_val);
xed_encoder_request_set_branch_displacement(
&req,
XED_STATIC_CAST(xed_int64_t,ptr_disp.immed_val),
ptr_disp.width_bits/8); //FIXME
xed_encoder_request_set_operand_order(&req,
operand_index,
XED_OPERAND_PTR);
xed_encoder_request_set_ptr(&req);
continue;
}
reg = str2xed_reg_enum_t(cres_reg);
if (reg == XED_REG_INVALID) {
fprintf(stderr,
"[XED CLIENT ERROR] Bad register name: %s on operand %u\n",
cres_reg, i);
exit(1);
}
if (areq.dstate.mmode != XED_MACHINE_MODE_LONG_64)
if (reg == XED_REG_DIL || reg == XED_REG_SPL || reg == XED_REG_BPL || reg == XED_REG_SIL)
{
fprintf(stderr,
"[XED CLIENT ERROR] Cannot use DIL/SPL/BPL/SIL outside of 64b mode\n");
exit(1);
}
// The registers operands are numbered starting from the first one
// as XED_OPERAND_REG0. We increment regnum (below) every time we
// add a register operands.
r = XED_CAST(xed_operand_enum_t,XED_OPERAND_REG0 + regnum);
// store the register identifier in the operand storage field
xed_encoder_request_set_reg(&req, r, reg);
// store the operand storage field name in the encode-order array
xed_encoder_request_set_operand_order(&req, operand_index, r);
find_vl(reg, &vl);
// Set the effective operand width for 64bit GPRs.
// For 64bit instructions, the default GPR EOSZ (effective operand size) is 32bits,
// We need to set it to 64bit in case we find 64bit register (on 64bit mode).
if (xed_operand_values_get_long_mode(&req))
find_64bit_eow(reg, &eow);
regnum++;
} // for loop
// Set Vector Length if needed
if (uvl == -1)
{
// no user VL setting, so use our observation-based guess.
if (vl>=0)
xed3_operand_set_vl(&req,(xed_uint_t)vl);
}
else
{
if (vl >= 0 && uvl < vl)
xedex_derror("User specified VL is smaller than largest observed register.");
// go with the user value. The encoder still might increase it
// based on observed values. But we test for that above so they'll
// get the feedback.
xed3_operand_set_vl(&req,(xed_uint_t)uvl);
}
// Set Effective Operand Width if needed
if (xed3_operand_get_vl(XED_CAST(xed_decoded_inst_t*, &req)) == 0)
{ // No need to set EOSZ if VL is defined
if (ueow == -1)
{
// no user eow, so use our observation-based guess.
if (eow >= 0)
xed_encoder_request_set_effective_operand_width(&req, XED_CAST(xed_uint_t, eow));
}
else
{
if (eow >= 0 && ueow < eow)
xedex_derror("User specified EOW is smaller than largest observed register.");
// go with the user value
xed_encoder_request_set_effective_operand_width(&req, XED_CAST(xed_uint_t, ueow));
}
}
xed_free_token_list(tokens);
return req;
}
xed_decoded_inst_t
struct xed_decoded_inst_s xed_decoded_inst_t
The main container for instructions.
xed_encoder_request_set_memory_operand_length
XED_DLL_EXPORT void xed_encoder_request_set_memory_operand_length(xed_encoder_request_t *p, xed_uint_t nbytes)
xed_encoder_request_set_absbr
XED_DLL_EXPORT void xed_encoder_request_set_absbr(xed_encoder_request_t *p)
xed_encoder_request_set_operand_order
XED_DLL_EXPORT void xed_encoder_request_set_operand_order(xed_encoder_request_t *p, xed_uint_t operand_index, xed_operand_enum_t name)
xed_encoder_request_set_branch_displacement
XED_DLL_EXPORT void xed_encoder_request_set_branch_displacement(xed_encoder_request_t *p, xed_int64_t brdisp, xed_uint_t nbytes)
xed_encoder_request_set_uimm1
XED_DLL_EXPORT void xed_encoder_request_set_uimm1(xed_encoder_request_t *p, xed_uint8_t uimm)
xed_encoder_request_set_effective_operand_width
XED_DLL_EXPORT void xed_encoder_request_set_effective_operand_width(xed_encoder_request_t *p, xed_uint_t width_bits)
xed_encoder_request_set_uimm0_bits
XED_DLL_EXPORT void xed_encoder_request_set_uimm0_bits(xed_encoder_request_t *p, xed_uint64_t uimm, xed_uint_t nbits)
Set the uimm0 using a BIT width.
xed_encoder_request_t
xed_decoded_inst_t xed_encoder_request_t
Definition xed-encode.h:41
xed_encoder_request_set_seg0
XED_DLL_EXPORT void xed_encoder_request_set_seg0(xed_encoder_request_t *p, xed_reg_enum_t seg_reg)
xed_encoder_request_set_mem0
XED_DLL_EXPORT void xed_encoder_request_set_mem0(xed_encoder_request_t *p)
xed_encoder_request_set_ptr
XED_DLL_EXPORT void xed_encoder_request_set_ptr(xed_encoder_request_t *p)
xed_encoder_request_zero_set_mode
XED_DLL_EXPORT void xed_encoder_request_zero_set_mode(xed_encoder_request_t *p, const xed_state_t *dstate)
xed_encoder_request_set_base0
XED_DLL_EXPORT void xed_encoder_request_set_base0(xed_encoder_request_t *p, xed_reg_enum_t base_reg)
xed_encoder_request_set_agen
XED_DLL_EXPORT void xed_encoder_request_set_agen(xed_encoder_request_t *p)
xed_encoder_request_set_effective_address_size
XED_DLL_EXPORT void xed_encoder_request_set_effective_address_size(xed_encoder_request_t *p, xed_uint_t width_bits)
xed_encoder_request_set_reg
XED_DLL_EXPORT void xed_encoder_request_set_reg(xed_encoder_request_t *p, xed_operand_enum_t operand, xed_reg_enum_t reg)
xed_encoder_request_set_scale
XED_DLL_EXPORT void xed_encoder_request_set_scale(xed_encoder_request_t *p, xed_uint_t scale)
xed_encoder_request_set_index
XED_DLL_EXPORT void xed_encoder_request_set_index(xed_encoder_request_t *p, xed_reg_enum_t index_reg)
xed_encoder_request_set_relbr
XED_DLL_EXPORT void xed_encoder_request_set_relbr(xed_encoder_request_t *p)
xed_encoder_request_set_simm
XED_DLL_EXPORT void xed_encoder_request_set_simm(xed_encoder_request_t *p, xed_int32_t simm, xed_uint_t nbytes)
same storage as uimm0
xed_encoder_request_set_memory_displacement
XED_DLL_EXPORT void xed_encoder_request_set_memory_displacement(xed_encoder_request_t *p, xed_int64_t memdisp, xed_uint_t nbytes)
xed_encoder_request_set_seg1
XED_DLL_EXPORT void xed_encoder_request_set_seg1(xed_encoder_request_t *p, xed_reg_enum_t seg_reg)
xed_encoder_request_set_mem1
XED_DLL_EXPORT void xed_encoder_request_set_mem1(xed_encoder_request_t *p)
xed_encoder_request_set_iclass
XED_DLL_EXPORT void xed_encoder_request_set_iclass(xed_encoder_request_t *p, xed_iclass_enum_t iclass)
str2xed_reg_enum_t
XED_DLL_EXPORT xed_reg_enum_t str2xed_reg_enum_t(const char *s)
This converts strings to xed_reg_enum_t types.
xed_reg_enum_t2str
XED_DLL_EXPORT const char * xed_reg_enum_t2str(const xed_reg_enum_t p)
This converts strings to xed_reg_enum_t types.
str2xed_iclass_enum_t
XED_DLL_EXPORT xed_iclass_enum_t str2xed_iclass_enum_t(const char *s)
This converts strings to xed_iclass_enum_t types.
xed_operand_values_get_long_mode
XED_DLL_EXPORT xed_bool_t xed_operand_values_get_long_mode(const xed_operand_values_t *p)
xed_gpr_reg_class
XED_DLL_EXPORT xed_reg_class_enum_t xed_gpr_reg_class(xed_reg_enum_t r)
Returns the specific width GPR reg class (like XED_REG_CLASS_GPR32 or XED_REG_CLASS_GPR64) for a give...
xed_reg_class
XED_DLL_EXPORT xed_reg_class_enum_t xed_reg_class(xed_reg_enum_t r)
Returns the register class of the given input register.
xed_iclass_enum_t
xed_iclass_enum_t
Definition xed-iclass-enum.h:1988
XED_ICLASS_INVALID
@ XED_ICLASS_INVALID
Definition xed-iclass-enum.h:1989
xed-interface.h
XED_MACHINE_MODE_LONG_64
@ XED_MACHINE_MODE_LONG_64
64b operating mode
Definition xed-machine-mode-enum.h:37
xed3_operand_get_vl
static XED_INLINE xed_bits_t xed3_operand_get_vl(const xed_decoded_inst_t *d)
Definition xed-operand-accessors.h:1567
xed3_operand_set_vl
static XED_INLINE void xed3_operand_set_vl(xed_decoded_inst_t *d, xed_bits_t opval)
Definition xed-operand-accessors.h:1571
xed_operand_enum_t
xed_operand_enum_t
Definition xed-operand-enum.h:172
XED_OPERAND_MEM0
@ XED_OPERAND_MEM0
Definition xed-operand-enum.h:225
XED_OPERAND_AGEN
@ XED_OPERAND_AGEN
Definition xed-operand-enum.h:175
XED_OPERAND_REG0
@ XED_OPERAND_REG0
Definition xed-operand-enum.h:267
XED_OPERAND_RELBR
@ XED_OPERAND_RELBR
Definition xed-operand-enum.h:277
XED_OPERAND_IMM0
@ XED_OPERAND_IMM0
Definition xed-operand-enum.h:212
XED_OPERAND_ABSBR
@ XED_OPERAND_ABSBR
Definition xed-operand-enum.h:174
XED_OPERAND_MEM1
@ XED_OPERAND_MEM1
Definition xed-operand-enum.h:226
XED_OPERAND_IMM1
@ XED_OPERAND_IMM1
Definition xed-operand-enum.h:214
XED_OPERAND_PTR
@ XED_OPERAND_PTR
Definition xed-operand-enum.h:264
XED_CAST
#define XED_CAST(x, y)
Definition xed-portability.h:29
xed_strncpy
XED_DLL_EXPORT int xed_strncpy(char *dst, const char *src, int len)
returns the number of bytes remaining for the next use of xed_strncpy() or xed_strncat() .
xed_strlen
XED_DLL_EXPORT xed_uint_t xed_strlen(const char *s)
XED_FMT_LX
#define XED_FMT_LX
Definition xed-portability.h:132
XED_STATIC_CAST
#define XED_STATIC_CAST(x, y)
Definition xed-portability.h:27
xed_reg_class_enum_t
xed_reg_class_enum_t
Definition xed-reg-class-enum.h:55
XED_REG_CLASS_GPR16
@ XED_REG_CLASS_GPR16
Definition xed-reg-class-enum.h:64
XED_REG_CLASS_ZMM
@ XED_REG_CLASS_ZMM
Definition xed-reg-class-enum.h:83
XED_REG_CLASS_XMM
@ XED_REG_CLASS_XMM
Definition xed-reg-class-enum.h:81
XED_REG_CLASS_YMM
@ XED_REG_CLASS_YMM
Definition xed-reg-class-enum.h:82
XED_REG_CLASS_GPR64
@ XED_REG_CLASS_GPR64
Definition xed-reg-class-enum.h:66
XED_REG_CLASS_GPR32
@ XED_REG_CLASS_GPR32
Definition xed-reg-class-enum.h:65
XED_REG_CLASS_SR
@ XED_REG_CLASS_SR
Definition xed-reg-class-enum.h:75
XED_REG_CLASS_INVALID
@ XED_REG_CLASS_INVALID
Definition xed-reg-class-enum.h:56
xed_reg_enum_t
xed_reg_enum_t
Definition xed-reg-enum.h:448
XED_REG_DIL
@ XED_REG_DIL
Definition xed-reg-enum.h:586
XED_REG_BPL
@ XED_REG_BPL
Definition xed-reg-enum.h:584
XED_REG_EIP
@ XED_REG_EIP
Definition xed-reg-enum.h:617
XED_REG_SIL
@ XED_REG_SIL
Definition xed-reg-enum.h:585
XED_REG_SPL
@ XED_REG_SPL
Definition xed-reg-enum.h:583
XED_REG_INVALID
@ XED_REG_INVALID
Definition xed-reg-enum.h:449
xed_uint_t
unsigned int xed_uint_t
Definition xed-types.h:39
xed_int32_t
int32_t xed_int32_t
Definition xed-types.h:36
xed_int_t
int xed_int_t
Definition xed-types.h:40
xed_uint8_t
uint8_t xed_uint8_t
Definition xed-types.h:30
xed_uint64_t
uint64_t xed_uint64_t
Definition xed-types.h:33
xed_int16_t
int16_t xed_int16_t
Definition xed-types.h:35
xed_int8_t
int8_t xed_int8_t
Definition xed-types.h:34
xed_bool_t
unsigned int xed_bool_t
Definition xed-types.h:42
xed_int64_t
int64_t xed_int64_t
Definition xed-types.h:37
xed_sign_extend16_64
XED_DLL_EXPORT xed_int64_t xed_sign_extend16_64(xed_int16_t x)
xed_sign_extend32_64
XED_DLL_EXPORT xed_int64_t xed_sign_extend32_64(xed_int32_t x)
xed_sign_extend8_64
XED_DLL_EXPORT xed_int64_t xed_sign_extend8_64(xed_int8_t x)