12b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <stdio.h>
22b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <stdlib.h>
32b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include <string.h>
42b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
52b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "libdis.h"
62b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "ia32_insn.h"
72b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "ia32_operand.h"
82b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "ia32_modrm.h"
92b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "ia32_reg.h"
102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "x86_imm.h"
112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org#include "x86_operand_list.h"
122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org/* apply segment override to memory operand in insn */
162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic void apply_seg( x86_op_t *op, unsigned int prefixes ) {
172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if (! prefixes ) return;
182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* apply overrides from prefix */
202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	switch ( prefixes & PREFIX_REG_MASK ) {
212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_CS:
222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_cs_seg; break;
232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_SS:
242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_ss_seg; break;
252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_DS:
262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_ds_seg; break;
272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_ES:
282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_es_seg; break;
292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_FS:
302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_fs_seg; break;
312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case PREFIX_GS:
322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_gs_seg; break;
332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return;
362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic size_t decode_operand_value( unsigned char *buf, size_t buf_len,
392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			    x86_op_t *op, x86_insn_t *insn,
402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			    unsigned int addr_meth, size_t op_size,
412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			    unsigned int op_value, unsigned char modrm,
422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			    size_t gen_regs ) {
432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	size_t size = 0;
442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* ++ Do Operand Addressing Method / Decode operand ++ */
462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	switch (addr_meth) {
472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* This sets the operand Size based on the Intel Opcode Map
482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * (Vol 2, Appendix A). Letter encodings are from section
492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * A.1.1, 'Codes for Addressing Method' */
502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* ---------------------- Addressing Method -------------- */
522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* Note that decoding mod ModR/M operand adjusts the size of
532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * the instruction, but decoding the reg operand does not.
542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * This should not cause any problems, as every 'reg' operand
552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * has an associated 'mod' operand.
562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * Goddamn-Intel-Note:
572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   Some Intel addressing methods [M, R] specify that modR/M
582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   byte may only refer to a memory address/may only refer to
592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   a register -- however Intel provides no clues on what to do
602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   if, say, the modR/M for an M opcode decodes to a register
612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   rather than a memory address ... returning 0 is out of the
622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   question, as this would be an Immediate or a RelOffset, so
632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   instead these modR/Ms are decoded with total disregard to
642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *   the M, R constraints. */
652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* MODRM -- mod operand. sets size to at least 1! */
672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_E:	/* ModR/M present, Gen reg or memory  */
682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = ia32_modrm_decode( buf, buf_len, op, insn,
692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						  gen_regs );
702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_M:	/* ModR/M only refers to memory */
722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = ia32_modrm_decode( buf, buf_len, op, insn,
732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						  gen_regs );
742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_Q:	/* ModR/M present, MMX or Memory */
762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = ia32_modrm_decode( buf, buf_len, op, insn,
772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						  REG_MMX_OFFSET );
782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_R:	/* ModR/M mod == gen reg */
802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = ia32_modrm_decode( buf, buf_len, op, insn,
812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						  gen_regs );
822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
832b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_W:	/* ModR/M present, mem or SIMD reg */
842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = ia32_modrm_decode( buf, buf_len, op, insn,
852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						  REG_SIMD_OFFSET );
862b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
882b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* MODRM -- reg operand. does not effect size! */
892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_C:	/* ModR/M reg == control reg */
902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_CTRL_OFFSET );
912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_D:	/* ModR/M reg == debug reg */
932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_DEBUG_OFFSET );
942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_G:	/* ModR/M reg == gen-purpose reg */
962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, gen_regs );
972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_P:	/* ModR/M reg == qword MMX reg */
992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_MMX_OFFSET );
1002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1012b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_S:	/* ModR/M reg == segment reg */
1022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_SEG_OFFSET );
1032b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1042b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_T:	/* ModR/M reg == test reg */
1052b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_TEST_OFFSET );
1062b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_V:	/* ModR/M reg == SIMD reg */
1082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_reg_decode( modrm, op, REG_SIMD_OFFSET );
1092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* No MODRM : note these set operand type explicitly */
1122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_A:	/* No modR/M -- direct addr */
1132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_absolute;
1142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* segment:offset address used in far calls */
1162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			x86_imm_sized( buf, buf_len,
1172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				       &op->data.absolute.segment, 2 );
1182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			if ( insn->addr_size == 4 ) {
1192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_sized( buf, buf_len,
1202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				    &op->data.absolute.offset.off32, 4 );
1212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				size = 6;
1222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			} else {
1232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_sized( buf, buf_len,
1242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				    &op->data.absolute.offset.off16, 2 );
1252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				size = 4;
1262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			}
1272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_I:	/* Immediate val */
1302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_immediate;
1312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* if it ever becomes legal to have imm as dest and
1322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * there is a src ModR/M operand, we are screwed! */
1332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			if ( op->flags & op_signed ) {
1342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_signsized(buf, buf_len, &op->data.byte,
1352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_size);
1362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			} else {
1372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_sized(buf, buf_len, &op->data.byte,
1382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_size);
1392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			}
1402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = op_size;
1412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_J:	/* Rel offset to add to IP [jmp] */
1432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* this fills op->data.near_offset or
1442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			   op->data.far_offset depending on the size of
1452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			   the operand */
1462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_signed;
1472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			if ( op_size == 1 ) {
1482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				/* one-byte near offset */
1492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				op->type = op_relative_near;
1502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_signsized(buf, buf_len,
1512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						&op->data.relative_near, 1);
1522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			} else {
1532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				/* far offset...is this truly signed? */
1542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				op->type = op_relative_far;
1552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				x86_imm_signsized(buf, buf_len,
1562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org					&op->data.relative_far, op_size );
1572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			}
1582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = op_size;
1592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_O:	/* No ModR/M; op is word/dword offset */
1612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* NOTE: these are actually RVAs not offsets to seg!! */
1622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* note bene: 'O' ADDR_METH uses addr_size  to
1632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			   determine operand size */
1642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_offset;
1652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_pointer;
1662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			x86_imm_sized( buf, buf_len, &op->data.offset,
1672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org					insn->addr_size );
1682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = insn->addr_size;
1702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
1722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* Hard-coded: these are specified in the insn definition */
1732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_F:	/* EFLAGS register */
1742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_register;
1752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
1762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.reg, REG_FLAGS_INDEX );
1772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_X:	/* Memory addressed by DS:SI [string] */
1792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_expression;
1802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
1812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_ds_seg | op_pointer | op_string;
1822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.expression.base,
1832b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org					     REG_DWORD_OFFSET + 6 );
1842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_Y:	/* Memory addressed by ES:DI [string] */
1862b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_expression;
1872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
1882b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_es_seg | op_pointer | op_string;
1892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.expression.base,
1902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org					     REG_DWORD_OFFSET + 7 );
1912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_RR:	/* Gen Register hard-coded in opcode */
1932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_register;
1942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
1952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.reg,
1962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_value + gen_regs );
1972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
1982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_RS:	/* Seg Register hard-coded in opcode */
1992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_register;
2002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
2012b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.reg,
2022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_value + REG_SEG_OFFSET );
2032b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2042b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_RF:	/* FPU Register hard-coded in opcode */
2052b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_register;
2062b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
2072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.reg,
2082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_value + REG_FPU_OFFSET );
2092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_RT:	/* TST Register hard-coded in opcode */
2112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_register;
2122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
2132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			ia32_handle_register( &op->data.reg,
2142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org						op_value + REG_TEST_OFFSET );
2152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case ADDRMETH_II:	/* Immediate hard-coded in opcode */
2172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_immediate;
2182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->data.dword = op_value;
2192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->flags |= op_hardcode;
2202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
2222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case 0:	/* Operand is not used */
2232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		default:
2242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* ignore -- operand not used in this insn */
2252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->type = op_unused;	/* this shouldn't happen! */
2262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
2282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
2292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return size;
2302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
2312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
2322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgstatic size_t decode_operand_size( unsigned int op_type, x86_insn_t *insn,
2332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				   x86_op_t *op ){
2342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	size_t size;
2352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
2362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* ++ Do Operand Type ++ */
2372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	switch (op_type) {
2382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* This sets the operand Size based on the Intel Opcode Map
2392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * (Vol 2, Appendix A). Letter encodings are from section
2402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 * A.1.2, 'Codes for Operand Type' */
2412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* NOTE: in this routines, 'size' refers to the size
2422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *       of the operand in the raw (encoded) instruction;
2432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *       'datatype' stores the actual size and datatype
2442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		 *       of the operand */
2452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
2462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* ------------------------ Operand Type ----------------- */
2472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_c:	/* byte or word [op size attr] */
2482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->op_size == 4) ? 2 : 1;
2492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ? op_word : op_byte;
2502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_a:	/* 2 word or 2 dword [op size attr] */
2522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* pointer to a 16:16 or 32:32 BOUNDS operand */
2532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->op_size == 4) ? 8 : 4;
2542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ? op_bounds32 : op_bounds16;
2552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_v:	/* word or dword [op size attr] */
2572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->op_size == 4) ? 4 : 2;
2582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ? op_dword : op_word;
2592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_p:	/* 32/48-bit ptr [op size attr] */
2612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* technically these flags are not accurate: the
2622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * value s a 16:16 pointer or a 16:32 pointer, where
2632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * the first '16' is a segment */
2642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->addr_size == 4) ? 6 : 4;
2652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ? op_descr32 : op_descr16;
2662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_b:	/* byte, ignore op-size */
2682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 1;
2692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_byte;
2702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_w:	/* word, ignore op-size */
2722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 2;
2732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_word;
2742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_d:	/* dword , ignore op-size */
2762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 4;
2772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_dword;
2782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_s:	/* 6-byte psuedo-descriptor */
2802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* ptr to 6-byte value which is 32:16 in 32-bit
2812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * mode, or 8:24:16 in 16-bit mode. The high byte
2822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * is ignored in 16-bit mode. */
2832b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 6;
2842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (insn->addr_size == 4) ?
2852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				op_pdescr32 : op_pdescr16;
2862b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_q:	/* qword, ignore op-size */
2882b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 8;
2892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_qword;
2902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_dq:	/* d-qword, ignore op-size */
2922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 16;
2932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_dqword;
2942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
2952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_ps:	/* 128-bit FP data */
2962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 16;
2972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* really this is 4 packed SP FP values */
2982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_ssimd;
2992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_pd:	/* 128-bit FP data */
3012b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 16;
3022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* really this is 2 packed DP FP values */
3032b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_dsimd;
3042b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3052b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_ss:	/* Scalar elem of 128-bit FP data */
3062b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 16;
3072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* this only looks at the low dword (4 bytes)
3082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * of the xmmm register passed as a param.
3092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * This is a 16-byte register where only 4 bytes
3102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * are used in the insn. Painful, ain't it? */
3112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_sssimd;
3122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_sd:	/* Scalar elem of 128-bit FP data */
3142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 16;
3152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			/* this only looks at the low qword (8 bytes)
3162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * of the xmmm register passed as a param.
3172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * This is a 16-byte register where only 8 bytes
3182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			 * are used in the insn. Painful, again... */
3192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_sdsimd;
3202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_pi:	/* qword mmx register */
3222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 8;
3232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_qword;
3242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_si:	/* dword integer register */
3262b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 4;
3272b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_dword;
3282b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3292b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fs:	/* single-real */
3302b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 4;
3312b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_sreal;
3322b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3332b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fd:	/* double real */
3342b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 8;
3352b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_dreal;
3362b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3372b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fe:	/* extended real */
3382b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 10;
3392b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_extreal;
3402b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3412b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fb:	/* packed BCD */
3422b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 10;
3432b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_bcd;
3442b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3452b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fv:	/* pointer to FPU env: 14 or 28-bytes */
3462b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->addr_size == 4)? 28 : 14;
3472b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 28)?  op_fpuenv32: op_fpuenv16;
3482b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3492b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_ft:	/* pointer to FPU env: 94 or 108 bytes */
3502b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = (insn->addr_size == 4)? 108 : 94;
3512b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 108)?
3522b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				op_fpustate32: op_fpustate16;
3532b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3542b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fx:	/* 512-byte register stack */
3552b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 512;
3562b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_fpregset;
3572b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3582b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_fp:	/* floating point register */
3592b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 10;	/* double extended precision */
3602b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_fpreg;
3612b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3622b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_m:	/* fake operand type used for "lea Gv, M" */
3632b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = insn->addr_size;
3642b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ?  op_dword : op_word;
3652b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3662b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case OPTYPE_none: /* handle weird instructions that have no encoding but use a dword datatype, like invlpg */
3672b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = 0;
3682b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = op_none;
3692b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3702b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		case 0:
3712b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		default:
3722b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			size = insn->op_size;
3732b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			op->datatype = (size == 4) ? op_dword : op_word;
3742b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			break;
3752b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		}
3762b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return size;
3772b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
3782b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
3792b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.orgsize_t ia32_decode_operand( unsigned char *buf, size_t buf_len,
3802b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			      x86_insn_t *insn, unsigned int raw_op,
3812b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			      unsigned int raw_flags, unsigned int prefixes,
3822b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org			      unsigned char modrm ) {
3832b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	unsigned int addr_meth, op_type, op_size, gen_regs;
3842b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	x86_op_t *op;
3852b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	size_t size;
3862b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
3872b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* ++ Yank optype and addr mode out of operand flags */
3882b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	addr_meth = raw_flags & ADDRMETH_MASK;
3892b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	op_type = raw_flags & OPTYPE_MASK;
3902b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
3912b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if ( raw_flags == ARG_NONE ) {
3922b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		/* operand is not used in this instruction */
3932b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		return 0;
3942b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
3952b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
3962b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* allocate a new operand */
3972b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	op = x86_operand_new( insn );
3982b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
3992b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* ++ Copy flags from opcode table to x86_insn_t */
4002b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	op->access = (enum x86_op_access) OP_PERM(raw_flags);
4012b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	op->flags = (enum x86_op_flags) (OP_FLAGS(raw_flags) >> 12);
4022b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
4032b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* Get size (for decoding)  and datatype of operand */
4042b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	op_size = decode_operand_size(op_type, insn, op);
4052b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
4062b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* override default register set based on Operand Type */
4072b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* this allows mixing of 8, 16, and 32 bit regs in insn */
4082b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if (op_size == 1) {
4092b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		gen_regs = REG_BYTE_OFFSET;
4102b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	} else if (op_size == 2) {
4112b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		gen_regs = REG_WORD_OFFSET;
4122b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	} else {
4132b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		gen_regs = REG_DWORD_OFFSET;
4142b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
4152b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
4162b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	size = decode_operand_value( buf, buf_len, op, insn, addr_meth,
4172b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org				      op_size, raw_op, modrm, gen_regs );
4182b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
4192b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	/* if operand is an address, apply any segment override prefixes */
4202b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	if ( op->type == op_expression || op->type == op_offset ) {
4212b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org		apply_seg(op, prefixes);
4222b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	}
4232b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org
4242b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org	return size;		/* return number of bytes in instruction */
4252b4274afc4fae883d1251a7a420e24fd526a9f16cdn@chromium.org}
426