Пример #1
0
        /* =============================================================================
         * ud_decode() - Instruction decoder. Returns the number of bytes decoded.
         * =============================================================================
         */
        public int ud_decode(ref ud u)
        {
            inp_start(ref u);
            clear_insn(ref u);
            u.le    = InstructionTables.ud_lookup_table_list[0];
            u.error = (byte)((decode_prefixes(ref u) == -1 ||
                              decode_opcode(ref u) == -1 ||
                              u.error == 1) ? 1 : 0);
            /* Handle decode error. */
            if (u.error == 1)
            {
                /* clear out the decode data. */
                clear_insn(ref u);
                /* mark the sequence of bytes as invalid. */
                u.itab_entry = InstructionTables.ud_itab[0]; /* entry 0 is invalid */
                u.mnemonic   = u.itab_entry.Mnemonic;
            }

            /* maybe this stray segment override byte
             * should be spewed out?
             */
            if (BitOps.P_SEG(u.itab_entry.Prefix) == 0 &&
                u.operand[0].type != ud_type.UD_OP_MEM &&
                u.operand[1].type != ud_type.UD_OP_MEM)
            {
                u.pfx_seg = 0;
            }

            u.insn_offset  = u.pc;            /* set offset of instruction */
            u.asm_buf_fill = 0;               /* set translation buffer index to 0 */
            u.pc          += (uint)u.inp_ctr; /* move program counter by bytes decoded */

            /* return number of bytes disassembled. */
            return(u.inp_ctr);
        }
Пример #2
0
        /*
         * decode_modrm_reg
         *
         *    Decodes reg field of mod/rm byte
         *
         */
        void decode_modrm_reg(ref ud u,
                              ref ud_operand operand,
                              reg_class type,
                              ud_operand_size size)
        {
            byte reg = (byte)((BitOps.REX_R(u._rex) << 3) | BitOps.MODRM_REG(modrm(ref u)));

            decode_reg(ref u, ref operand, type, reg, size);
        }
Пример #3
0
        decode_vex(ref ud u)
        {
            byte index;

            if (u.dis_mode != 64 && BitOps.MODRM_MOD((byte)inp_peek(ref u)) != 0x3)
            {
                index = 0;
            }
            else
            {
                u.vex_op = (byte)inp_curr(ref u);
                u.vex_b1 = (byte)inp_next(ref u);
                if (u.vex_op == 0xc4)
                {
                    byte pp, m;
                    /* 3-byte vex */
                    u.vex_b2 = inp_next(ref u);
                    if (u.error != 0)
                    {
                        return(u.error);
                    }

                    m = (byte)(u.vex_b1 & 0x1f);
                    if (m == 0 || m > 3)
                    {
                        u.error        = 1;
                        u.errorMessage = "decode-error: reserved vex.m-mmmm value";
                    }
                    pp    = (byte)(u.vex_b2 & 0x3);
                    index = (byte)((pp << 2) | m);
                }
                else
                {
                    /* 2-byte vex */
                    Debug.Assert(u.vex_op == 0xc5);
                    index = (byte)(0x1 | ((u.vex_b1 & 0x3) << 2));
                }
            }
            if (u.le.Table.Length > index)
            {
                return(decode_ext(ref u, u.le.Table[index]));
            }
            else
            {
                u.error        = 1;
                u.errorMessage = string.Format("decoding vex error: index value {0} of 'u.le.Table' is out of range {1}",
                                               index, u.le.Table.Length);
                return(-1);
            }
        }
Пример #4
0
 resolve_pfx_str(ref ud u)
 {
     if (u.pfx_str == 0xf3)
     {
         if (BitOps.P_STR(u.itab_entry.Prefix) > 0)
         {
             u.pfx_rep = 0xf3;
         }
         else
         {
             u.pfx_repe = 0xf3;
         }
     }
     else if (u.pfx_str == 0xf2)
     {
         u.pfx_repne = 0xf3;
     }
     return(0);
 }
Пример #5
0
        decode_vex(ref ud u)
        {
            byte index;

            if (u.dis_mode != 64 && BitOps.MODRM_MOD((byte)inp_peek(ref u)) != 0x3)
            {
                index = 0;
            }
            else
            {
                u.vex_op = (byte)inp_curr(ref u);
                u.vex_b1 = (byte)inp_next(ref u);
                if (u.vex_op == 0xc4)
                {
                    byte pp, m;
                    /* 3-byte vex */
                    u.vex_b2 = inp_next(ref u);
                    if (u.error != 0)
                    {
                        return(u.error);
                    }

                    m = (byte)(u.vex_b1 & 0x1f);
                    if (m == 0 || m > 3)
                    {
                        u.error        = 1;
                        u.errorMessage = "decode-error: reserved vex.m-mmmm value";
                        return(u.error);
                    }
                    pp    = (byte)(u.vex_b2 & 0x3);
                    index = (byte)((pp << 2) | m);
                }
                else
                {
                    /* 2-byte vex */
                    Debug.Assert(u.vex_op == 0xc5);
                    index = (byte)(0x1 | ((u.vex_b1 & 0x3) << 2));
                }
            }
            return(decode_ext(ref u, u.le.Table[index]));
        }
Пример #6
0
        ud_operand_size resolve_operand_size(ref ud u, ud_operand_size oSize)
        {
            switch (oSize)
            {
            case ud_operand_size.SZ_V:
                return((ud_operand_size)u.opr_mode);

            case ud_operand_size.SZ_Z:
                return((ud_operand_size)((u.opr_mode == 16) ? 16 : 32));

            case ud_operand_size.SZ_Y:
                return((ud_operand_size)((u.opr_mode == 16) ? 32 : u.opr_mode));

            case ud_operand_size.SZ_RDQ:
                return((ud_operand_size)((u.dis_mode == 64) ? 64 : 32));

            case ud_operand_size.SZ_X:
                Debug.Assert(u.vex_op != 0);
                return((BitOps.P_VEXL(u.itab_entry.Prefix) > 0 && vex_l(ref u) > 0) ? ud_operand_size.SZ_QQ : ud_operand_size.SZ_DQ);

            default:
                return(oSize);
            }
        }
Пример #7
0
        decode_operand(ref ud u,
                       ref ud_operand operand,
                       ud_operand_code type,
                       ud_operand_size size)
        {
            operand.type     = ud_type.UD_NONE;
            operand._oprcode = type;

            switch (type)
            {
            case ud_operand_code.OP_A:
                decode_a(ref u, ref operand);
                break;

            case ud_operand_code.OP_MR:
                decode_modrm_rm(ref u, ref operand, (byte)reg_class.REGCLASS_GPR,
                                BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                size.Mx_reg_size() : size.Mx_mem_size());
                break;

            case ud_operand_code.OP_F:
                u.br_far = 1;
                if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod != 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_M:
                if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod != 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_E:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_G:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_sI:
            case ud_operand_code.OP_I:
                decode_imm(ref u, size, ref operand);
                break;

            case ud_operand_code.OP_I1:
                operand.type        = ud_type.UD_OP_CONST;
                operand.lval.udword = 1;
                break;

            case ud_operand_code.OP_N:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_Q:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_P:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_U:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_W:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_V:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_H:
                decode_vex_vvvv(ref u, ref operand, size);
                break;

            case ud_operand_code.OP_MU:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM,
                                BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                size.Mx_reg_size() : size.Mx_mem_size());
                break;

            case ud_operand_code.OP_S:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_SEG, size);
                break;

            case ud_operand_code.OP_O:
                decode_moffset(ref u, size, ref operand);
                break;

            case ud_operand_code.OP_R0:
            case ud_operand_code.OP_R1:
            case ud_operand_code.OP_R2:
            case ud_operand_code.OP_R3:
            case ud_operand_code.OP_R4:
            case ud_operand_code.OP_R5:
            case ud_operand_code.OP_R6:
            case ud_operand_code.OP_R7:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR,
                           (byte)((BitOps.REX_B(u._rex) << 3) | (type - ud_operand_code.OP_R0)), size);
                break;

            case ud_operand_code.OP_AL:
            case ud_operand_code.OP_AX:
            case ud_operand_code.OP_eAX:
            case ud_operand_code.OP_rAX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 0, size);
                break;

            case ud_operand_code.OP_CL:
            case ud_operand_code.OP_CX:
            case ud_operand_code.OP_eCX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 1, size);
                break;

            case ud_operand_code.OP_DL:
            case ud_operand_code.OP_DX:
            case ud_operand_code.OP_eDX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 2, size);
                break;

            case ud_operand_code.OP_ES:
            case ud_operand_code.OP_CS:
            case ud_operand_code.OP_DS:
            case ud_operand_code.OP_SS:
            case ud_operand_code.OP_FS:
            case ud_operand_code.OP_GS:
                /* in 64bits mode, only fs and gs are allowed */
                if (u.dis_mode == 64)
                {
                    if (type != ud_operand_code.OP_FS && type != ud_operand_code.OP_GS)
                    {
                        u.error        = 1;
                        u.errorMessage = "invalid segment register in 64bits\n";
                    }
                }
                operand.type  = ud_type.UD_OP_REG;
                operand.@base = (type - ud_operand_code.OP_ES) + ud_type.UD_R_ES;
                operand.size  = 16;
                break;

            case ud_operand_code.OP_J:
                decode_imm(ref u, size, ref operand);
                operand.type = ud_type.UD_OP_JIMM;
                break;

            case ud_operand_code.OP_R:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_C:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_CR, size);
                break;

            case ud_operand_code.OP_D:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_DB, size);
                break;

            case ud_operand_code.OP_I3:
                operand.type        = ud_type.UD_OP_CONST;
                operand.lval.@sbyte = 3;
                break;

            case ud_operand_code.OP_ST0:
            case ud_operand_code.OP_ST1:
            case ud_operand_code.OP_ST2:
            case ud_operand_code.OP_ST3:
            case ud_operand_code.OP_ST4:
            case ud_operand_code.OP_ST5:
            case ud_operand_code.OP_ST6:
            case ud_operand_code.OP_ST7:
                operand.type  = ud_type.UD_OP_REG;
                operand.@base = (type - ud_operand_code.OP_ST0) + ud_type.UD_R_ST0;
                operand.size  = 80;
                break;

            case ud_operand_code.OP_L:
                decode_vex_immreg(ref u, ref operand, size);
                break;

            default:
                operand.type = ud_type.UD_NONE;
                break;
            }
            return(operand.type);
        }
Пример #8
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;
            }
        }
Пример #9
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]));
        }
Пример #10
0
        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);
        }
Пример #11
0
        /* =============================================================================
         * translates to intel syntax
         * =============================================================================
         */
        public void ud_translate_intel(ref ud u)
        {
            /* check if P_OSO prefix is used */
            if (BitOps.P_OSO(u.itab_entry.Prefix) == 0 && u.pfx_opr > 0)
            {
                switch (u.dis_mode)
                {
                case 16: ud_asmprintf(ref u, "o32 "); break;

                case 32:
                case 64: ud_asmprintf(ref u, "o16 "); break;
                }
            }

            /* check if P_ASO prefix was used */
            if (BitOps.P_ASO(u.itab_entry.Prefix) == 0 && u.pfx_adr > 0)
            {
                switch (u.dis_mode)
                {
                case 16: ud_asmprintf(ref u, "a32 "); break;

                case 32: ud_asmprintf(ref u, "a16 "); break;

                case 64: ud_asmprintf(ref u, "a32 "); break;
                }
            }

            if (u.pfx_seg > 0 &&
                u.operand[0].type != ud_type.UD_OP_MEM &&
                u.operand[1].type != ud_type.UD_OP_MEM)
            {
                ud_asmprintf(ref u, "{0} ", ud_reg_tab[u.pfx_seg - (byte)ud_type.UD_R_AL]);
            }

            if (u.pfx_lock > 0)
            {
                ud_asmprintf(ref u, "lock ");
            }
            if (u.pfx_rep > 0)
            {
                ud_asmprintf(ref u, "rep ");
            }
            else if (u.pfx_repe > 0)
            {
                ud_asmprintf(ref u, "repe ");
            }
            else if (u.pfx_repne > 0)
            {
                ud_asmprintf(ref u, "repne ");
            }

            /* print the instruction mnemonic */
            ud_asmprintf(ref u, "{0}", udis86.ud_lookup_mnemonic(u.mnemonic));

            if (u.operand[0].type != ud_type.UD_NONE)
            {
                int cast = 0;
                ud_asmprintf(ref u, " ");
                if (u.operand[0].type == ud_type.UD_OP_MEM)
                {
                    if (u.operand[1].type == ud_type.UD_OP_IMM ||
                        u.operand[1].type == ud_type.UD_OP_CONST ||
                        u.operand[1].type == ud_type.UD_NONE ||
                        (u.operand[0].size != u.operand[1].size &&
                         u.operand[1].type != ud_type.UD_OP_REG))
                    {
                        cast = 1;
                    }
                    else if (u.operand[1].type == ud_type.UD_OP_REG &&
                             u.operand[1].@base == ud_type.UD_R_CL)
                    {
                        switch (u.mnemonic)
                        {
                        case ud_mnemonic_code.UD_Ircl:
                        case ud_mnemonic_code.UD_Irol:
                        case ud_mnemonic_code.UD_Iror:
                        case ud_mnemonic_code.UD_Ircr:
                        case ud_mnemonic_code.UD_Ishl:
                        case ud_mnemonic_code.UD_Ishr:
                        case ud_mnemonic_code.UD_Isar:
                            cast = 1;
                            break;

                        default: break;
                        }
                    }
                }
                gen_operand(ref u, ref u.operand[0], cast);
            }

            if (u.operand[1].type != ud_type.UD_NONE)
            {
                int cast = 0;
                ud_asmprintf(ref u, ", ");
                if (u.operand[1].type == ud_type.UD_OP_MEM &&
                    u.operand[0].size != u.operand[1].size &&
                    !udis86.ud_opr_is_sreg(ref u.operand[0]))
                {
                    cast = 1;
                }
                gen_operand(ref u, ref u.operand[1], cast);
            }

            if (u.operand[2].type != ud_type.UD_NONE)
            {
                int cast = 0;
                ud_asmprintf(ref u, ", ");
                if (u.operand[2].type == ud_type.UD_OP_MEM &&
                    u.operand[2].size != u.operand[1].size)
                {
                    cast = 1;
                }
                gen_operand(ref u, ref u.operand[2], cast);
            }

            if (u.operand[3].type != ud_type.UD_NONE)
            {
                ud_asmprintf(ref u, ", ");
                gen_operand(ref u, ref u.operand[3], 0);
            }
        }