X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_xed.c;h=25103cc687bfc29fcc3706466c7416940a2a46f6;hb=0733f93d0fc8a20528a9ab2f21704bee5562b302;hp=140ecb69f857f2c6a584d08c67df5535f1a0aaf6;hpb=4f7c3b759e3889870c5b5e7d09b3ffcc168e5632;p=palacios.git diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index 140ecb6..25103cc 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -1,5 +1,21 @@ -/* Northwestern University */ -/* (c) 2008, Jack Lange */ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ #ifdef __DECODER_TEST__ #include "vmm_decoder.h" @@ -7,17 +23,28 @@ #include #include "vm_guest.h" #include "test.h" + #else + #include #include #include #include #include +#endif + +#ifndef DEBUG_XED +#undef PrintDebug +#define PrintDebug(fmt, args...) #endif -static xed_state_t decoder_state; + + + +static uint_t tables_inited = 0; + #define GPR_REGISTER 0 #define SEGMENT_REGISTER 1 @@ -40,12 +67,16 @@ static const ullong_t mask_8 = 0xffffffffffffffffLL; switch (length) { \ case 1: \ mask = mask_1; \ + break; \ case 2: \ mask = mask_2; \ + break; \ case 4: \ mask = mask_4; \ + break; \ case 8: \ mask = mask_8; \ + break; \ } \ val & mask;}) \ @@ -63,8 +94,8 @@ struct memory_operand { -// This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h -static int get_opcode(xed_iform_enum_t iform, addr_t * opcode); + +static v3_op_type_t get_opcode(xed_iform_enum_t iform); static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len); static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand); @@ -88,18 +119,33 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { XED_ADDRESS_WIDTH_32b); } break; + case LONG_32_COMPAT: + if (state->mmode != XED_MACHINE_MODE_LONG_COMPAT_32) { + xed_state_init(state, + XED_MACHINE_MODE_LONG_COMPAT_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); + } + break; case LONG: - if (state->mmode != XED_MACHINE_MODE_LONG_64) { - state->mmode = XED_MACHINE_MODE_LONG_64; + if (state->mmode != XED_MACHINE_MODE_LONG_64) { + PrintDebug("Setting decoder to long mode\n"); + // state->mmode = XED_MACHINE_MODE_LONG_64; + //xed_state_set_machine_mode(state, XED_MACHINE_MODE_LONG_64); + xed_state_init(state, + XED_MACHINE_MODE_LONG_64, + XED_ADDRESS_WIDTH_64b, + XED_ADDRESS_WIDTH_64b); } break; default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); return -1; } return 0; } -int is_flags_reg(xed_reg_enum_t xed_reg) { +static int is_flags_reg(xed_reg_enum_t xed_reg) { switch (xed_reg) { case XED_REG_FLAGS: case XED_REG_EFLAGS: @@ -112,9 +158,22 @@ int is_flags_reg(xed_reg_enum_t xed_reg) { -int init_decoder() { - xed_tables_init(); - xed_state_zero(&decoder_state); +int v3_init_decoder(struct guest_info * info) { + // Global library initialization, only do it once + if (tables_inited == 0) { + xed_tables_init(); + tables_inited = 1; + } + + xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t)); + xed_state_zero(decoder_state); + xed_state_init(decoder_state, + XED_MACHINE_MODE_LEGACY_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); + + info->decoder_state = decoder_state; + return 0; } @@ -125,13 +184,13 @@ int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic xed_error_enum_t xed_error; - if (set_decoder_mode(info, &decoder_state) == -1) { + if (set_decoder_mode(info, info->decoder_state) == -1) { PrintError("Could not set decoder mode\n"); return -1; } - xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state); + xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state); xed_error = xed_decode(&xed_instr, REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), @@ -171,21 +230,82 @@ int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic } +static int decode_string_op(struct guest_info * info, + xed_decoded_inst_t * xed_instr, const xed_inst_t * xi, + struct x86_instr * instr) { + + PrintDebug("String operation\n"); + + if (instr->op_type == V3_OP_MOVS) { + instr->num_operands = 2; + + if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) { + PrintError("Could not get Destination memory operand\n"); + return -1; + } + + if (get_memory_operand(info, xed_instr, 1, &(instr->src_operand)) == -1) { + PrintError("Could not get Source memory operand\n"); + return -1; + } + + if (instr->prefixes.rep == 1) { + addr_t reg_addr = 0; + uint_t reg_length = 0; + + xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), ®_addr, ®_length); + instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length); + } else { + instr->str_op_length = 1; + } + + } else if (instr->op_type == V3_OP_STOS) { + instr->num_operands = 2; + + if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) { + PrintError("Could not get Destination memory operand\n"); + return -1; + } + + // STOS reads from rax + xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), + &(instr->src_operand.operand), + &(instr->src_operand.size)); + instr->src_operand.type = REG_OPERAND; + + if (instr->prefixes.rep == 1) { + addr_t reg_addr = 0; + uint_t reg_length = 0; + + xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), ®_addr, ®_length); + instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length); + } else { + instr->str_op_length = 1; + } + + } else { + PrintError("Unhandled String OP\n"); + return -1; + } + + return 0; +} + + int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) { xed_decoded_inst_t xed_instr; xed_error_enum_t xed_error; + v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes)); - if (set_decoder_mode(info, &decoder_state) == -1) { + if (set_decoder_mode(info, info->decoder_state) == -1) { PrintError("Could not set decoder mode\n"); return -1; } - - - xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state); + xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state); xed_error = xed_decode(&xed_instr, REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), @@ -200,13 +320,34 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr); instr->instr_length = xed_decoded_inst_get_length(&xed_instr); - instr->num_operands = xed_decoded_inst_noperands(&xed_instr); + xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr); +#ifdef DEBUG_XED + xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr); + + PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass)); +#endif - PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform)); + if ((instr->op_type = get_opcode(iform)) == V3_INVALID_OP) { + PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform)); + return -1; + } + + + // We special case the string operations... + if (xed_decoded_inst_get_category(&xed_instr) == XED_CATEGORY_STRINGOP) { + instr->is_str_op = 1; + return decode_string_op(info, &xed_instr, xi, instr); + } else { + instr->is_str_op = 0; + instr->str_op_length = 0; + } + + + instr->num_operands = xed_decoded_inst_noperands(&xed_instr); if (instr->num_operands > 3) { PrintDebug("Special Case Not Handled\n"); @@ -219,23 +360,13 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins if ((!xed_operand_is_register(op_enum)) || (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) { // special case - PrintDebug("Special Case not handled\n"); + PrintError("Special Case not handled\n"); return -1; } } - - - if (get_opcode(iform, &(instr->opcode)) == -1) { - PrintDebug("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform)); - return -1; - } - - - - //PrintDebug("Number of operands: %d\n", instr->num_operands); //PrintDebug("INSTR length: %d\n", instr->instr_length); @@ -259,7 +390,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins xed_reg, &(v3_op->operand), &(v3_op->size)); - + if (v3_reg_type == -1) { PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); v3_op->type = INVALID_OPERAND; @@ -276,16 +407,6 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM0: { - /* - struct x86_operand * operand = &(instr->dst_operand); - - if (xed_decoded_inst_mem_read(&xed_instr, 0)) { - operand = &(instr->src_operand); - } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) { - operand = &(instr->dst_operand); - } - */ - if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { PrintError("Could not get first memory operand\n"); return -1; @@ -352,15 +473,6 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM0: { - - /* - if (xed_decoded_inst_mem_read(&xed_instr, 0)) { - v3_op = &(instr->src_operand); - } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) { - v3_op = &(instr->dst_operand); - } - */ - if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { PrintError("Could not get first memory operand\n"); return -1; @@ -403,7 +515,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins // set third operand if (instr->num_operands >= 3) { const xed_operand_t * op = xed_inst_operand(xi, 2); - // xed_operand_type_enum_t op_type = xed_operand_type(op); + xed_operand_type_enum_t op_type = xed_operand_type(op); xed_operand_enum_t op_enum = xed_operand_name(op); if (xed_operand_is_register(op_enum)) { @@ -427,7 +539,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins } else { - // PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type)); + PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type)); return -1; } @@ -459,8 +571,11 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe ullong_t displacement; // struct v3_segment * seg_reg; - - + PrintDebug("Xen mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); + PrintDebug("Address width: %s\n", + xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); + PrintDebug("Stack Address width: %s\n", + xed_address_width_enum_t2str(xed_state_get_stack_address_width(info->decoder_state))); memset((void*)&mem_op, '\0', sizeof(struct memory_operand)); @@ -508,9 +623,8 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe if (disp_bits) { xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index); - mem_op.displacement_size = disp_bits / 8; + mem_op.displacement_size = disp_bits; mem_op.displacement = xed_disp; - } operand->type = MEM_OPERAND; @@ -518,17 +632,22 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe - PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", - mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement); + PrintDebug("Struct: Seg=%p (size=%d), base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n", + (void *)mem_op.segment, mem_op.segment_size, (void*)mem_op.base, (void *)mem_op.index, + (void *)mem_op.scale, (void *)(addr_t)mem_op.displacement, mem_op.displacement_size); - seg = mem_op.segment; + PrintDebug("operand size: %d\n", operand->size); + + seg = MASK(mem_op.segment, mem_op.segment_size); base = MASK(mem_op.base, mem_op.base_size); index = MASK(mem_op.index, mem_op.index_size); scale = mem_op.scale; - displacement = MASK(mem_op.displacement, mem_op.displacement_size); + // displacement = MASK(mem_op.displacement, mem_op.displacement_size); + displacement = mem_op.displacement; - PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement); + PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n", + (void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement); operand->operand = seg + base + (scale * index) + displacement; return 0; @@ -537,6 +656,8 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) { + PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); + switch (xed_reg) { case XED_REG_INVALID: *v3_reg = 0; @@ -703,6 +824,146 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a return GPR_REGISTER; + + + + case XED_REG_R8: + *v3_reg = (addr_t)&(info->vm_regs.r8); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R8D: + *v3_reg = (addr_t)&(info->vm_regs.r8); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R8W: + *v3_reg = (addr_t)&(info->vm_regs.r8); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R8B: + *v3_reg = (addr_t)&(info->vm_regs.r8); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R9: + *v3_reg = (addr_t)&(info->vm_regs.r9); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R9D: + *v3_reg = (addr_t)&(info->vm_regs.r9); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R9W: + *v3_reg = (addr_t)&(info->vm_regs.r9); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R9B: + *v3_reg = (addr_t)&(info->vm_regs.r9); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R10: + *v3_reg = (addr_t)&(info->vm_regs.r10); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R10D: + *v3_reg = (addr_t)&(info->vm_regs.r10); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R10W: + *v3_reg = (addr_t)&(info->vm_regs.r10); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R10B: + *v3_reg = (addr_t)&(info->vm_regs.r10); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R11: + *v3_reg = (addr_t)&(info->vm_regs.r11); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R11D: + *v3_reg = (addr_t)&(info->vm_regs.r11); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R11W: + *v3_reg = (addr_t)&(info->vm_regs.r11); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R11B: + *v3_reg = (addr_t)&(info->vm_regs.r11); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R12: + *v3_reg = (addr_t)&(info->vm_regs.r12); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R12D: + *v3_reg = (addr_t)&(info->vm_regs.r12); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R12W: + *v3_reg = (addr_t)&(info->vm_regs.r12); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R12B: + *v3_reg = (addr_t)&(info->vm_regs.r12); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R13: + *v3_reg = (addr_t)&(info->vm_regs.r13); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R13D: + *v3_reg = (addr_t)&(info->vm_regs.r13); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R13W: + *v3_reg = (addr_t)&(info->vm_regs.r13); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R13B: + *v3_reg = (addr_t)&(info->vm_regs.r13); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R14: + *v3_reg = (addr_t)&(info->vm_regs.r14); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R14D: + *v3_reg = (addr_t)&(info->vm_regs.r14); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R14W: + *v3_reg = (addr_t)&(info->vm_regs.r14); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R14B: + *v3_reg = (addr_t)&(info->vm_regs.r14); + *reg_len = 1; + return GPR_REGISTER; + + case XED_REG_R15: + *v3_reg = (addr_t)&(info->vm_regs.r15); + *reg_len = 8; + return GPR_REGISTER; + case XED_REG_R15D: + *v3_reg = (addr_t)&(info->vm_regs.r15); + *reg_len = 4; + return GPR_REGISTER; + case XED_REG_R15W: + *v3_reg = (addr_t)&(info->vm_regs.r15); + *reg_len = 2; + return GPR_REGISTER; + case XED_REG_R15B: + *v3_reg = (addr_t)&(info->vm_regs.r15); + *reg_len = 1; + return GPR_REGISTER; + + /* * CTRL REGS */ @@ -746,7 +1007,7 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a return CTRL_REGISTER; case XED_REG_CR4: *v3_reg = (addr_t)&(info->ctrl_regs.cr4); - *reg_len = 4; + *reg_len = 4; return CTRL_REGISTER; case XED_REG_CR8: *v3_reg = (addr_t)&(info->ctrl_regs.cr8); @@ -774,21 +1035,27 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a */ case XED_REG_CS: *v3_reg = (addr_t)&(info->segments.cs); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_DS: *v3_reg = (addr_t)&(info->segments.ds); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_ES: *v3_reg = (addr_t)&(info->segments.es); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_SS: *v3_reg = (addr_t)&(info->segments.ss); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_FS: *v3_reg = (addr_t)&(info->segments.fs); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_GS: *v3_reg = (addr_t)&(info->segments.gs); + *reg_len = 8; return SEGMENT_REGISTER; @@ -823,45 +1090,7 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a - case XED_REG_R8: - case XED_REG_R8D: - case XED_REG_R8W: - case XED_REG_R8B: - - case XED_REG_R9: - case XED_REG_R9D: - case XED_REG_R9W: - case XED_REG_R9B: - - case XED_REG_R10: - case XED_REG_R10D: - case XED_REG_R10W: - case XED_REG_R10B: - - case XED_REG_R11: - case XED_REG_R11D: - case XED_REG_R11W: - case XED_REG_R11B: - - case XED_REG_R12: - case XED_REG_R12D: - case XED_REG_R12W: - case XED_REG_R12B: - - case XED_REG_R13: - case XED_REG_R13D: - case XED_REG_R13W: - case XED_REG_R13B: - - case XED_REG_R14: - case XED_REG_R14D: - case XED_REG_R14W: - case XED_REG_R14B: - case XED_REG_R15: - case XED_REG_R15D: - case XED_REG_R15W: - case XED_REG_R15B: case XED_REG_XMM0: case XED_REG_XMM1: @@ -947,32 +1176,202 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a -static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) { +static v3_op_type_t get_opcode(xed_iform_enum_t iform) { switch (iform) { + + /* Control Instructions */ + case XED_IFORM_MOV_CR_GPR64_CR: case XED_IFORM_MOV_CR_GPR32_CR: - *opcode = (addr_t)&V3_OPCODE_MOVCR2; - break; + return V3_OP_MOVCR2; case XED_IFORM_MOV_CR_CR_GPR64: case XED_IFORM_MOV_CR_CR_GPR32: - *opcode = (addr_t)&V3_OPCODE_MOV2CR; - break; + return V3_OP_MOV2CR; + case XED_IFORM_SMSW_GPRv: + return V3_OP_SMSW; case XED_IFORM_LMSW_GPR16: - *opcode = (addr_t)&V3_OPCODE_LMSW; - break; + return V3_OP_LMSW; case XED_IFORM_CLTS: - *opcode = (addr_t)&V3_OPCODE_CLTS; - break; + return V3_OP_CLTS; + + case XED_IFORM_INVLPG_MEMb: + return V3_OP_INVLPG; + + + /* Data Instructions */ + + // Write + case XED_IFORM_ADC_MEMv_GPRv: + case XED_IFORM_ADC_MEMv_IMM: + case XED_IFORM_ADC_MEMb_GPR8: + case XED_IFORM_ADC_MEMb_IMM: + // Read + case XED_IFORM_ADC_GPRv_MEMv: + case XED_IFORM_ADC_GPR8_MEMb: + return V3_OP_ADC; + + // Write + case XED_IFORM_ADD_MEMv_GPRv: + case XED_IFORM_ADD_MEMb_IMM: + case XED_IFORM_ADD_MEMb_GPR8: + case XED_IFORM_ADD_MEMv_IMM: + // Read + case XED_IFORM_ADD_GPRv_MEMv: + case XED_IFORM_ADD_GPR8_MEMb: + return V3_OP_ADD; + + // Write + case XED_IFORM_AND_MEMv_IMM: + case XED_IFORM_AND_MEMb_GPR8: + case XED_IFORM_AND_MEMv_GPRv: + case XED_IFORM_AND_MEMb_IMM: + // Read + case XED_IFORM_AND_GPR8_MEMb: + case XED_IFORM_AND_GPRv_MEMv: + return V3_OP_AND; + + // Write + case XED_IFORM_SUB_MEMv_IMM: + case XED_IFORM_SUB_MEMb_GPR8: + case XED_IFORM_SUB_MEMb_IMM: + case XED_IFORM_SUB_MEMv_GPRv: + // Read + case XED_IFORM_SUB_GPR8_MEMb: + case XED_IFORM_SUB_GPRv_MEMv: + return V3_OP_SUB; + + // Write + case XED_IFORM_MOV_MEMv_GPRv: + case XED_IFORM_MOV_MEMb_GPR8: + case XED_IFORM_MOV_MEMb_AL: + case XED_IFORM_MOV_MEMv_IMM: + case XED_IFORM_MOV_MEMb_IMM: + // Read + case XED_IFORM_MOV_GPRv_MEMv: + case XED_IFORM_MOV_GPR8_MEMb: + case XED_IFORM_MOV_AL_MEMb: + return V3_OP_MOV; + + + // Read + case XED_IFORM_MOVZX_GPRv_MEMb: + case XED_IFORM_MOVZX_GPRv_MEMw: + return V3_OP_MOVZX; + + // Read + case XED_IFORM_MOVSX_GPRv_MEMb: + case XED_IFORM_MOVSX_GPRv_MEMw: + return V3_OP_MOVSX; + + + + case XED_IFORM_DEC_MEMv: + case XED_IFORM_DEC_MEMb: + return V3_OP_DEC; + + case XED_IFORM_INC_MEMb: + case XED_IFORM_INC_MEMv: + return V3_OP_INC; + + // Write + case XED_IFORM_OR_MEMv_IMM: + case XED_IFORM_OR_MEMb_IMM: + case XED_IFORM_OR_MEMv_GPRv: + case XED_IFORM_OR_MEMb_GPR8: + // Read + case XED_IFORM_OR_GPRv_MEMv: + case XED_IFORM_OR_GPR8_MEMb: + return V3_OP_OR; + + // Write + case XED_IFORM_XOR_MEMv_GPRv: + case XED_IFORM_XOR_MEMb_IMM: + case XED_IFORM_XOR_MEMb_GPR8: + case XED_IFORM_XOR_MEMv_IMM: + // Read + case XED_IFORM_XOR_GPRv_MEMv: + case XED_IFORM_XOR_GPR8_MEMb: + return V3_OP_XOR; + + case XED_IFORM_NEG_MEMb: + case XED_IFORM_NEG_MEMv: + return V3_OP_NEG; + + case XED_IFORM_NOT_MEMv: + case XED_IFORM_NOT_MEMb: + return V3_OP_NOT; + + case XED_IFORM_XCHG_MEMv_GPRv: + case XED_IFORM_XCHG_MEMb_GPR8: + return V3_OP_XCHG; + + case XED_IFORM_SETB_MEMb: + return V3_OP_SETB; + + case XED_IFORM_SETBE_MEMb: + return V3_OP_SETBE; + + case XED_IFORM_SETL_MEMb: + return V3_OP_SETL; + + case XED_IFORM_SETLE_MEMb: + return V3_OP_SETLE; + + case XED_IFORM_SETNB_MEMb: + return V3_OP_SETNB; + + case XED_IFORM_SETNBE_MEMb: + return V3_OP_SETNBE; + + case XED_IFORM_SETNL_MEMb: + return V3_OP_SETNL; + + case XED_IFORM_SETNLE_MEMb: + return V3_OP_SETNLE; + + case XED_IFORM_SETNO_MEMb: + return V3_OP_SETNO; + + case XED_IFORM_SETNP_MEMb: + return V3_OP_SETNP; + + case XED_IFORM_SETNS_MEMb: + return V3_OP_SETNS; + + case XED_IFORM_SETNZ_MEMb: + return V3_OP_SETNZ; + + case XED_IFORM_SETO_MEMb: + return V3_OP_SETO; + + case XED_IFORM_SETP_MEMb: + return V3_OP_SETP; + + case XED_IFORM_SETS_MEMb: + return V3_OP_SETS; + + case XED_IFORM_SETZ_MEMb: + return V3_OP_SETZ; + + case XED_IFORM_MOVSB: + case XED_IFORM_MOVSW: + case XED_IFORM_MOVSD: + case XED_IFORM_MOVSQ: + return V3_OP_MOVS; + + case XED_IFORM_STOSB: + case XED_IFORM_STOSW: + case XED_IFORM_STOSD: + case XED_IFORM_STOSQ: + return V3_OP_STOS; + default: - *opcode = 0; - return -1; + return V3_INVALID_OP; } - - return 0; }