MODRM_RM() public static method

public static MODRM_RM ( byte b ) : byte
b byte
return byte
Exemplo n.º 1
0
        decode_modrm_rm(ref ud u,
                        ref ud_operand op,
                        reg_class type,       /* register type */
                        ud_operand_size size) /* operand size */
        {
            int  offset = 0;
            byte mod, rm;

            /* get mod, r/m and reg fields */
            mod = BitOps.MODRM_MOD(modrm(ref u));
            rm  = (byte)((BitOps.REX_B(u._rex) << 3) | BitOps.MODRM_RM(modrm(ref u)));

            /*
             * If mod is 11b, then the modrm.rm specifies a register.
             *
             */
            if (mod == 3)
            {
                decode_reg(ref u, ref op, type, rm, size);
                return;
            }

            /*
             * !11b => Memory Address
             */
            op.type = ud_type.UD_OP_MEM;
            op.size = (byte)resolve_operand_size(ref u, size);

            if (u.adr_mode == 64)
            {
                op.@base = ud_type.UD_R_RAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && (rm & 7) == 5)
                {
                    op.@base = ud_type.UD_R_RIP;
                    offset   = 32;
                }
                else
                {
                    offset = 0;
                }

                /*
                 * Scale-Index-Base (SIB)
                 */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.@base = ud_type.UD_R_RAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u._rex) << 3));
                    op.index = ud_type.UD_R_RAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u._rex) << 3));

                    /* special conditions for base reference */
                    if (op.index == ud_type.UD_R_RSP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }
                    else
                    {
                        op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    }

                    if (op.@base == ud_type.UD_R_RBP || op.@base == ud_type.UD_R_R13)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else if (u.adr_mode == 32)
            {
                op.@base = ud_type.UD_R_EAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && rm == 5)
                {
                    op.@base = ud_type.UD_NONE;
                    offset   = 32;
                }
                else
                {
                    offset = 0;
                }

                /* Scale-Index-Base (SIB) */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    op.index = ud_type.UD_R_EAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u.pfx_rex) << 3));
                    op.@base = ud_type.UD_R_EAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u.pfx_rex) << 3));

                    if (op.index == ud_type.UD_R_ESP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }

                    /* special condition for base reference */
                    if (op.@base == ud_type.UD_R_EBP)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else
            {
                ud_type[] bases = { ud_type.UD_R_BX, ud_type.UD_R_BX, ud_type.UD_R_BP, ud_type.UD_R_BP,
                                    ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_BP, ud_type.UD_R_BX };
                ud_type[] indices = { ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_SI, ud_type.UD_R_DI,
                                      ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE };
                op.@base = bases[rm & 7];
                op.index = indices[rm & 7];
                op.scale = 0;
                if (mod == 0 && rm == 6)
                {
                    offset   = 16;
                    op.@base = ud_type.UD_NONE;
                }
                else if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 16;
                }
            }

            if (offset > 0)
            {
                decode_mem_disp(ref u, offset, ref op);
            }
            else
            {
                op.offset = 0;
            }
        }
Exemplo n.º 2
0
        /*
         * 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]));
        }