/* * decode_ext() * * Decode opcode extensions (if any) */ int decode_ext(ref ud u, ushort ptr) { byte idx = 0; if ((ptr & 0x8000) == 0) { return(decode_insn(ref u, ptr)); } u.le = InstructionTables.ud_lookup_table_list[(~0x8000 & ptr)]; if (u.le.Type == ud_table_type.UD_TAB__OPC_3DNOW) { return(decode_3dnow(ref u)); } switch (u.le.Type) { case ud_table_type.UD_TAB__OPC_MOD: /* !11 = 0, 11 = 1 */ idx = (byte)((BitOps.MODRM_MOD(modrm(ref u)) + 1) / 4); break; /* disassembly mode/operand size/address size based tables. * 16 = 0,, 32 = 1, 64 = 2 */ case ud_table_type.UD_TAB__OPC_MODE: idx = (byte)(u.dis_mode != 64 ? 0 : 1); break; case ud_table_type.UD_TAB__OPC_OSIZE: idx = (byte)(eff_opr_mode(u.dis_mode, BitOps.REX_W(u.pfx_rex), u.pfx_opr) / 32); break; case ud_table_type.UD_TAB__OPC_ASIZE: idx = (byte)(eff_adr_mode(u.dis_mode, u.pfx_adr) / 32); break; case ud_table_type.UD_TAB__OPC_X87: idx = (byte)(modrm(ref u) - 0xC0); break; case ud_table_type.UD_TAB__OPC_VENDOR: if (u.vendor == UD_VENDOR_ANY) { /* choose a valid entry */ idx = (byte)((u.le.Table[idx] != 0) ? 0 : 1); } else if (u.vendor == UD_VENDOR_AMD) { idx = 0; } else { idx = 1; } break; case ud_table_type.UD_TAB__OPC_RM: idx = BitOps.MODRM_RM(modrm(ref u)); break; case ud_table_type.UD_TAB__OPC_REG: idx = BitOps.MODRM_REG(modrm(ref u)); break; case ud_table_type.UD_TAB__OPC_SSE: return(decode_ssepfx(ref u)); case ud_table_type.UD_TAB__OPC_VEX: return(decode_vex(ref u)); case ud_table_type.UD_TAB__OPC_VEX_W: idx = vex_w(ref u); break; case ud_table_type.UD_TAB__OPC_VEX_L: idx = vex_l(ref u); break; case ud_table_type.UD_TAB__OPC_TABLE: inp_next(ref u); return(decode_opcode(ref u)); default: Debug.Assert(false, "not reached"); break; } return(decode_ext(ref u, u.le.Table[idx])); }
resolve_mode(ref ud u) { int default64; /* if in error state, bail out */ if (u.error == 1) { return(-1); } /* propagate prefix effects */ if (u.dis_mode == 64) { /* set 64bit-mode flags */ /* Check validity of instruction m64 */ if (BitOps.P_INV64(u.itab_entry.Prefix) > 0) { u.error = 1; u.errorMessage = "instruction invalid in 64bits\n"; return(-1); } /* compute effective rex based on, * - vex prefix (if any) * - rex prefix (if any, and not vex) * - allowed prefixes specified by the opcode map */ if (u.vex_op == 0xc4) { /* vex has rex.rxb in 1's complement */ u._rex = (byte)((~(u.vex_b1 >> 5) & 0x7) /* rex.0rxb */ | ((u.vex_b2 >> 4) & 0x8) /* rex.w000 */); } else if (u.vex_op == 0xc5) { /* vex has rex.r in 1's complement */ u._rex = (byte)((~(u.vex_b1 >> 5)) & 4); } else { Debug.Assert(u.vex_op == 0); u._rex = u.pfx_rex; } u._rex &= (byte)BitOps.REX_PFX_MASK(u.itab_entry.Prefix); /* whether this instruction has a default operand size of * 64bit, also hardcoded into the opcode map. */ default64 = (int)BitOps.P_DEF64(u.itab_entry.Prefix); /* calculate effective operand size */ if (BitOps.REX_W(u._rex) > 0) { u.opr_mode = 64; } else if (u.pfx_opr > 0) { u.opr_mode = 16; } else { /* unless the default opr size of instruction is 64, * the effective operand size in the absence of rex.w * prefix is 32. */ u.opr_mode = (byte)(default64 > 0 ? 64 : 32); } /* calculate effective address size */ u.adr_mode = (byte)((u.pfx_adr > 0) ? 32 : 64); } else if (u.dis_mode == 32) { /* set 32bit-mode flags */ u.opr_mode = (byte)((u.pfx_opr > 0) ? 16 : 32); u.adr_mode = (byte)((u.pfx_adr > 0) ? 16 : 32); } else if (u.dis_mode == 16) { /* set 16bit-mode flags */ u.opr_mode = (byte)((u.pfx_opr > 0) ? 32 : 16); u.adr_mode = (byte)((u.pfx_adr > 0) ? 32 : 16); } return(0); }