VirtualBox

Changeset 103511 in vbox


Ignore:
Timestamp:
Feb 22, 2024 1:16:10 AM (9 months ago)
Author:
vboxsync
Message:

DIS: Added vex group 13 and redid some or the vex prefix decoding.

Location:
trunk/src/VBox/Disassembler
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Disassembler/DisasmCore-x86-amd64.cpp

    r101539 r103511  
    3939#include <iprt/string.h>
    4040#include <iprt/stdarg.h>
     41#include <iprt/x86.h>
    4142#include "DisasmInternal-x86-amd64.h"
    4243
     
    966967     * encoding of the MOD field in the MODR/M byte.
    967968     */
    968     if (pOp->fOpType & DISOPTYPE_X86_MOD_FIXED_11)
     969    if (!(pOp->fOpType & DISOPTYPE_X86_MOD_FIXED_11))
     970    { /* likely */ }
     971    else
    969972        pDis->x86.ModRM.Bits.Mod = 3;
    970973
     
    974977
    975978        /* REX.R extends the Reg field. */
    976         pDis->x86.ModRM.Bits.Reg |= ((!!(pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3);
     979        pDis->x86.ModRM.Bits.Reg |= (!!(pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_R)) << 3;
    977980
    978981        /* REX.B extends the Rm field if there is no SIB byte nor a 32 bits displacement */
     982#if 1
     983        if (   pDis->x86.ModRM.Bits.Mod == 3 /* The register mode has neither SIB nor disp32. */
     984            || (   pDis->x86.ModRM.Bits.Rm != 4      /* SIB */
     985                && (   pDis->x86.ModRM.Bits.Mod != 0 /* disp32/PCREL is mod=0 rm=5 */
     986                    || pDis->x86.ModRM.Bits.Rm  != 5)))
     987#else
    979988        if (!(    pDis->x86.ModRM.Bits.Mod != 3
    980989              &&  pDis->x86.ModRM.Bits.Rm  == 4)
     
    982991            !(    pDis->x86.ModRM.Bits.Mod == 0
    983992              &&  pDis->x86.ModRM.Bits.Rm  == 5))
    984         {
    985             pDis->x86.ModRM.Bits.Rm |= ((!!(pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3);
    986         }
     993#endif
     994            pDis->x86.ModRM.Bits.Rm |= (!!(pDis->x86.fRexPrefix & DISPREFIX_REX_FLAGS_B)) << 3;
    987995    }
    988996    offInstr = QueryModRM(offInstr, pOp, pDis, pParam);
     
    16441652
    16451653        case OP_PARM_B: // Always OP_PARM_By. Change if it is not so.
    1646             if (pDis->x86.bVexWFlag && pDis->uCpuMode == DISCPUMODE_64BIT)
     1654            if ((pDis->x86.bVexByte2 & DISPREFIX_VEX_F_W) && pDis->uCpuMode == DISCPUMODE_64BIT)
    16471655                pParam->fUse |= DISUSE_REG_GEN64;
    16481656            else
     
    20992107    uint8_t modrm = disReadByte(pDis, offInstr);
    21002108    uint8_t reg   = MODRM_REG(modrm);
    2101     if (pDis->x86.fPrefix & DISPREFIX_OPSIZE)
    2102         reg += 8;   /* 2nd table */
    2103 
    2104     pOp = &g_aMapX86_Group13[reg];
     2109    if (!(pDis->x86.fPrefix & DISPREFIX_VEX))
     2110    {
     2111        if (pDis->x86.fPrefix & DISPREFIX_OPSIZE)
     2112            reg += 8;   /* 2nd table */
     2113        pOp = &g_aMapX86_Group13[reg];
     2114    }
     2115    else
     2116        pOp = &g_aMapX86_VGroup13[(pDis->x86.bVexByte2 & DISPREFIX_VEX_F_PP_MASK) == DISPREFIX_VEX_F_PP_66 ? reg + 8 : reg];
    21052117
    21062118    return disParseInstruction(offInstr, pOp, pDis);
     
    21722184    RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
    21732185
    2174     uint8_t byte = disReadByte(pDis, offInstr++);
    2175     pDis->x86.bOpCode = disReadByte(pDis, offInstr++);
    2176 
    2177     pDis->x86.bVexDestReg = VEX_2B2INT(byte);
    2178 
    2179     // VEX.R (equivalent to REX.R)
    2180     if (pDis->uCpuMode == DISCPUMODE_64BIT && !(byte & 0x80))
    2181     {
    2182         /* REX prefix byte */
    2183         pDis->x86.fPrefix   |= DISPREFIX_REX;
    2184         pDis->x86.fRexPrefix = DISPREFIX_REX_FLAGS_R;
    2185     }
    2186 
    2187     PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[byte & 3][1];
     2186    uint8_t const bVexByte = disReadByte(pDis, offInstr++);
     2187    if (pDis->uCpuMode == DISCPUMODE_64BIT)
     2188    {
     2189        // VEX.~R => REX.R
     2190        if (!(bVexByte & 0x80))
     2191        {
     2192            pDis->x86.fPrefix   |= DISPREFIX_REX;
     2193            pDis->x86.fRexPrefix = DISPREFIX_REX_FLAGS_R;
     2194        }
     2195    }
     2196    else if ((bVexByte & X86_MODRM_MOD_MASK) != (X86_MOD_REG << X86_MODRM_MOD_SHIFT))
     2197        return disParseInstruction(offInstr - 1, &g_OpcodeLDS, pDis); /* LDS r,mem */
     2198
     2199    /* VEX2.byte1 is the same as VEX3.byte2 with the exception of the 7th bit (~R vs W). */
     2200    pDis->x86.bVexByte2   = bVexByte & (DISPREFIX_VEX_F_PP_MASK | DISPREFIX_VEX_F_L | DISPREFIX_VEX_F_VVVV);
     2201    pDis->x86.bVexDestReg = VEX_2B2INT(bVexByte);
     2202    pDis->x86.bOpCode     = disReadByte(pDis, offInstr++);
     2203    pDis->x86.fPrefix    |= DISPREFIX_VEX;
     2204
     2205    PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[bVexByte & 3][1];
    21882206    unsigned  const      idxOpcode = pDis->x86.bOpCode - pRange->idxFirst;
    21892207    PCDISOPCODE          pOpCode;
     
    22012219    RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
    22022220
    2203     uint8_t byte1 = disReadByte(pDis, offInstr++);
    2204     uint8_t byte2 = disReadByte(pDis, offInstr++);
    2205     pDis->x86.bOpCode = disReadByte(pDis, offInstr++);
    2206     pDis->x86.bVexDestReg = VEX_2B2INT(byte2); /** @todo r=bird: why on earth ~vvvv + L; this is obfuscation non-sense. Either split the shit up or just store byte2 raw here! */
    2207 
    2208     // VEX.W
    2209     pDis->x86.bVexWFlag = !!(byte2 & 0x80); /** @todo r=bird: why a whole byte for this one flag? x86.bVexWFlag and bVexDestReg makes little sense. */
     2221    uint8_t const bVexByte1 = disReadByte(pDis, offInstr++);
     2222    if (pDis->uCpuMode == DISCPUMODE_64BIT)
     2223    {
     2224        // VEX.~R~X~B => REX.RXB
     2225        pDis->x86.fRexPrefix |= (bVexByte1 >> 5) ^ 7;
     2226        if (pDis->x86.fRexPrefix)
     2227            pDis->x86.fPrefix |= DISPREFIX_REX;
     2228    }
     2229    else if ((bVexByte1 & X86_MODRM_MOD_MASK) != (X86_MOD_REG << X86_MODRM_MOD_SHIFT))
     2230        return disParseInstruction(offInstr - 1, &g_OpcodeLES, pDis); /* LES r,mem */
     2231
     2232    uint8_t const bVexByte2 = disReadByte(pDis, offInstr++);
     2233    pDis->x86.fPrefix    |= DISPREFIX_VEX;
     2234    pDis->x86.bVexByte2   = bVexByte2;
     2235    pDis->x86.bOpCode     = disReadByte(pDis, offInstr++);
     2236    pDis->x86.bVexDestReg = VEX_2B2INT(bVexByte2); /** @todo r=bird: why on earth ~vvvv + L; this is obfuscation non-sense. Either split the shit up or just store bVexByte2 raw here! */
    22102237
    22112238    /* Hack alert! Assume VEX.W rules over any 66h prefix and that no VEX
    22122239       encoded instructions ever uses the regular x86.uOpMode w/o VEX.W. */
    2213     pDis->x86.uOpMode = (byte2 & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT ? DISCPUMODE_64BIT : DISCPUMODE_32BIT;
    2214 
    2215     // VEX.~R~X~B => REX.RXB
    2216     if (pDis->uCpuMode == DISCPUMODE_64BIT)
    2217     {
    2218         pDis->x86.fRexPrefix |= (byte1 >> 5) ^ 7;
    2219         if (pDis->x86.fRexPrefix)
    2220             pDis->x86.fPrefix |= DISPREFIX_REX;
    2221     }
     2240    pDis->x86.uOpMode = (bVexByte2 & 0x80) && pDis->uCpuMode == DISCPUMODE_64BIT ? DISCPUMODE_64BIT : DISCPUMODE_32BIT;
    22222241
    22232242    PCDISOPCODE pOpCode;
    2224     uint8_t const idxVexMap = byte1 & 0x1f;
    2225     if (idxVexMap < RT_ELEMENTS(g_aapVexOpcodesMapRanges[byte2 & 3]))
    2226     {
    2227         PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[byte2 & 3][idxVexMap];
     2243    uint8_t const idxVexMap = bVexByte1 & 0x1f;
     2244    if (idxVexMap < RT_ELEMENTS(g_aapVexOpcodesMapRanges[bVexByte2 & 3]))
     2245    {
     2246        PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[bVexByte2 & 3][idxVexMap];
    22282247        unsigned  const      idxOpcode = pDis->x86.bOpCode - pRange->idxFirst;
    22292248        if (idxOpcode < pRange->cOpcodes)
     
    24192438        }
    24202439
    2421         /* Check if this is a VEX prefix. Not for 32-bit mode. */
    2422         if (pDis->uCpuMode != DISCPUMODE_64BIT
    2423             && (enmOpcode == OP_LES || enmOpcode == OP_LDS)
    2424             && (disReadByte(pDis, offInstr) & 0xc0) == 0xc0)
    2425         {
    2426             paOneByteMap = g_aOneByteMapX64;
    2427         }
    2428 
    24292440        /* first opcode byte. */
    24302441        pDis->x86.bOpCode  = bCode;
  • trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp

    r101546 r103511  
    640640                        char *pszFmtDst = szTmpFmt;
    641641                        if (pszSpace == NULL) pszSpace = strchr(pszDelim, 0);
    642                         if (   (*pszFmt == '#' && !pDis->x86.bVexWFlag) /** @todo check this*/
     642                        if (   (*pszFmt == '#' && !(pDis->x86.bVexByte2 & DISPREFIX_VEX_F_W)) /** @todo check this*/
    643643                            || (*pszFmt == '@' && !VEXREG_IS256B(pDis->x86.bVexDestReg))
    644644                            || (*pszFmt == '&' && (   DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse)
     
    723723                            case DISCPUMODE_16BIT: if (OP_PARM_VSUBTYPE(pParam->x86.fParam) != OP_PARM_y) PUT_SZ("word "); break; \
    724724                            case DISCPUMODE_32BIT: \
    725                                 if (pDis->pCurInstr->uOpcode != OP_GATHER || pDis->x86.bVexWFlag) { PUT_SZ("dword "); break; } \
     725                                if (pDis->pCurInstr->uOpcode != OP_GATHER || (pDis->x86.bVexByte2 & DISPREFIX_VEX_F_W)) \
     726                                { PUT_SZ("dword "); break; } \
    726727                                RT_FALL_THRU(); \
    727728                            case DISCPUMODE_64BIT: PUT_SZ("qword "); break; \
  • trunk/src/VBox/Disassembler/DisasmInternal-x86-amd64.h

    r99236 r103511  
    131131extern const DISOPCODE g_aOneByteMapX64[256];
    132132extern const DISOPCODE g_aTwoByteMapX86[256];
     133extern const DISOPCODE g_OpcodeLES;
     134extern const DISOPCODE g_OpcodeLDS;
    133135
    134136/** Two byte opcode map with prefix 0x66 */
     
    198200extern const DISOPCODE g_aMapX86_Group12[8*2];
    199201extern const DISOPCODE g_aMapX86_Group13[8*2];
     202extern const DISOPCODE g_aMapX86_VGroup13[8*2];
    200203extern const DISOPCODE g_aMapX86_Group14[8*2];
    201204extern const DISOPCODE g_aMapX86_Group15_mem[8];
  • trunk/src/VBox/Disassembler/DisasmTables-x86-amd64.cpp

    r100571 r103511  
    321321    OP("retn %Iw",           IDX_ParseImmUshort, 0,                 0,          OP_RETN,        OP_PARM_Iw,      OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_X86_FORCED_64_OP_SIZE),
    322322    OP("retn",               0,                  0,                 0,          OP_RETN,        OP_PARM_NONE,    OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_CONTROLFLOW | DISOPTYPE_UNCOND_CONTROLFLOW | DISOPTYPE_X86_FORCED_64_OP_SIZE),
    323     OP("les %Gv,%Mp",        IDX_ParseModRM,     IDX_UseModRM,      0,          OP_LES,         OP_PARM_Gv,      OP_PARM_Mp,     OP_PARM_NONE,   DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64),
    324     OP("lds %Gv,%Mp",        IDX_ParseModRM,     IDX_UseModRM,      0,          OP_LDS,         OP_PARM_Gv,      OP_PARM_Mp,     OP_PARM_NONE,   DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64 | DISOPTYPE_RRM_DANGEROUS),
     323    OP("vex3b/les %Gv,%Mp",  IDX_ParseVex3b,     0,                 0,          OP_VEX3B,       OP_PARM_NONE,    OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_HARMLESS),
     324    OP("vex2b/lds %Gv,%Mp",  IDX_ParseVex2b,     0,                 0,          OP_VEX2B,       OP_PARM_NONE,    OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_HARMLESS),
    325325    /** @todo these two are actually group11 */
    326326    OP("mov %Eb,%Ib",        IDX_ParseModRM,     IDX_ParseImmByte,  0,          OP_MOV,         OP_PARM_Eb,      OP_PARM_Ib,     OP_PARM_NONE,   DISOPTYPE_HARMLESS),
     
    394394};
    395395
     396const DISOPCODE g_OpcodeLES =
     397    OP("les %Gv,%Mp",        IDX_ParseModRM,     IDX_UseModRM,      0,          OP_LES,         OP_PARM_Gv,      OP_PARM_Mp,     OP_PARM_NONE,   DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64);
     398const DISOPCODE g_OpcodeLDS =
     399    OP("lds %Gv,%Mp",        IDX_ParseModRM,     IDX_UseModRM,      0,          OP_LDS,         OP_PARM_Gv,      OP_PARM_Mp,     OP_PARM_NONE,   DISOPTYPE_HARMLESS | DISOPTYPE_X86_INVALID_64 | DISOPTYPE_RRM_DANGEROUS);
    396400
    397401const DISOPCODE g_aTwoByteMapX86[256] =
     
    31903194};
    31913195
     3196/* vex map1 0x72 */
     3197const DISOPCODE g_aMapX86_VGroup13[8*2] =
     3198{
     3199    /* 0   format string,                   parse param #1,     parse param #2,     parse param #3,     parse param #4,     opcode,             param #1,     param #2,     param #3,     param #4,     flags */
     3200    /* No prefix */
     3201    INVALID_OPCODE_MOD_RM(0x00),
     3202    INVALID_OPCODE_MOD_RM(0x01),
     3203    INVALID_OPCODE_MOD_RM(0x02),
     3204    INVALID_OPCODE_MOD_RM(0x03),
     3205    INVALID_OPCODE_MOD_RM(0x04),
     3206    INVALID_OPCODE_MOD_RM(0x05),
     3207    INVALID_OPCODE_MOD_RM(0x06),
     3208    INVALID_OPCODE_MOD_RM(0x07),
     3209
     3210    /* Group 13 with prefix 0x66 */
     3211    INVALID_OPCODE_MOD_RM(0x08),
     3212    INVALID_OPCODE_MOD_RM(0x09),
     3213    OPVEX("vpsrld %Hx,%Ux,%Ib",             IDX_ParseVexDest,   IDX_ParseModRM,     IDX_ParseImmByte,   0,                  OP_VPSRLD,          OP_PARM_Hx,   OP_PARM_Ux,    OP_PARM_Ib,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
     3214    INVALID_OPCODE_MOD_RM(0x0b),
     3215    OPVEX("vpsrad %Hx,%Ux,%Ib",             IDX_ParseVexDest,   IDX_ParseModRM,     IDX_ParseImmByte,   0,                  OP_VPSRAD,          OP_PARM_Hx,   OP_PARM_Ux,    OP_PARM_Ib,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
     3216    INVALID_OPCODE_MOD_RM(0x0d),
     3217    OPVEX("vpslld %Hx,%Ux,%Ib",             IDX_ParseVexDest,   IDX_ParseModRM,     IDX_ParseImmByte,   0,                  OP_VPSLLD,          OP_PARM_Hx,   OP_PARM_Ux,    OP_PARM_Ib,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
     3218    INVALID_OPCODE_MOD_RM(0x0f),
     3219    /*     format string,                   parse param #1,     parse param #2,     parse param #3,     parse param #4,     opcode,             param #1,     param #2,     param #3,     param #4,     flags */
     3220};
     3221
    31923222/* 0xF 0x73 */
    31933223const DISOPCODE g_aMapX86_Group14[8*2] =
     
    34613491    OPVEX("vpshufd %Vx,%Wx,%Ib",            IDX_ParseModRM,     IDX_UseModRM,    IDX_ParseImmByte,      0,                  OP_VPSHUFD,         OP_PARM_Vx,   OP_PARM_Wx,   OP_PARM_Ib,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
    34623492    INVALID_OPCODE,
    3463     INVALID_OPCODE,
     3493    OP("vgroup13",                          IDX_ParseGrp13,                0,                   0,                          OP_GRP13,           OP_PARM_NONE, OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
    34643494    INVALID_OPCODE,
    34653495    OPVEX("vpcmpeqb %Vx,%Hx,%Wx",           IDX_ParseModRM,     IDX_ParseVexDest,   IDX_UseModRM,       0,                  OP_VPCMPEQB,        OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wx,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
  • trunk/src/VBox/Disassembler/testcase/tstDisasm-1A.asm

    r98668 r103511  
    164164        paddd       xmm1, xmm3
    165165
     166        lds eax, [ebx]
     167        les ebp, [esp]
    166168%if __YASM_VERSION_ID__ >= 001030000h ; Old yasm doesn't support the instructions below
    167169        adcx        eax, ebx
     
    181183        vgatherqps xmm0,dword [eax+xmm0*2],xmm0
    182184        vgatherqpd xmm0,qword [eax+xmm0*2],xmm0
     185        vpsrld      ymm5, ymm1, 009h
     186        vpslld      ymm0, ymm7, 01ah
    183187%endif
    184188
     
    386390        vpmovsxbw  ymm4,[0x100]
    387391        vgatherqpd xmm0,qword [rbx+xmm11*2],xmm2
     392
     393        vpsrld      ymm5, ymm1, 009h
     394        vpsrld      ymm8, ymm12, 011h
     395        vpslld      ymm0, ymm7, 01ah
    388396%endif
    389397
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette