VirtualBox

Changeset 99319 in vbox for trunk


Ignore:
Timestamp:
Apr 6, 2023 7:28:23 PM (18 months ago)
Author:
vboxsync
Message:

Disassember: Continue work on the ARMv8 disassember, defining the instruction table layout and intermediate structures for decoding, bugref:10394

Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/dis-armv8.h

    r99241 r99319  
    5555typedef struct DISOPPARAMARMV8
    5656{
     57    /** The register operand. */
     58    union
     59    {
     60        /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN32
     61         * or DISUSE_REG_GEN64 is set in fUse. */
     62        uint8_t     idxGenReg;
     63    } Reg;
     64    /** Scale factor. */
    5765    uint8_t           uScale;
    5866    /** Parameter size. */
     
    6775/** Pointer to opcode parameter. */
    6876typedef const DISOPPARAMARMV8 *PCDISOPPARAMARMV8;
    69 
    70 
    71 /** Parser callback.
    72  * @remark no DECLCALLBACK() here because it's considered to be internal and
    73  *         there is no point in enforcing CDECL. */
    74 typedef size_t FNDISPARSEARMV8(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, uint8_t cBitStart, uint8_t cBits);
    75 /** Pointer to a disassembler parser function. */
    76 typedef FNDISPARSEARMV8 *PFNDISPARSEARMV8;
    7777
    7878
  • trunk/include/VBox/dis.h

    r99241 r99319  
    552552DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
    553553
     554DISDECL(size_t) DISFormatArmV8(  PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
     555DISDECL(size_t) DISFormatArmV8Ex(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
     556
    554557/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
    555558 *        reader, memory reader); */
  • trunk/include/VBox/disopcode-armv8.h

    r99243 r99319  
    520520};
    521521
     522
     523/** @defgroup grp_dis_opparam Opcode parameters (DISOPCODE::fParam1,
     524 *            DISOPCODE::fParam2, DISOPCODE::fParam3)
     525 * @ingroup grp_dis
     526 * @{
     527 */
     528
     529enum OP_ARMV8_PARM
     530{
     531    OP_ARMV8_PARM_NONE,
     532};
     533
     534
     535/** Immediate (the instruction class gives the range of the immediate). */
     536#define OP_ARMV8_PARM_Imm               1
     537
    522538/** @} */
    523539
  • trunk/src/VBox/Disassembler/Disasm.cpp

    r99241 r99319  
    586586    if (RT_SUCCESS(rc) && pszOutput && cbOutput)
    587587    {
    588         size_t cch = DISFormatYasmEx(pDis, pszOutput, cbOutput,
    589                                      DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED
    590                                      | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT,
    591                                      NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
     588        size_t cch = 0;
     589
     590        switch (enmCpuMode)
     591        {
     592            case DISCPUMODE_16BIT:
     593            case DISCPUMODE_32BIT:
     594            case DISCPUMODE_64BIT:
     595#if defined(VBOX_DIS_WITH_X86_AMD64)
     596                cch = DISFormatYasmEx(pDis, pszOutput, cbOutput,
     597                                        DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED
     598                                      | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT,
     599                                      NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
     600#else
     601                AssertReleaseFailed(); /* Shouldn't ever get here (DISInstrEx() returning VERR_NOT_SUPPORTED). */
     602#endif
     603                break;
     604            case DISCPUMODE_ARMV8_A64:
     605            case DISCPUMODE_ARMV8_A32:
     606            case DISCPUMODE_ARMV8_T32:
     607#if defined(VBOX_DIS_WITH_ARMV8)
     608                cch = DISFormatArmV8Ex(pDis, pszOutput, cbOutput,
     609                                         DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED
     610                                       | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT,
     611                                       NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
     612#else
     613               AssertReleaseFailed(); /* Shouldn't ever get here (DISInstrEx() returning VERR_NOT_SUPPORTED). */
     614#endif
     615                break;
     616            default:
     617                break;
     618        }
     619
    592620        if (cch + 2 <= cbOutput)
    593621        {
  • trunk/src/VBox/Disassembler/DisasmCore-armv8.cpp

    r99242 r99319  
    4242
    4343/*********************************************************************************************************************************
     44*   Structures and Typedefs                                                                                                      *
     45*********************************************************************************************************************************/
     46
     47/** Parser callback.
     48 * @remark no DECLCALLBACK() here because it's considered to be internal and
     49 *         there is no point in enforcing CDECL. */
     50typedef int FNDISPARSEARMV8(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit);
     51/** Pointer to a disassembler parser function. */
     52typedef FNDISPARSEARMV8 *PFNDISPARSEARMV8;
     53
     54
     55/** Opcode decoder callback.
     56 * @remark no DECLCALLBACK() here because it's considered to be internal and
     57 *         there is no point in enforcing CDECL. */
     58typedef uint32_t FNDISDECODEARMV8(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass);
     59/** Pointer to a disassembler parser function. */
     60typedef FNDISDECODEARMV8 *PFNDISDECODEARMV8;
     61
     62
     63/*********************************************************************************************************************************
    4464*   Defined Constants And Macros                                                                                                 *
    4565*********************************************************************************************************************************/
     
    5272 * @{ */
    5373static FNDISPARSEARMV8 disArmV8ParseIllegal;
     74static FNDISPARSEARMV8 disArmV8ParseImm;
     75static FNDISPARSEARMV8 disArmV8ParseImmRel;
     76static FNDISPARSEARMV8 disArmV8ParseImmAdr;
     77static FNDISPARSEARMV8 disArmV8ParseReg;
     78static FNDISPARSEARMV8 disArmV8ParseImmsImmrN;
     79static FNDISPARSEARMV8 disArmV8ParseHw;
     80static FNDISPARSEARMV8 disArmV8ParseCond;
    5481/** @}  */
     82
     83
     84/** @name Decoders
     85 * @{ */
     86static FNDISDECODEARMV8 disArmV8DecodeIllegal;
     87/** @} */
    5588
    5689
     
    5992*********************************************************************************************************************************/
    6093/** Parser opcode table for full disassembly. */
    61 static PFNDISPARSEARMV8 const g_apfnDisasm[IDX_ParseMax] =
     94static PFNDISPARSEARMV8 const g_apfnDisasm[kDisParmParseMax] =
    6295{
    6396    disArmV8ParseIllegal,
     97    disArmV8ParseImm,
     98    disArmV8ParseImmRel,
     99    disArmV8ParseImmAdr,
     100    disArmV8ParseReg,
     101    disArmV8ParseImmsImmrN,
     102    disArmV8ParseHw,
     103    disArmV8ParseCond
    64104};
    65105
    66 static size_t disArmV8ParseIllegal(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam, uint8_t cBitStart, uint8_t cBits)
    67 {
    68     RT_NOREF_PV(pOp); RT_NOREF_PV(pParam); RT_NOREF_PV(pDis);
     106
     107/** Opcode decoder table. */
     108static PFNDISDECODEARMV8 const g_apfnOpcDecode[kDisArmV8OpcDecodeMax] =
     109{
     110    disArmV8DecodeIllegal,
     111};
     112
     113
     114DECLINLINE(uint32_t) disArmV8ExtractBitVecFromInsn(uint32_t u32Insn, uint8_t idxBitStart, uint8_t cBits)
     115{
     116    uint32_t fMask = RT_BIT_32(idxBitStart + cBits) - 1;
     117    return (u32Insn & fMask) >> idxBitStart;
     118}
     119
     120
     121DECLINLINE(int32_t) disArmV8ExtractBitVecFromInsnSignExtend(uint32_t u32Insn, uint8_t idxBitStart, uint8_t cBits)
     122{
     123    uint32_t fMask = RT_BIT_32(idxBitStart + cBits) - 1;
     124    uint32_t fSign = ~(UINT32_MAX & (RT_BIT_32(cBits - 1) - 1));
     125    uint32_t fValue = (u32Insn & fMask) >> idxBitStart;
     126    if (fValue & fSign)
     127        return (int32_t)(fValue | fSign);
     128
     129    return (int32_t)fValue;
     130}
     131
     132
     133static int disArmV8ParseIllegal(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     134{
     135    RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit);
    69136    AssertFailed();
    70     return offInstr;
     137    return VERR_INTERNAL_ERROR;
     138}
     139
     140
     141static int disArmV8ParseImm(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     142{
     143    RT_NOREF(pDis, pInsnClass, f64Bit);
     144
     145    AssertReturn(pInsnParm->idxBitStart + pInsnParm->cBits < 32, VERR_INTERNAL_ERROR_2);
     146
     147    pParam->uValue = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits);
     148    if (pInsnParm->cBits <= 8)
     149    {
     150        pParam->arch.armv8.cb = sizeof(uint8_t);
     151        pParam->fUse |= DISUSE_IMMEDIATE8;
     152    }
     153    else if (pInsnParm->cBits <= 16)
     154    {
     155        pParam->arch.armv8.cb = sizeof(uint16_t);
     156        pParam->fUse |= DISUSE_IMMEDIATE16;
     157    }
     158    else if (pInsnParm->cBits <= 32)
     159    {
     160        pParam->arch.armv8.cb = sizeof(uint32_t);
     161        pParam->fUse |= DISUSE_IMMEDIATE32;
     162    }
     163    else
     164        AssertReleaseFailed();
     165
     166    return VINF_SUCCESS;
     167}
     168
     169
     170static int disArmV8ParseImmRel(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     171{
     172    RT_NOREF(pDis, pInsnClass, f64Bit);
     173
     174    AssertReturn(pInsnParm->idxBitStart + pInsnParm->cBits < 32, VERR_INTERNAL_ERROR_2);
     175
     176    pParam->uValue = (int64_t)disArmV8ExtractBitVecFromInsnSignExtend(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits);
     177    if (pInsnParm->cBits <= 8)
     178    {
     179        pParam->arch.armv8.cb = sizeof(int8_t);
     180        pParam->fUse |= DISUSE_IMMEDIATE8_REL;
     181    }
     182    else if (pInsnParm->cBits <= 16)
     183    {
     184        pParam->arch.armv8.cb = sizeof(int16_t);
     185        pParam->fUse |= DISUSE_IMMEDIATE16_REL;
     186    }
     187    else if (pInsnParm->cBits <= 32)
     188    {
     189        pParam->arch.armv8.cb = sizeof(int32_t);
     190        pParam->fUse |= DISUSE_IMMEDIATE32_REL;
     191    }
     192    else
     193        AssertReleaseFailed();
     194
     195    return VINF_SUCCESS;
     196}
     197
     198
     199static int disArmV8ParseImmAdr(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     200{
     201    RT_NOREF(pDis, pInsnClass, f64Bit, pInsnParm);
     202
     203    pParam->uValue  = disArmV8ExtractBitVecFromInsn(u32Insn, 5, 19);
     204    pParam->uValue |= disArmV8ExtractBitVecFromInsn(u32Insn, 29, 2) << 29;
     205    pParam->fUse |= DISUSE_IMMEDIATE32;
     206    return VINF_SUCCESS;
     207}
     208
     209
     210static int disArmV8ParseReg(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     211{
     212    RT_NOREF(pDis, pInsnClass);
     213    pParam->arch.armv8.Reg.idxGenReg = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits);
     214    pParam->arch.armv8.cb            = f64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
     215    pParam->fUse |= f64Bit ? DISUSE_REG_GEN64 : DISUSE_REG_GEN32;
     216    return VINF_SUCCESS;
     217}
     218
     219
     220static int disArmV8ParseImmsImmrN(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     221{
     222    RT_NOREF(pDis);
     223    AssertReturn(pInsnParm->cBits == 13, VERR_INTERNAL_ERROR_2);
     224
     225    uint32_t u32ImmRaw = disArmV8ExtractBitVecFromInsn(u32Insn, pInsnParm->idxBitStart, pInsnParm->cBits);
     226    /* N bit must be 0 if 32-bit variant is used. */
     227    if (   (   (u32ImmRaw & RT_BIT_32(12))
     228            && !f64Bit)
     229        || (   !(u32ImmRaw & RT_BIT_32(12))
     230            && f64Bit
     231            && (pInsnClass->fClass & DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT)))
     232        return VERR_DIS_INVALID_OPCODE;
     233
     234    /** @todo Decode according to spec. */
     235    pParam->uValue        = u32ImmRaw;
     236    pParam->arch.armv8.cb = sizeof(uint32_t);
     237    pParam->fUse         |= DISUSE_IMMEDIATE32;
     238    return VINF_SUCCESS;
     239}
     240
     241
     242static int disArmV8ParseHw(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     243{
     244    RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit);
     245    AssertFailed();
     246    /** @todo */
     247    return VINF_SUCCESS;
     248}
     249
     250
     251static int disArmV8ParseCond(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass, PDISOPPARAM pParam, PCDISARMV8INSNPARAM pInsnParm, bool f64Bit)
     252{
     253    RT_NOREF(pDis, u32Insn, pInsnClass, pParam, pInsnParm, f64Bit);
     254    //AssertFailed();
     255    /** @todo */
     256    return VINF_SUCCESS;
     257}
     258
     259
     260static uint32_t disArmV8DecodeIllegal(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8INSNCLASS pInsnClass)
     261{
     262    RT_NOREF(pDis, u32Insn, pInsnClass);
     263    AssertFailed();
     264    return UINT32_MAX;
     265}
     266
     267
     268static int disArmV8A64ParseInstruction(PDISSTATE pDis, uint32_t u32Insn, PCDISOPCODE pOp, PCDISARMV8INSNCLASS pInsnClass)
     269{
     270    AssertPtr(pOp);
     271    AssertPtr(pDis);
     272
     273    /* Should contain the parameter type on input. */
     274    pDis->Param1.arch.armv8.fParam = pOp->fParam1;
     275    pDis->Param2.arch.armv8.fParam = pOp->fParam2;
     276    pDis->Param3.arch.armv8.fParam = pOp->fParam3;
     277    pDis->Param4.arch.armv8.fParam = pOp->fParam4;
     278
     279    pDis->pCurInstr = pOp;
     280    Assert(pOp != &g_ArmV8A64InvalidOpcode[0]);
     281
     282    bool f64Bit = false;
     283
     284    if (pInsnClass->fClass & DISARMV8INSNCLASS_F_SF)
     285        f64Bit = RT_BOOL(u32Insn & RT_BIT_32(31));
     286    else if (pInsnClass->fClass & DISARMV8INSNCLASS_F_FORCED_64BIT)
     287        f64Bit = true;
     288
     289    int rc = VINF_SUCCESS;
     290    if (pInsnClass->aParms[0].idxParse != kDisParmParseNop)
     291        rc = g_apfnDisasm[pInsnClass->aParms[0].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param1, &pInsnClass->aParms[0], f64Bit);
     292
     293    if (   pInsnClass->aParms[1].idxParse != kDisParmParseNop
     294        && RT_SUCCESS(rc))
     295        rc = g_apfnDisasm[pInsnClass->aParms[1].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param2, &pInsnClass->aParms[1], f64Bit);
     296
     297    if (   pInsnClass->aParms[2].idxParse != kDisParmParseNop
     298        && RT_SUCCESS(rc))
     299        rc = g_apfnDisasm[pInsnClass->aParms[2].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param3, &pInsnClass->aParms[2], f64Bit);
     300
     301    if (   pInsnClass->aParms[3].idxParse != kDisParmParseNop
     302        && RT_SUCCESS(rc))
     303        rc = g_apfnDisasm[pInsnClass->aParms[3].idxParse](pDis, u32Insn, pInsnClass, &pDis->Param4, &pInsnClass->aParms[3], f64Bit);
     304
     305    /* If parameter parsing returned an invalid opcode error the encoding is invalid. */
     306    if (rc == VERR_DIS_INVALID_OPCODE)
     307    {
     308        pDis->pCurInstr = &g_ArmV8A64InvalidOpcode[0];
     309
     310        pDis->Param1.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam1;
     311        pDis->Param2.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam2;
     312        pDis->Param3.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam3;
     313        pDis->Param4.arch.armv8.fParam = g_ArmV8A64InvalidOpcode[0].fParam4;
     314    }
     315    pDis->rc = rc;
     316    return rc;
     317}
     318
     319
     320static int disArmV8A64ParseInvOpcode(PDISSTATE pDis)
     321{
     322    pDis->pCurInstr = &g_ArmV8A64InvalidOpcode[0];
     323    pDis->rc = VERR_DIS_INVALID_OPCODE;
     324    return VERR_DIS_INVALID_OPCODE;
     325}
     326
     327
     328static int disInstrArmV8DecodeWorker(PDISSTATE pDis, uint32_t u32Insn, PCDISARMV8DECODEHDR pHdr)
     329{
     330    while (   pHdr
     331           && pHdr->enmDecodeType != kDisArmV8DecodeType_InsnClass)
     332    {
     333        if (pHdr->enmDecodeType == kDisArmV8DecodeType_Map)
     334        {
     335            PCDISARMV8DECODEMAP pMap = (PCDISARMV8DECODEMAP)pHdr;
     336
     337            uint32_t idxNext = (u32Insn & pMap->fMask) >> pMap->cShift;
     338            if (RT_LIKELY(idxNext < pMap->Hdr.cDecode))
     339                pHdr = pMap->papNext[idxNext];
     340            else
     341            {
     342                pHdr = NULL;
     343                break;
     344            }
     345        }
     346        else
     347        {
     348            Assert(pHdr->enmDecodeType == kDisArmV8DecodeType_Table);
     349            PCDISARMV8DECODETBL pTbl = (PCDISARMV8DECODETBL)pHdr;
     350
     351            /* Walk all entries in the table and select the best match. */
     352            pHdr = NULL;
     353            for (uint32_t i = 0; i < pTbl->Hdr.cDecode; i++)
     354            {
     355                PCDISARMV8DECODETBLENTRY pEntry = &pTbl->paEntries[i];
     356                if ((u32Insn & pEntry->fMask) == pEntry->fValue)
     357                {
     358                    pHdr = pEntry->pHdrNext;
     359                    break;
     360                }
     361            }
     362        }
     363    }
     364
     365    if (pHdr)
     366    {
     367        Assert(pHdr->enmDecodeType == kDisArmV8DecodeType_InsnClass);
     368        PCDISARMV8INSNCLASS pInsnClass = (PCDISARMV8INSNCLASS)pHdr;
     369
     370        /* Decode the opcode from the instruction class. */
     371        uint32_t uOpcRaw = (u32Insn & pInsnClass->fMask) >> pInsnClass->cShift;
     372        if (pInsnClass->enmOpcDecode != kDisArmV8OpcDecodeNop)
     373            uOpcRaw = g_apfnOpcDecode[pInsnClass->enmOpcDecode](pDis, u32Insn, pInsnClass);
     374
     375        if (uOpcRaw < pInsnClass->Hdr.cDecode)
     376        {
     377            PCDISOPCODE pOp = &pInsnClass->paOpcodes[uOpcRaw];
     378            return disArmV8A64ParseInstruction(pDis, u32Insn, pOp, pInsnClass);
     379        }
     380    }
     381
     382    return disArmV8A64ParseInvOpcode(pDis);
    71383}
    72384
     
    82394DECLHIDDEN(int) disInstrWorkerArmV8(PDISSTATE pDis, PCDISOPCODE paOneByteMap, uint32_t *pcbInstr)
    83395{
    84     RT_NOREF(pDis, paOneByteMap, pcbInstr);
     396    RT_NOREF(paOneByteMap);
     397
     398    if (pDis->uCpuMode == DISCPUMODE_ARMV8_A64)
     399    {
     400        *pcbInstr = sizeof(uint32_t);
     401
     402        /* Instructions are always little endian and 4 bytes. */
     403        uint32_t u32Insn = disReadDWord(pDis, 0 /*offInstr*/);
     404        if (RT_FAILURE(pDis->rc))
     405            return pDis->rc;
     406
     407        pDis->u.u32   = RT_LE2H_U32(u32Insn);
     408        pDis->cbInstr = sizeof(u32Insn);
     409
     410        return disInstrArmV8DecodeWorker(pDis, u32Insn, &g_ArmV8A64DecodeL0.Hdr);
     411    }
     412
     413    AssertReleaseFailed();
    85414    return VERR_NOT_IMPLEMENTED;
    86415}
  • trunk/src/VBox/Disassembler/DisasmInternal-armv8.h

    r99241 r99319  
    4848/** @name Index into g_apfnFullDisasm.
    4949 * @{ */
    50 enum IDX_Parse
    51 {
    52   IDX_ParseNop = 0,
    53   IDX_ParseMax
    54 };
    55 AssertCompile(IDX_ParseMax < 64 /* Packed DISOPCODE assumption. */);
     50typedef enum DISPARMPARSEIDX
     51{
     52    kDisParmParseNop = 0,
     53    kDisParmParseImm,
     54    kDisParmParseImmRel,
     55    kDisParmParseImmAdr,
     56    kDisParmParseReg,
     57    kDisParmParseImmsImmrN,
     58    kDisParmParseHw,
     59    kDisParmParseCond,
     60    kDisParmParseMax
     61} DISPARMPARSEIDX;
    5662/** @}  */
     63
     64
     65typedef struct DISARMV8INSNPARAM
     66{
     67    /** The parser to use for the parameter. */
     68    DISPARMPARSEIDX     idxParse;
     69    /** Bit index at which the field starts. */
     70    uint8_t             idxBitStart;
     71    /** Size of the bit field. */
     72    uint8_t             cBits;
     73} DISARMV8INSNPARAM;
     74typedef DISARMV8INSNPARAM *PDISARMV8INSNPARAM;
     75typedef const DISARMV8INSNPARAM *PCDISARMV8INSNPARAM;
     76
     77#define DIS_ARMV8_INSN_PARAM_NONE { kDisParmParseNop, 0, 0 }
     78#define DIS_ARMV8_INSN_PARAM_CREATE(a_idxParse, a_idxBitStart, a_cBits) \
     79    { a_idxParse, a_idxBitStart, a_cBits }
     80
     81
     82/**
     83 * Opcode decode index.
     84 */
     85typedef enum DISARMV8OPCDECODE
     86{
     87    kDisArmV8OpcDecodeNop = 0,
     88    kDisArmV8OpcDecodeMax
     89} DISARMV8OPCDECODE;
     90
     91
     92/**
     93 * Decoder stage type.
     94 */
     95typedef enum kDisArmV8DecodeType
     96{
     97    kDisArmV8DecodeType_Invalid = 0,
     98    kDisArmV8DecodeType_Map,
     99    kDisArmV8DecodeType_Table,
     100    kDisArmV8DecodeType_InsnClass,
     101    kDisArmV8DecodeType_32Bit_Hack = 0x7fffffff
     102} kDisArmV8DecodeType;
     103
     104
     105/**
     106 * Decode header.
     107 */
     108typedef struct DISARMV8DECODEHDR
     109{
     110    /** Next stage decoding type. */
     111    kDisArmV8DecodeType         enmDecodeType;
     112    /** Number of entries in the next decoder stage or
     113     * opcodes in the instruction class. */
     114    uint32_t                    cDecode;
     115} DISARMV8DECODEHDR;
     116/** Pointer to a decode header. */
     117typedef DISARMV8DECODEHDR *PDISARMV8DECODEHDR;
     118/** Pointer to a const decode header. */
     119typedef const DISARMV8DECODEHDR *PCDISARMV8DECODEHDR;
     120typedef const PCDISARMV8DECODEHDR *PPCDISARMV8DECODEHDR;
     121
     122
     123/**
     124 * Instruction class descriptor.
     125 */
     126typedef struct DISARMV8INSNCLASS
     127{
     128    /** Decoder header. */
     129    DISARMV8DECODEHDR       Hdr;
     130    /** Pointer to the arry of opcodes. */
     131    PCDISOPCODE             paOpcodes;
     132    /** Some flags for this instruction class. */
     133    uint32_t                fClass;
     134    /** Opcode decoder function. */
     135    DISARMV8OPCDECODE       enmOpcDecode;
     136    /** The mask of the bits relevant for decoding. */
     137    uint32_t                fMask;
     138    /** Number of bits to shift to get an index. */
     139    uint32_t                cShift;
     140    /** The parameters. */
     141    DISARMV8INSNPARAM       aParms[4];
     142} DISARMV8INSNCLASS;
     143/** Pointer to a constant instruction class descriptor. */
     144typedef const DISARMV8INSNCLASS *PCDISARMV8INSNCLASS;
     145
     146/** The instruction class distinguishes between a 32-bit and 64-bit variant using the sf bit (bit 31). */
     147#define DISARMV8INSNCLASS_F_SF                          RT_BIT_32(0)
     148/** The N bit in an N:ImmR:ImmS bit vector must be 1 for 64-bit instruction variants. */
     149#define DISARMV8INSNCLASS_F_N_FORCED_1_ON_64BIT         RT_BIT_32(1)
     150/** The instruction class is using the 64-bit register encoding only. */
     151#define DISARMV8INSNCLASS_F_FORCED_64BIT                RT_BIT_32(2)
     152
     153
     154#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_BEGIN(a_Name) \
     155    static const DISOPCODE a_Name ## Opcodes[] = {
     156#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_PARAMS(a_Name, a_fClass, a_enmOpcDecode, a_fMask, a_cShift) \
     157    }; \
     158    static const DISARMV8INSNCLASS a_Name = { { kDisArmV8DecodeType_InsnClass, RT_ELEMENTS(a_Name ## Opcodes) }, &a_Name ## Opcodes[0],\
     159                                              a_fClass, a_enmOpcDecode, a_fMask, a_cShift, {
     160#define DIS_ARMV8_DECODE_INSN_CLASS_DEFINE_END } }
     161
     162/**
     163 * Decoder lookup table entry.
     164 */
     165typedef struct DISARMV8DECODETBLENTRY
     166{
     167    /** The mask to apply to the instruction. */
     168    uint32_t                    fMask;
     169    /** The value the masked instruction must match for the entry to match. */
     170    uint32_t                    fValue;
     171    /** The next stage followed when there is a match. */
     172    PCDISARMV8DECODEHDR         pHdrNext;
     173} DISARMV8DECODETBLENTRY;
     174typedef struct DISARMV8DECODETBLENTRY *PDISARMV8DECODETBLENTRY;
     175typedef const DISARMV8DECODETBLENTRY *PCDISARMV8DECODETBLENTRY;
     176
     177
     178#define DIS_ARMV8_DECODE_TBL_ENTRY_INIT(a_fMask, a_fValue, a_pNext) \
     179    { a_fMask, a_fValue, &a_pNext.Hdr }
     180
     181
     182/**
     183 * Decoder lookup table using masks and values.
     184 */
     185typedef struct DISARMV8DECODETBL
     186{
     187    /** The header for the decoder lookup table. */
     188    DISARMV8DECODEHDR           Hdr;
     189    /** Pointer to the individual entries. */
     190    PCDISARMV8DECODETBLENTRY    paEntries;
     191} DISARMV8DECODETBL;
     192/** Pointer to a const decode table. */
     193typedef const struct DISARMV8DECODETBL *PCDISARMV8DECODETBL;
     194
     195
     196#define DIS_ARMV8_DECODE_TBL_DEFINE_BEGIN(a_Name) \
     197    static const DISARMV8DECODETBLENTRY a_Name ## TblEnt[] = {
     198
     199#define DIS_ARMV8_DECODE_TBL_DEFINE_END(a_Name) \
     200    }; \
     201    static const DISARMV8DECODETBL a_Name = { { kDisArmV8DecodeType_Table, RT_ELEMENTS(a_Name ## TblEnt) }, &a_Name ## TblEnt[0] }
     202
     203
     204/**
     205 * Decoder map when direct indexing is possible.
     206 */
     207typedef struct DISARMV8DECODEMAP
     208{
     209    /** The header for the decoder map. */
     210    DISARMV8DECODEHDR           Hdr;
     211    /** The bitmask used to decide where to go next. */
     212    uint32_t                    fMask;
     213    /** Amount to shift to get at the index. */
     214    uint32_t                    cShift;
     215    /** Pointer to the array of pointers to the next stage to index into. */
     216    PPCDISARMV8DECODEHDR        papNext;
     217} DISARMV8DECODEMAP;
     218/** Pointer to a const decode map. */
     219typedef const struct DISARMV8DECODEMAP *PCDISARMV8DECODEMAP;
     220
     221#define DIS_ARMV8_DECODE_MAP_DEFINE_BEGIN(a_Name) \
     222    static const PCDISARMV8DECODEHDR a_Name ## MapHdrs[] = {
     223
     224#define DIS_ARMV8_DECODE_MAP_DEFINE_END(a_Name, a_fMask, a_cShift) \
     225    }; \
     226    static const DISARMV8DECODEMAP a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(a_Name ## MapHdrs) }, a_fMask, a_cShift, &a_Name ## MapHdrs[0] }
     227
     228#define DIS_ARMV8_DECODE_MAP_DEFINE_END_NON_STATIC(a_Name, a_fMask, a_cShift) \
     229    }; \
     230    DECL_HIDDEN_CONST(DISARMV8DECODEMAP) a_Name = { { kDisArmV8DecodeType_Map, RT_ELEMENTS(a_Name ## MapHdrs) }, a_fMask, a_cShift, &a_Name ## MapHdrs[0] }
     231
     232#define DIS_ARMV8_DECODE_MAP_INVALID_ENTRY NULL
     233#define DIS_ARMV8_DECODE_MAP_ENTRY(a_Next) &a_Next.Hdr
     234
     235
     236/** @name Decoder maps.
     237 * @{ */
     238extern DECL_HIDDEN_DATA(DISOPCODE) g_ArmV8A64InvalidOpcode[1];
     239
     240extern DECL_HIDDEN_DATA(DISARMV8DECODEMAP) g_ArmV8A64DecodeL0;
     241/** @} */
     242
    57243
    58244/** @} */
  • trunk/src/VBox/Disassembler/Makefile.kmk

    r99241 r99319  
    5858        Disasm.cpp \
    5959        DisasmCore-armv8.cpp \
    60         DisasmFormatBytes.cpp
     60        DisasmTables-armv8.cpp \
     61        DisasmFormatBytes.cpp \
     62        DisasmFormatArmV8.cpp
    6163endif
    6264
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