VirtualBox

Changeset 95167 in vbox for trunk


Ignore:
Timestamp:
Jun 1, 2022 7:38:29 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151664
Message:

VMM/IEM,DIS: Refreshed my memory on generating disassembler tables from IEM, making some related VEX table+code optimizations (saves a few Ks of data and some code bytes too). bugref:6251

Location:
trunk/src/VBox
Files:
4 edited

Legend:

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

    r93742 r95167  
    24792479    RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
    24802480
    2481     PCDISOPCODE pOpCode = &g_InvalidOpcode[0];
    2482 
    24832481    uint8_t byte = disReadByte(pDis, offInstr++);
    24842482    pDis->bOpCode = disReadByte(pDis, offInstr++);
     
    24942492    }
    24952493
    2496     switch(byte & 3)
    2497     {
    2498         case 0:
    2499             pOpCode = g_aVexOpcodesMap[0] + pDis->bOpCode;
    2500         break;
    2501         // 0x66 prefix
    2502         case 1:
    2503             pOpCode = g_aVexOpcodesMap_66H[0] + pDis->bOpCode;
    2504 
    2505         break;
    2506 
    2507         // 0xF3 prefix
    2508         case 2:
    2509             pOpCode = g_aVexOpcodesMap_F3H[0] + pDis->bOpCode;
    2510         break;
    2511 
    2512         // 0xF2 prefix
    2513         case 3:
    2514             pOpCode = g_aVexOpcodesMap_F2H[0] + pDis->bOpCode;
    2515         break;
    2516         default:
    2517         break;
    2518     }
     2494    PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[byte & 3][1];
     2495    unsigned  const      idxOpcode = pDis->bOpCode - pRange->idxFirst;
     2496    PCDISOPCODE          pOpCode;
     2497    if (idxOpcode < pRange->cOpcodes)
     2498        pOpCode = &pRange->papOpcodes[idxOpcode];
     2499    else
     2500        pOpCode = &g_InvalidOpcode[0];
    25192501
    25202502    return disParseInstruction(offInstr, pOpCode, pDis);
     
    25252507{
    25262508    RT_NOREF_PV(pOp); RT_NOREF_PV(pParam);
    2527 
    2528     PCDISOPCODE pOpCode = NULL;
    25292509
    25302510    uint8_t byte1 = disReadByte(pDis, offInstr++);
     
    25462526        pDis->fPrefix |= DISPREFIX_REX;
    25472527
    2548     switch(byte2 & 3)
    2549     {
    2550         case 0:
    2551             if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
    2552             {
    2553                 pOpCode = g_aVexOpcodesMap[implOpcode - 1];
    2554                 if (pOpCode != NULL)
    2555                 {
    2556                     switch (implOpcode)
    2557                     {
    2558                         case 2:
    2559                             if (pDis->bOpCode >= 0xf0)
    2560                                 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
    2561                             else pOpCode = g_InvalidOpcode;
    2562                             break;
    2563                         default:
    2564                         pOpCode = &pOpCode[pDis->bOpCode];
    2565                     }
    2566                 }
    2567             }
    2568         break;
    2569         // 0x66 prefix
    2570         case 1:
    2571             if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
    2572             {
    2573                 pOpCode = g_aVexOpcodesMap_66H[implOpcode - 1];
    2574                 if (pOpCode != NULL)
    2575                     pOpCode = &pOpCode[pDis->bOpCode];
    2576             }
    2577         break;
    2578 
    2579         // 0xF3 prefix
    2580         case 2:
    2581             if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
    2582             {
    2583                 pOpCode = g_aVexOpcodesMap_F3H[implOpcode - 1];
    2584                 if (pOpCode != NULL)
    2585                 {
    2586                     switch (implOpcode)
    2587                     {
    2588                         case 2:
    2589                             if (pDis->bOpCode >= 0xf0)
    2590                                 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
    2591                             else pOpCode = g_InvalidOpcode;
    2592                             break;
    2593                         default:
    2594                         pOpCode = &pOpCode[pDis->bOpCode];
    2595                     }
    2596                 }
    2597 
    2598             }
    2599         break;
    2600 
    2601         // 0xF2 prefix
    2602         case 3:
    2603             if (implOpcode >= 1 && implOpcode <= 3) // Other values are #UD.
    2604             {
    2605                 pOpCode = g_aVexOpcodesMap_F2H[implOpcode - 1];
    2606                 if (pOpCode != NULL)
    2607                 {
    2608                     switch (implOpcode)
    2609                     {
    2610                         case 2:
    2611                             if (pDis->bOpCode >= 0xf0)
    2612                                 pOpCode = &pOpCode[pDis->bOpCode - 0xf0];
    2613                             else pOpCode = g_InvalidOpcode;
    2614                             break;
    2615                         case 3:
    2616                             if (pDis->bOpCode != 0xf0)
    2617                                 pOpCode = g_InvalidOpcode;
    2618                             break;
    2619                         default:
    2620                         pOpCode = &pOpCode[pDis->bOpCode];
    2621                     }
    2622                 }
    2623             }
    2624         break;
    2625 
    2626         default:
    2627         break;
    2628     }
    2629 
    2630     if (pOpCode == NULL)
    2631         pOpCode = g_InvalidOpcode;
     2528    PCDISOPCODE pOpCode;
     2529    if (implOpcode < RT_ELEMENTS(g_aapVexOpcodesMapRanges[byte2 & 3]))
     2530    {
     2531        PCDISOPMAPDESC const pRange    = g_aapVexOpcodesMapRanges[byte2 & 3][implOpcode];
     2532        unsigned  const      idxOpcode = pDis->bOpCode - pRange->idxFirst;
     2533        if (idxOpcode < pRange->cOpcodes)
     2534            pOpCode = &pRange->papOpcodes[idxOpcode];
     2535        else
     2536            pOpCode = &g_InvalidOpcode[0];
     2537    }
     2538    else
     2539        pOpCode = &g_InvalidOpcode[0];
    26322540
    26332541    return disParseInstruction(offInstr, pOpCode, pDis);
  • trunk/src/VBox/Disassembler/DisasmInternal.h

    r93115 r95167  
    8585/** @}  */
    8686
     87/**
     88 * Opcode map descriptor.
     89 *
     90 * This is used a number of places to save storage space where there are lots of
     91 * invalid instructions and the beginning or end of the map.
     92 */
     93typedef struct DISOPMAPDESC
     94{
     95    /** Pointer to the opcodes described by this structure. */
     96    PCDISOPCODE     papOpcodes;
     97#if ARCH_BITS <= 32
     98    uint16_t
     99#else
     100    uint32_t
     101#endif
     102    /** The map index corresponding to the first papOpcodes entry. */
     103                    idxFirst,
     104    /** Number of opcodes in the map. */
     105                    cOpcodes;
     106} DISOPMAPDESC;
     107/** Pointer to a const opcode map descriptor. */
     108typedef DISOPMAPDESC const *PCDISOPMAPDESC;
    87109
    88110/** @name Opcode maps.
     
    125147/** VEX opcodes table defined by [VEX.m-mmmm - 1].
    126148  * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 00b */
    127 extern PCDISOPCODE const g_aVexOpcodesMap[3];
     149extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_None[3];
    128150
    129151/** VEX opcodes table defined by [VEX.m-mmmm - 1].
    130152  * 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 01b (66h) */
    131 extern PCDISOPCODE const g_aVexOpcodesMap_66H[3];
     153extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_66H[3];
    132154
    133155/** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 10b (F3h) */
    134 extern PCDISOPCODE const g_aVexOpcodesMap_F3H[3];
     156extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F3H[3];
    135157
    136158/** 0Fh, 0F38h, 0F3Ah correspondingly, VEX.pp = 11b (F2h) */
    137 extern PCDISOPCODE const g_aVexOpcodesMap_F2H[3];
     159extern PCDISOPMAPDESC const g_apVexOpcodesMapRanges_F2H[3];
     160
     161/** Two dimmentional map descriptor array: first index is by VEX.pp (prefix),
     162 * second by the VEX.mmmm (map).
     163 * The latter has to be bounced checked as we only have the first 4 maps. */
     164extern PCDISOPMAPDESC const g_aapVexOpcodesMapRanges[4][4];
    138165/** @} */
    139166
  • trunk/src/VBox/Disassembler/DisasmTables.cpp

    r93115 r95167  
    32073207
    32083208/* Vex codes for two bytes opcodes starting with 0Fh */
    3209 const DISOPCODE g_aMapTwoBytesVex[256] =
    3210 {
    3211     /* 0 */
    3212     INVALID_OPCODE_BLOCK
    3213 
     3209const DISOPCODE g_aDisasVexMap1[] =
     3210{
    32143211    /* 1 */
    32153212    OPVEX("vmovups %Vps,%Wps",       IDX_ParseModRM,     IDX_UseModRM,       0,              0,          OP_MOVUPS,      OP_PARM_Vps,    OP_PARM_Wps,    OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_HARMLESS),
     
    33173314    INVALID_OPCODE,
    33183315    OPVEX("vshufps %Vps,%Hps,%Wps,%Ib",  IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,   IDX_ParseImmByte,  OP_SHUFPS,   OP_PARM_Vps,  OP_PARM_Hps,  OP_PARM_Wps,   OP_PARM_Ib,     DISOPTYPE_HARMLESS),
    3319     INVALID_OPCODE,
    3320     INVALID_OPCODE,
    3321     INVALID_OPCODE,
    3322     INVALID_OPCODE,
    3323     INVALID_OPCODE,
    3324     INVALID_OPCODE,
    3325     INVALID_OPCODE,
    3326     INVALID_OPCODE,
    3327     INVALID_OPCODE,
    3328 
    3329     /* d */
    3330     INVALID_OPCODE_BLOCK
    3331 
    3332     /* e */
    3333     INVALID_OPCODE_BLOCK
    3334 
    3335     /* f */
    3336     INVALID_OPCODE_BLOCK
    3337 };
     3316};
     3317const DISOPMAPDESC g_DisasVexMap1Range = { &g_aDisasVexMap1[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1) };
    33383318
    33393319/* Vex codes for two bytes opcodes starting with 0Fh with prefix 66H*/
    3340 const DISOPCODE g_aMapTwoBytesVex_66H[256] =
    3341 {
    3342     /* 0 */
    3343     INVALID_OPCODE_BLOCK
    3344 
     3320static const DISOPCODE g_aDisasVexMap1_66[] =
     3321{
    33453322    /* 1 */
    33463323    OPVEX("vmovupd %Vpd,%Wpd",       IDX_ParseModRM,     IDX_UseModRM,       0,              0,          OP_MOVUPD,      OP_PARM_Vpd,    OP_PARM_Wpd,    OP_PARM_NONE,   OP_PARM_NONE,   DISOPTYPE_HARMLESS),
     
    35233500    OPVEX("vpaddw %Vx,%Hx,%Wx",       IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_PADDW,     OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wx,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
    35243501    OPVEX("vpaddd %Vx,%Hx,%Wx",       IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_PADDD,     OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wx,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3525     INVALID_OPCODE,
    3526 };
    3527 
    3528 const DISOPCODE g_aMapTwoBytesVex_F2H[256] =
    3529 {
    3530     /* 0 */
    3531     INVALID_OPCODE_BLOCK
    3532 
     3502};
     3503const DISOPMAPDESC g_DisasVexMap1_66Range = { &g_aDisasVexMap1_66[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1_66) };
     3504
     3505static const DISOPCODE g_aDisasVexMap1F2[] =
     3506{
    35333507    /* 1 */
    35343508    OPVEX("vmovsd %Vx,%Hx,%Wsd",      IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_MOVSD,     OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wsd,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
     
    36653639    /* f */
    36663640    OPVEX("vlddqu %Vx,%Mx",         IDX_ParseModRM,    IDX_UseModRM,       0,                           0,  OP_LDDQU,  OP_PARM_Vx,   OP_PARM_Mx,   OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3667     INVALID_OPCODE,
    3668     INVALID_OPCODE,
    3669     INVALID_OPCODE,
    3670     INVALID_OPCODE,
    3671     INVALID_OPCODE,
    3672     INVALID_OPCODE,
    3673     INVALID_OPCODE,
    3674     INVALID_OPCODE,
    3675     INVALID_OPCODE,
    3676     INVALID_OPCODE,
    3677     INVALID_OPCODE,
    3678     INVALID_OPCODE,
    3679     INVALID_OPCODE,
    3680     INVALID_OPCODE,
    3681     INVALID_OPCODE,
    3682 };
     3641};
     3642const DISOPMAPDESC g_DisasVexMap1F2Range = { &g_aDisasVexMap1F2[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1F2) };
    36833643
    36843644/* Vex codes for two bytes opcodes starting with 0Fh with prefix F3H*/
    3685 const DISOPCODE g_aMapTwoBytesVex_F3H[256] =
    3686 {
    3687 
    3688     /* 0 */
    3689     INVALID_OPCODE_BLOCK
    3690 
     3645static const DISOPCODE g_aDisasVexMap1F3[] =
     3646{
    36913647    /* 1 */
    36923648    OPVEX("vmovss %Vx,%Hx,%Wss",       IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_MOVSS,     OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wss,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
     
    38263782    INVALID_OPCODE,
    38273783    OPVEX("vcvtdq2pd %Vx,%Wpd",     IDX_ParseModRM,    IDX_UseModRM,       0,                           0,  OP_CVTDQ2PD,  OP_PARM_Vx,   OP_PARM_Wpd,   OP_PARM_NONE, OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3828     INVALID_OPCODE,
    3829     INVALID_OPCODE,
    3830     INVALID_OPCODE,
    3831     INVALID_OPCODE,
    3832     INVALID_OPCODE,
    3833     INVALID_OPCODE,
    3834     INVALID_OPCODE,
    3835     INVALID_OPCODE,
    3836     INVALID_OPCODE,
    3837 
    3838     /* f */
    3839     INVALID_OPCODE_BLOCK
    3840 };
    3841 
    3842 const DISOPCODE g_aMapThreeBytesVex_0F38_F[16] =
    3843 {
    3844     INVALID_OPCODE,
    3845     INVALID_OPCODE,
     3784};
     3785const DISOPMAPDESC g_DisasVexMap1F3Range = { &g_aDisasVexMap1F3[0], 0x10, RT_ELEMENTS(g_aDisasVexMap1F3) };
     3786
     3787static const DISOPCODE g_aDisasVexMap2[] =
     3788{
     3789    /** @todo vsha1nexte at 0xc8 + ? */
    38463790    OPVEX("andn %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_ANDN,      OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    38473791    INVALID_OPCODE,
     
    38503794    INVALID_OPCODE,
    38513795    OPVEX("bextr %Gy,%By,%Ey",   IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_BEXTR,     OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3852     INVALID_OPCODE,
    3853     INVALID_OPCODE,
    3854     INVALID_OPCODE,
    3855     INVALID_OPCODE,
    3856     INVALID_OPCODE,
    3857     INVALID_OPCODE,
    3858     INVALID_OPCODE,
    3859     INVALID_OPCODE
    3860 };
    3861 
    3862 const DISOPCODE g_aMapThreeBytesVex_F30F38_F[16] =
    3863 {
    3864     INVALID_OPCODE,
    3865     INVALID_OPCODE,
    3866     INVALID_OPCODE,
    3867     INVALID_OPCODE,
     3796};
     3797const DISOPMAPDESC g_DisasVexMap2Range = { &g_aDisasVexMap2[0], 0xf2, RT_ELEMENTS(g_aDisasVexMap2) };
     3798
     3799static const DISOPCODE g_aDisasVexMap2F3[] =
     3800{
     3801    /* 0xf3: */
     3802    INVALID_OPCODE, /** @todo vgrp17 */
    38683803    INVALID_OPCODE,
    38693804    OPVEX("pext %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_PEXT,      OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    38703805    INVALID_OPCODE,
    38713806    OPVEX("sarx %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_SARX,      OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3872     INVALID_OPCODE,
    3873     INVALID_OPCODE,
    3874     INVALID_OPCODE,
    3875     INVALID_OPCODE,
    3876     INVALID_OPCODE,
    3877     INVALID_OPCODE,
    3878     INVALID_OPCODE,
    3879     INVALID_OPCODE
    3880 };
    3881 
    3882 const DISOPCODE g_aMapThreeBytesVex_F20F38_F[16] =
    3883 {
    3884     INVALID_OPCODE,
    3885     INVALID_OPCODE,
    3886     INVALID_OPCODE,
    3887     INVALID_OPCODE,
    3888     INVALID_OPCODE,
     3807};
     3808const DISOPMAPDESC g_DisasVexMap2F3Range = { &g_aDisasVexMap2F3[0], 0xf3, RT_ELEMENTS(g_aDisasVexMap2F3) };
     3809
     3810static const DISOPCODE g_aDisasVexMap2F2[16] =
     3811{
    38893812    OPVEX("pdep %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_PDEP,      OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3890     OPVEX("mulx %By,%Gy,%Ey",    IDX_ParseVexDest,    IDX_ParseModRM,   IDX_UseModRM,                0,  OP_MULX,      OP_PARM_By,   OP_PARM_Gy,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
     3813    OPVEX("mulx %By,%Gy,%Ey",    IDX_ParseVexDest,  IDX_ParseModRM,     IDX_UseModRM,                0,  OP_MULX,      OP_PARM_By,   OP_PARM_Gy,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    38913814    OPVEX("shrx %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_SHRX,      OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey,  OP_PARM_NONE, DISOPTYPE_HARMLESS),
    3892     INVALID_OPCODE,
    3893     INVALID_OPCODE,
    3894     INVALID_OPCODE,
    3895     INVALID_OPCODE,
    3896     INVALID_OPCODE,
    3897     INVALID_OPCODE,
    3898     INVALID_OPCODE,
    3899     INVALID_OPCODE
    3900 };
    3901 
    3902 const DISOPCODE g_aMapThreeBytesVex_660F38[256] =
    3903 {
    3904 
     3815};
     3816const DISOPMAPDESC g_DisasVexMap2F2Range = { &g_aDisasVexMap2F2[0], 0xf5, RT_ELEMENTS(g_aDisasVexMap2F2) };
     3817
     3818static const DISOPCODE g_aDisasVexMap2_66[] =
     3819{
    39053820    /* 0 */
    39063821    OPVEX("vpshufb %Vx,%Hx,%Wx",       IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,                0,  OP_PSHUFB,    OP_PARM_Vx,   OP_PARM_Hx,   OP_PARM_Wx,   OP_PARM_NONE, DISOPTYPE_HARMLESS),
     
    41484063    INVALID_OPCODE,
    41494064    OPVEX("shlx %Gy,%By,%Ey",    IDX_ParseModRM,    IDX_ParseVexDest,   IDX_UseModRM,  0,   OP_BEXTR,   OP_PARM_Gy,   OP_PARM_By,   OP_PARM_Ey, OP_PARM_NONE, DISOPTYPE_HARMLESS),
    4150     INVALID_OPCODE,
    4151     INVALID_OPCODE,
    4152     INVALID_OPCODE,
    4153     INVALID_OPCODE,
    4154     INVALID_OPCODE,
    4155     INVALID_OPCODE,
    4156     INVALID_OPCODE,
    4157     INVALID_OPCODE,
    4158 };
    4159 
    4160 const DISOPCODE g_aMapThreeBytesVex_660F3A[256] =
     4065};
     4066const DISOPMAPDESC g_DisasVexMap2_66Range = { &g_aDisasVexMap2_66[0], 0x00, RT_ELEMENTS(g_aDisasVexMap2_66) };
     4067
     4068const DISOPCODE g_aDisasVexMap3[] =
     4069{
     4070    INVALID_OPCODE, /* dummy */
     4071};
     4072const DISOPMAPDESC g_DisasVexMap3Range = { &g_aDisasVexMap3[0], 0, RT_ELEMENTS(g_aDisasVexMap3) };
     4073
     4074static const DISOPCODE g_aDisasVexMap3_66[] =
    41614075{
    41624076    /* 0 */
     
    43104224    INVALID_OPCODE,
    43114225    OPVEX("vaeskeygen %Vdq,%Wdq,%Ib",   IDX_ParseModRM,    IDX_UseModRM,   IDX_ParseImmByte,   0,   OP_AESKEYGEN,  OP_PARM_Vdq,   OP_PARM_Wdq,   OP_PARM_Ib,  OP_PARM_NONE,  DISOPTYPE_HARMLESS),
    4312 
    4313     /* e */
    4314     INVALID_OPCODE_BLOCK
    4315 
    4316     /* f */
    4317     INVALID_OPCODE_BLOCK
    4318 };
    4319 
    4320 const DISOPCODE g_aMapThreeBytesVex_F20F3A_F0[1] =
     4226};
     4227const DISOPMAPDESC g_DisasVexMap3_66Range = { &g_aDisasVexMap3_66[0], 0x00, RT_ELEMENTS(g_aDisasVexMap3_66) };
     4228
     4229const DISOPCODE g_aDisasVexMap3F2[] =
    43214230{
    43224231    OPVEX("rorx %Gy,%Ey,%Ib",    IDX_ParseModRM,    IDX_UseModRM,   IDX_ParseImmByte,   0,   OP_RORX,    OP_PARM_Gy,  OP_PARM_Ey,  OP_PARM_Ib,  OP_PARM_NONE,  DISOPTYPE_HARMLESS),
    43234232};
    4324 
    4325 
    4326 PCDISOPCODE const g_aVexOpcodesMap[3] =
    4327 {
    4328     &g_aMapTwoBytesVex[0],         // 0fh 2-byte opcodes
    4329     &g_aMapThreeBytesVex_0F38_F[0],// 0f38h 3-byte opcodes
    4330     NULL,                          // 0f3ah 3-byte opcodes
    4331 };
    4332 
    4333 PCDISOPCODE const g_aVexOpcodesMap_66H[3] =
    4334 {
    4335     &g_aMapTwoBytesVex_66H[0],     // 0fh 2-byte opcodes
    4336     &g_aMapThreeBytesVex_660F38[0],// 0f38h 3-byte opcodes
    4337     &g_aMapThreeBytesVex_660F3A[0],// 0f3ah 3-byte opcodes
    4338 };
    4339 
    4340 PCDISOPCODE const g_aVexOpcodesMap_F2H[3] =
    4341 {
    4342     &g_aMapTwoBytesVex_F2H[0],       // 0fh 2-byte opcodes
    4343     &g_aMapThreeBytesVex_F20F38_F[0],// 0f38h 3-byte opcodes
    4344     &g_aMapThreeBytesVex_F20F3A_F0[0],// 0f3ah 3-byte opcodes
    4345 };
    4346 
    4347 PCDISOPCODE const g_aVexOpcodesMap_F3H[3] =
    4348 {
    4349     &g_aMapTwoBytesVex_F3H[0],       // 0fh 2-byte opcodes
    4350     &g_aMapThreeBytesVex_F30F38_F[0],// 0f38h 3-byte opcodes
    4351     NULL,                            // 0f3ah 3-byte opcodes
    4352 };
     4233const DISOPMAPDESC g_DisasVexMap3F2Range = { &g_aDisasVexMap3F2[0], 0xf0, RT_ELEMENTS(g_aDisasVexMap3F2) };
     4234
     4235const DISOPCODE g_aDisasVexMap3F3[] =
     4236{
     4237    INVALID_OPCODE, /* dummy */
     4238};
     4239const DISOPMAPDESC g_DisasVexMap3F3Range = { &g_aDisasVexMap3F3[0], 0, RT_ELEMENTS(g_aDisasVexMap3F3) };
     4240
     4241
     4242/** Invalid range for the g_aapVexOpcodesMapRanges table.  */
     4243const DISOPMAPDESC g_DisasVexMapInvalidRange = { &g_InvalidOpcode[0], 0, 1 };
     4244
     4245
     4246PCDISOPMAPDESC const g_aapVexOpcodesMapRanges[4][4] =
     4247{
     4248    /* No prefix: */
     4249    {
     4250        &g_DisasVexMapInvalidRange,
     4251        &g_DisasVexMap1Range,           // 0fh 2-byte opcodes
     4252        &g_DisasVexMap2Range,           // 0f38h 3-byte opcodes
     4253        &g_DisasVexMap3Range,           // 0f3ah 3-byte opcodes
     4254    },
     4255    /* 66h prefix: */
     4256    {
     4257        &g_DisasVexMapInvalidRange,
     4258        &g_DisasVexMap1_66Range,        // 0fh 2-byte opcodes
     4259        &g_DisasVexMap2_66Range,        // 0f38h 3-byte opcodes
     4260        &g_DisasVexMap3_66Range,        // 0f3ah 3-byte opcodes
     4261    },
     4262    /* f3h prefix: */
     4263    {
     4264        &g_DisasVexMapInvalidRange,
     4265        &g_DisasVexMap1F3Range,         // 0fh 2-byte opcodes
     4266        &g_DisasVexMap2F3Range,         // 0f38h 3-byte opcodes
     4267        &g_DisasVexMap3F3Range,         // 0f3ah 3-byte opcodes
     4268    },
     4269    /* f2h prefix: */
     4270    {
     4271        &g_DisasVexMapInvalidRange,
     4272        &g_DisasVexMap1F2Range,        // 0fh 2-byte opcodes
     4273        &g_DisasVexMap2F2Range,        // 0f38h 3-byte opcodes2
     4274        &g_DisasVexMap3F2Range,        // 0f3ah 3-byte opcodes
     4275    }
     4276};
     4277
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py

    r93115 r95167  
    221221    'Ew':           ( 'IDX_UseModRM',       'rm',     '%Ew',  'Ew',      'RM',    ),
    222222    'Ev':           ( 'IDX_UseModRM',       'rm',     '%Ev',  'Ev',      'RM',    ),
     223    'Ey':           ( 'IDX_UseModRM',       'rm',     '%Ey',  'Ey',      'RM',    ),
    223224    'Qq':           ( 'IDX_UseModRM',       'rm',     '%Qq',  'Qq',      'RM',    ),
    224225    'Qq_WO':        ( 'IDX_UseModRM',       'rm',     '%Qq',  'Qq',      'RM',    ),
     
    270271    'Gv':           ( 'IDX_UseModRM',       'reg',    '%Gv',  'Gv',      '',      ),
    271272    'Gv_RO':        ( 'IDX_UseModRM',       'reg',    '%Gv',  'Gv',      '',      ),
     273    'Gy':           ( 'IDX_UseModRM',       'reg',    '%Gy',  'Gy',      '',      ),
    272274    'Pd':           ( 'IDX_UseModRM',       'reg',    '%Pd',  'Pd',      '',      ),
    273275    'PdZx_WO':      ( 'IDX_UseModRM',       'reg',    '%Pd',  'PdZx',    '',      ),
     
    298300
    299301    # VEX.vvvv
     302    'By':           ( 'IDX_UseModRM',       'vvvv',   '%By',  'By',      'V',     ),
    300303    'HssHi':        ( 'IDX_UseModRM',       'vvvv',   '%Hx',  'HssHi',   'V',     ),
    301304    'HsdHi':        ( 'IDX_UseModRM',       'vvvv',   '%Hx',  'HsdHi',   'V',     ),
     
    368371    'VEX_RVM_REG':  ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm' ], '11 mr/reg',   ),
    369372    'VEX_RVM_MEM':  ( 'VEX.ModR/M', [ 'reg', 'vvvv', 'rm' ], '!11 mr/reg',  ),
     373    'VEX_RMV':      ( 'VEX.ModR/M', [ 'reg', 'rm', 'vvvv' ], '',            ),
     374    'VEX_RMV_REG':  ( 'VEX.ModR/M', [ 'reg', 'rm', 'vvvv' ], '11 mr/reg',   ),
     375    'VEX_RMV_MEM':  ( 'VEX.ModR/M', [ 'reg', 'rm', 'vvvv' ], '!11 mr/reg',  ),
    370376    'VEX_MVR':      ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg' ], '',            ),
    371377    'VEX_MVR_REG':  ( 'VEX.ModR/M', [ 'rm', 'vvvv', 'reg' ], '11 mr/reg',   ),
     
    595601    };
    596602    ## Selectors.
    597     ## The first value is the number of table entries required by a
     603    ## 1. The first value is the number of table entries required by a
    598604    ## decoder or disassembler for this type of selector.
     605    ## 2. The second value is how many entries per opcode byte if applicable.
    599606    kdSelectors = {
    600         'byte':     [ 256, ], ##< next opcode byte selects the instruction (default).
    601         '/r':       [   8, ], ##< modrm.reg selects the instruction.
    602         'memreg /r':[  16, ], ##< modrm.reg and (modrm.mod == 3) selects the instruction.
    603         'mod /r':   [  32, ], ##< modrm.reg and modrm.mod selects the instruction.
    604         '!11 /r':   [   8, ], ##< modrm.reg selects the instruction with modrm.mod != 0y11.
    605         '11 /r':    [   8, ], ##< modrm.reg select the instruction with modrm.mod == 0y11.
    606         '11':       [  64, ], ##< modrm.reg and modrm.rm select the instruction with modrm.mod == 0y11.
     607        'byte':     [  256, 1, ], ##< next opcode byte selects the instruction (default).
     608        'byte+pfx': [ 1024, 4, ], ##< next opcode byte selects the instruction together with the 0x66, 0xf2 and 0xf3 prefixes.
     609        '/r':       [    8, 1, ], ##< modrm.reg selects the instruction.
     610        'memreg /r':[   16, 1, ], ##< modrm.reg and (modrm.mod == 3) selects the instruction.
     611        'mod /r':   [   32, 1, ], ##< modrm.reg and modrm.mod selects the instruction.
     612        '!11 /r':   [    8, 1, ], ##< modrm.reg selects the instruction with modrm.mod != 0y11.
     613        '11 /r':    [    8, 1, ], ##< modrm.reg select the instruction with modrm.mod == 0y11.
     614        '11':       [   64, 1, ], ##< modrm.reg and modrm.rm select the instruction with modrm.mod == 0y11.
    607615    };
    608616
    609     def __init__(self, sName, asLeadOpcodes = None, sSelector = 'byte', sEncoding = 'legacy', sDisParse = None):
     617    ## Define the subentry number according to the Instruction::sPrefix
     618    ## value for 'byte+pfx' selected tables.
     619    kiPrefixOrder = {
     620        'none': 0,
     621        '0x66': 1,
     622        '0xf3': 2,
     623        '0xf2': 3,
     624    };
     625
     626    def __init__(self, sName, sIemName = None, asLeadOpcodes = None, sSelector = 'byte+pfx',
     627                 sEncoding = 'legacy', sDisParse = None):
    610628        assert sSelector in self.kdSelectors;
    611629        assert sEncoding in self.kdEncodings;
     
    618636
    619637        self.sName          = sName;
     638        self.sIemName       = sIemName;
    620639        self.asLeadOpcodes  = asLeadOpcodes;    ##< Lead opcode bytes formatted as hex strings like '0x0f'.
    621640        self.sSelector      = sSelector;        ##< The member selector, see kdSelectors.
     
    624643        self.sDisParse      = sDisParse;        ##< IDX_ParseXXX.
    625644
     645    def copy(self, sNewName, sPrefixFilter = None):
     646        """
     647        Copies the table with filtering instruction by sPrefix if not None.
     648        """
     649        oCopy = InstructionMap(sNewName, sIemName = self.sIemName, asLeadOpcodes = self.asLeadOpcodes,
     650                               sSelector = 'byte' if sPrefixFilter is not None and self.sSelector == 'byte+pfx'
     651                               else self.sSelector,
     652                               sEncoding = self.sEncoding, sDisParse = self.sDisParse);
     653        if sPrefixFilter is None:
     654            oCopy.aoInstructions = list(self.aoInstructions);
     655        else:
     656            oCopy.aoInstructions = [oInstr for oInstr in self.aoInstructions if oInstr.sPrefix == sPrefixFilter];
     657        return oCopy;
     658
    626659    def getTableSize(self):
    627660        """
     
    630663        return self.kdSelectors[self.sSelector][0];
    631664
     665    def getEntriesPerByte(self):
     666        """
     667        Number of table entries per opcode bytes.
     668
     669        This only really makes sense for the 'byte' and 'byte+pfx' selectors, for
     670        the others it will just return 1.
     671        """
     672        return self.kdSelectors[self.sSelector][1];
     673
    632674    def getInstructionIndex(self, oInstr):
    633675        """
     
    636678        bOpcode = oInstr.getOpcodeByte();
    637679
    638         # The byte selector is simple.  We need a full opcode byte and need just return it.
     680        # The byte selectors are simple.  We need a full opcode byte and need just return it.
    639681        if self.sSelector == 'byte':
    640682            assert oInstr.sOpcode[:2] == '0x' and len(oInstr.sOpcode) == 4, str(oInstr);
    641683            return bOpcode;
     684
     685        # The byte + prefix selector is similarly simple, though requires a prefix as well as the full opcode.
     686        if self.sSelector  == 'byte+pfx':
     687            assert oInstr.sOpcode[:2] == '0x' and len(oInstr.sOpcode) == 4, str(oInstr);
     688            assert self.kiPrefixOrder.get(oInstr.sPrefix, -16384) >= 0;
     689            return bOpcode * 4 + self.kiPrefixOrder.get(oInstr.sPrefix, -16384);
    642690
    643691        # The other selectors needs masking and shifting.
     
    717765        return sName;
    718766
     767    def getDisasRangeName(self):
     768        """
     769        Returns the disassembler table range name for this map.
     770        """
     771        return self.getDisasTableName().replace('g_aDisas', 'g_Disas') + 'Range';
    719772
    720773    def isVexMap(self):
     
    13381391        ## @name Core attributes.
    13391392        ## @{
     1393        self.oParent        = None      # type: Instruction
    13401394        self.sMnemonic      = None;
    13411395        self.sBrief         = None;
     
    13981452
    13991453        aasFields.append(['opcode',    self.sOpcode]);
     1454        if self.sPrefix:
     1455            aasFields.append(['prefix', self.sPrefix]);
    14001456        aasFields.append(['mnemonic',  self.sMnemonic]);
    14011457        for iOperand, oOperand in enumerate(self.aoOperands):
     
    14431499        return self.toString(True);
    14441500
     1501    def copy(self, oMap = None, sOpcode = None, sSubOpcode = None, sPrefix = None):
     1502        """
     1503        Makes a copy of the object for the purpose of putting in a different map
     1504        or a different place in the current map.
     1505        """
     1506        oCopy = Instruction(self.sSrcFile, self.iLineCreated);
     1507
     1508        oCopy.oParent           = self;
     1509        oCopy.sMnemonic         = self.sMnemonic;
     1510        oCopy.sBrief            = self.sBrief;
     1511        oCopy.asDescSections    = list(self.asDescSections);
     1512        oCopy.aoMaps            = [oMap,]    if oMap       else list(self.aoMaps);
     1513        oCopy.aoOperands        = list(self.aoOperands); ## Deeper copy?
     1514        oCopy.sPrefix           = sPrefix    if sPrefix    else self.sPrefix;
     1515        oCopy.sOpcode           = sOpcode    if sOpcode    else self.sOpcode;
     1516        oCopy.sSubOpcode        = sSubOpcode if sSubOpcode else self.sSubOpcode;
     1517        oCopy.sEncoding         = self.sEncoding;
     1518        oCopy.asFlTest          = self.asFlTest;
     1519        oCopy.asFlModify        = self.asFlModify;
     1520        oCopy.asFlUndefined     = self.asFlUndefined;
     1521        oCopy.asFlSet           = self.asFlSet;
     1522        oCopy.asFlClear         = self.asFlClear;
     1523        oCopy.dHints            = dict(self.dHints);
     1524        oCopy.sDisEnum          = self.sDisEnum;
     1525        oCopy.asCpuIds          = list(self.asCpuIds);
     1526        oCopy.asReqFeatures     = list(self.asReqFeatures);
     1527        oCopy.aoTests           = list(self.aoTests); ## Deeper copy?
     1528        oCopy.sMinCpu           = self.sMinCpu;
     1529        oCopy.oCpuExpr          = self.oCpuExpr;
     1530        oCopy.sGroup            = self.sGroup;
     1531        oCopy.fUnused           = self.fUnused;
     1532        oCopy.fInvalid          = self.fInvalid;
     1533        oCopy.sInvalidStyle     = self.sInvalidStyle;
     1534        oCopy.sXcptType         = self.sXcptType;
     1535
     1536        oCopy.sStats            = self.sStats;
     1537        oCopy.sFunction         = self.sFunction;
     1538        oCopy.fStub             = self.fStub;
     1539        oCopy.fUdStub           = self.fUdStub;
     1540
     1541        oCopy.iLineCompleted    = self.iLineCompleted;
     1542        oCopy.cOpTags           = self.cOpTags;
     1543        oCopy.iLineFnIemOpMacro = self.iLineFnIemOpMacro;
     1544        oCopy.iLineMnemonicMacro = self.iLineMnemonicMacro;
     1545
     1546        oCopy.sRawDisOpNo       = self.sRawDisOpNo;
     1547        oCopy.asRawDisParams    = list(self.asRawDisParams);
     1548        oCopy.sRawIemOpFlags    = self.sRawIemOpFlags;
     1549        oCopy.sRawOldOpcodes    = self.sRawOldOpcodes;
     1550        oCopy.asCopyTests       = list(self.asCopyTests);
     1551
     1552        return oCopy;
     1553
    14451554    def getOpcodeByte(self):
    14461555        """
     
    15281637
    15291638## Instruction maps.
    1530 g_dInstructionMaps = {
    1531     'one':          InstructionMap('one'),
    1532     'grp1_80':      InstructionMap('grp1_80',   asLeadOpcodes = ['0x80',]),
    1533     'grp1_81':      InstructionMap('grp1_81',   asLeadOpcodes = ['0x81',], sSelector = '/r'),
    1534     'grp1_82':      InstructionMap('grp1_82',   asLeadOpcodes = ['0x82',], sSelector = '/r'),
    1535     'grp1_83':      InstructionMap('grp1_83',   asLeadOpcodes = ['0x83',], sSelector = '/r'),
    1536     'grp1a':        InstructionMap('grp1a',     asLeadOpcodes = ['0x8f',], sSelector = '/r'),
    1537     'grp2_c0':      InstructionMap('grp2_c0',   asLeadOpcodes = ['0xc0',], sSelector = '/r'),
    1538     'grp2_c1':      InstructionMap('grp2_c1',   asLeadOpcodes = ['0xc1',], sSelector = '/r'),
    1539     'grp2_d0':      InstructionMap('grp2_d0',   asLeadOpcodes = ['0xd0',], sSelector = '/r'),
    1540     'grp2_d1':      InstructionMap('grp2_d1',   asLeadOpcodes = ['0xd1',], sSelector = '/r'),
    1541     'grp2_d2':      InstructionMap('grp2_d2',   asLeadOpcodes = ['0xd2',], sSelector = '/r'),
    1542     'grp2_d3':      InstructionMap('grp2_d3',   asLeadOpcodes = ['0xd3',], sSelector = '/r'),
    1543     'grp3_f6':      InstructionMap('grp3_f6',   asLeadOpcodes = ['0xf6',], sSelector = '/r'),
    1544     'grp3_f7':      InstructionMap('grp3_f7',   asLeadOpcodes = ['0xf7',], sSelector = '/r'),
    1545     'grp4':         InstructionMap('grp4',      asLeadOpcodes = ['0xfe',], sSelector = '/r'),
    1546     'grp5':         InstructionMap('grp5',      asLeadOpcodes = ['0xff',], sSelector = '/r'),
    1547     'grp11_c6_m':   InstructionMap('grp11_c6_m',asLeadOpcodes = ['0xc6',], sSelector = '!11 /r'),
    1548     'grp11_c6_r':   InstructionMap('grp11_c6_r',asLeadOpcodes = ['0xc6',], sSelector = '11'),    # xabort
    1549     'grp11_c7_m':   InstructionMap('grp11_c7_m',asLeadOpcodes = ['0xc7',], sSelector = '!11 /r'),
    1550     'grp11_c7_r':   InstructionMap('grp11_c7_r',asLeadOpcodes = ['0xc7',], sSelector = '11'),    # xbegin
    1551 
    1552     'two0f':        InstructionMap('two0f',     asLeadOpcodes = ['0x0f',], sDisParse = 'IDX_ParseTwoByteEsc'),
    1553     'grp6':         InstructionMap('grp6',      asLeadOpcodes = ['0x0f', '0x00',], sSelector = '/r'),
    1554     'grp7_m':       InstructionMap('grp7_m',    asLeadOpcodes = ['0x0f', '0x01',], sSelector = '!11 /r'),
    1555     'grp7_r':       InstructionMap('grp7_r',    asLeadOpcodes = ['0x0f', '0x01',], sSelector = '11'),
    1556     'grp8':         InstructionMap('grp8',      asLeadOpcodes = ['0x0f', '0xba',], sSelector = '/r'),
    1557     'grp9':         InstructionMap('grp9',      asLeadOpcodes = ['0x0f', '0xc7',], sSelector = 'mod /r'),
    1558     'grp10':        InstructionMap('grp10',     asLeadOpcodes = ['0x0f', '0xb9',], sSelector = '/r'), # UD1 /w modr/m
    1559     'grp12':        InstructionMap('grp12',     asLeadOpcodes = ['0x0f', '0x71',], sSelector = 'mod /r'),
    1560     'grp13':        InstructionMap('grp13',     asLeadOpcodes = ['0x0f', '0x72',], sSelector = 'mod /r'),
    1561     'grp14':        InstructionMap('grp14',     asLeadOpcodes = ['0x0f', '0x73',], sSelector = 'mod /r'),
    1562     'grp15':        InstructionMap('grp15',     asLeadOpcodes = ['0x0f', '0xae',], sSelector = 'memreg /r'),
    1563     'grp16':        InstructionMap('grp16',     asLeadOpcodes = ['0x0f', '0x18',], sSelector = 'mod /r'),
    1564     'grpA17':       InstructionMap('grpA17',    asLeadOpcodes = ['0x0f', '0x78',], sSelector = '/r'), # AMD: EXTRQ weirdness
    1565     'grpP':         InstructionMap('grpP',      asLeadOpcodes = ['0x0f', '0x0d',], sSelector = '/r'), # AMD: prefetch
    1566 
    1567     'three0f38':    InstructionMap('three0f38', asLeadOpcodes = ['0x0f', '0x38',]),
    1568     'three0f3a':    InstructionMap('three0f3a', asLeadOpcodes = ['0x0f', '0x3a',]),
    1569 
    1570     'vexmap1':      InstructionMap('vexmap1',   sEncoding = 'vex1'),
    1571     'vexgrp12':     InstructionMap('vexgrp12',  sEncoding = 'vex1', asLeadOpcodes = ['0x71',], sSelector = 'mod /r'),
    1572     'vexgrp13':     InstructionMap('vexgrp13',  sEncoding = 'vex1', asLeadOpcodes = ['0x72',], sSelector = 'mod /r'),
    1573     'vexgrp14':     InstructionMap('vexgrp14',  sEncoding = 'vex1', asLeadOpcodes = ['0x73',], sSelector = 'mod /r'),
    1574     'vexgrp15':     InstructionMap('vexgrp15',  sEncoding = 'vex1', asLeadOpcodes = ['0xae',], sSelector = 'memreg /r'),
    1575     'vexgrp17':     InstructionMap('vexgrp17',  sEncoding = 'vex1', asLeadOpcodes = ['0xf3',], sSelector = '/r'),
    1576 
    1577     'vexmap2':      InstructionMap('vexmap2',   sEncoding = 'vex2'),
    1578     'vexmap3':      InstructionMap('vexmap3',   sEncoding = 'vex3'),
    1579 
    1580     '3dnow':        InstructionMap('3dnow',     asLeadOpcodes = ['0x0f', '0x0f',]),
    1581     'xopmap8':      InstructionMap('xopmap8',   sEncoding = 'xop8'),
    1582     'xopmap9':      InstructionMap('xopmap9',   sEncoding = 'xop9'),
    1583     'xopgrp1':      InstructionMap('xopgrp1',   sEncoding = 'xop9',  asLeadOpcodes = ['0x01'], sSelector = '/r'),
    1584     'xopgrp2':      InstructionMap('xopgrp2',   sEncoding = 'xop9',  asLeadOpcodes = ['0x02'], sSelector = '/r'),
    1585     'xopgrp3':      InstructionMap('xopgrp3',   sEncoding = 'xop9',  asLeadOpcodes = ['0x12'], sSelector = '/r'),
    1586     'xopmap10':     InstructionMap('xopmap10',  sEncoding = 'xop10'),
    1587     'xopgrp4':      InstructionMap('xopgrp4',   sEncoding = 'xop10', asLeadOpcodes = ['0x12'], sSelector = '/r'),
    1588 };
     1639g_aoInstructionMaps = [
     1640    InstructionMap('one',        'g_apfnOneByteMap',        sSelector = 'byte'),
     1641    InstructionMap('grp1_80',    asLeadOpcodes = ['0x80',], sSelector = '/r'),
     1642    InstructionMap('grp1_81',    asLeadOpcodes = ['0x81',], sSelector = '/r'),
     1643    InstructionMap('grp1_82',    asLeadOpcodes = ['0x82',], sSelector = '/r'),
     1644    InstructionMap('grp1_83',    asLeadOpcodes = ['0x83',], sSelector = '/r'),
     1645    InstructionMap('grp1a',      asLeadOpcodes = ['0x8f',], sSelector = '/r'),
     1646    InstructionMap('grp2_c0',    asLeadOpcodes = ['0xc0',], sSelector = '/r'),
     1647    InstructionMap('grp2_c1',    asLeadOpcodes = ['0xc1',], sSelector = '/r'),
     1648    InstructionMap('grp2_d0',    asLeadOpcodes = ['0xd0',], sSelector = '/r'),
     1649    InstructionMap('grp2_d1',    asLeadOpcodes = ['0xd1',], sSelector = '/r'),
     1650    InstructionMap('grp2_d2',    asLeadOpcodes = ['0xd2',], sSelector = '/r'),
     1651    InstructionMap('grp2_d3',    asLeadOpcodes = ['0xd3',], sSelector = '/r'),
     1652    ## @todo g_apfnEscF1_E0toFF
     1653    InstructionMap('grp3_f6',    asLeadOpcodes = ['0xf6',], sSelector = '/r'),
     1654    InstructionMap('grp3_f7',    asLeadOpcodes = ['0xf7',], sSelector = '/r'),
     1655    InstructionMap('grp4',       asLeadOpcodes = ['0xfe',], sSelector = '/r'),
     1656    InstructionMap('grp5',       asLeadOpcodes = ['0xff',], sSelector = '/r'),
     1657    InstructionMap('grp11_c6_m', asLeadOpcodes = ['0xc6',], sSelector = '!11 /r'),
     1658    InstructionMap('grp11_c6_r', asLeadOpcodes = ['0xc6',], sSelector = '11'),    # xabort
     1659    InstructionMap('grp11_c7_m', asLeadOpcodes = ['0xc7',], sSelector = '!11 /r'),
     1660    InstructionMap('grp11_c7_r', asLeadOpcodes = ['0xc7',], sSelector = '11'),    # xbegin
     1661
     1662    InstructionMap('two0f',      'g_apfnTwoByteMap',    asLeadOpcodes = ['0x0f',], sDisParse = 'IDX_ParseTwoByteEsc'),
     1663    InstructionMap('grp6',       'g_apfnGroup6',        asLeadOpcodes = ['0x0f', '0x00',], sSelector = '/r'),
     1664    InstructionMap('grp7_m',     'g_apfnGroup7Mem',     asLeadOpcodes = ['0x0f', '0x01',], sSelector = '!11 /r'),
     1665    InstructionMap('grp7_r',                            asLeadOpcodes = ['0x0f', '0x01',], sSelector = '11'),
     1666    InstructionMap('grp8',                              asLeadOpcodes = ['0x0f', '0xba',], sSelector = '/r'),
     1667    InstructionMap('grp9',       'g_apfnGroup9RegReg',  asLeadOpcodes = ['0x0f', '0xc7',], sSelector = 'mod /r'),
     1668    ## @todo What about g_apfnGroup9MemReg?
     1669    InstructionMap('grp10',      None,                  asLeadOpcodes = ['0x0f', '0xb9',], sSelector = '/r'), # UD1 /w modr/m
     1670    InstructionMap('grp12',      'g_apfnGroup12RegReg', asLeadOpcodes = ['0x0f', '0x71',], sSelector = 'mod /r'),
     1671    InstructionMap('grp13',      'g_apfnGroup13RegReg', asLeadOpcodes = ['0x0f', '0x72',], sSelector = 'mod /r'),
     1672    InstructionMap('grp14',      'g_apfnGroup14RegReg', asLeadOpcodes = ['0x0f', '0x73',], sSelector = 'mod /r'),
     1673    InstructionMap('grp15',      'g_apfnGroup15MemReg', asLeadOpcodes = ['0x0f', '0xae',], sSelector = 'memreg /r'),
     1674    ## @todo What about g_apfnGroup15RegReg?
     1675    InstructionMap('grp16',       asLeadOpcodes = ['0x0f', '0x18',], sSelector = 'mod /r'),
     1676    InstructionMap('grpA17',      asLeadOpcodes = ['0x0f', '0x78',], sSelector = '/r'), # AMD: EXTRQ weirdness
     1677    InstructionMap('grpP',        asLeadOpcodes = ['0x0f', '0x0d',], sSelector = '/r'), # AMD: prefetch
     1678
     1679    InstructionMap('three0f38',  'g_apfnThreeByte0f38',    asLeadOpcodes = ['0x0f', '0x38',]),
     1680    InstructionMap('three0f3a',  'g_apfnThreeByte0f3a',    asLeadOpcodes = ['0x0f', '0x3a',]),
     1681
     1682    InstructionMap('vexmap1',  'g_apfnVexMap1',          sEncoding = 'vex1'),
     1683    InstructionMap('vexgrp12', 'g_apfnVexGroup12RegReg', sEncoding = 'vex1', asLeadOpcodes = ['0x71',], sSelector = 'mod /r'),
     1684    InstructionMap('vexgrp13', 'g_apfnVexGroup13RegReg', sEncoding = 'vex1', asLeadOpcodes = ['0x72',], sSelector = 'mod /r'),
     1685    InstructionMap('vexgrp14', 'g_apfnVexGroup14RegReg', sEncoding = 'vex1', asLeadOpcodes = ['0x73',], sSelector = 'mod /r'),
     1686    InstructionMap('vexgrp15', 'g_apfnVexGroup15MemReg', sEncoding = 'vex1', asLeadOpcodes = ['0xae',], sSelector = 'memreg /r'),
     1687    InstructionMap('vexgrp17', 'g_apfnVexGroup17_f3',    sEncoding = 'vex1', asLeadOpcodes = ['0xf3',], sSelector = '/r'),
     1688
     1689    InstructionMap('vexmap2',  'g_apfnVexMap2',          sEncoding = 'vex2'),
     1690    InstructionMap('vexmap3',  'g_apfnVexMap3',          sEncoding = 'vex3'),
     1691
     1692    InstructionMap('3dnow',    asLeadOpcodes = ['0x0f', '0x0f',]),
     1693    InstructionMap('xopmap8',  sEncoding = 'xop8'),
     1694    InstructionMap('xopmap9',  sEncoding = 'xop9'),
     1695    InstructionMap('xopgrp1',  sEncoding = 'xop9',  asLeadOpcodes = ['0x01'], sSelector = '/r'),
     1696    InstructionMap('xopgrp2',  sEncoding = 'xop9',  asLeadOpcodes = ['0x02'], sSelector = '/r'),
     1697    InstructionMap('xopgrp3',  sEncoding = 'xop9',  asLeadOpcodes = ['0x12'], sSelector = '/r'),
     1698    InstructionMap('xopmap10', sEncoding = 'xop10'),
     1699    InstructionMap('xopgrp4',  sEncoding = 'xop10', asLeadOpcodes = ['0x12'], sSelector = '/r'),
     1700];
     1701g_dInstructionMaps          = { oMap.sName:    oMap for oMap in g_aoInstructionMaps };
     1702g_dInstructionMapsByIemName = { oMap.sIemName: oMap for oMap in g_aoInstructionMaps };
    15891703
    15901704
     
    16291743        self.oReGroupName   = re.compile('^og_[a-z0-9]+(|_[a-z0-9]+|_[a-z0-9]+_[a-z0-9]+)$');
    16301744        self.oReDisEnum     = re.compile('^OP_[A-Z0-9_]+$');
     1745        self.oReFunTable    = re.compile('^(IEM_STATIC|static) +const +PFNIEMOP +g_apfn[A-Za-z0-9_]+ *\[ *\d* *\] *= *$');
     1746        self.oReComment     = re.compile('//.*?$|/\*.*?\*/'); ## Full comments.
    16311747        self.fDebug         = True;
    16321748
     
    17261842            print('debug: %s' % (sMessage,));
    17271843
     1844    def stripComments(self, sLine):
     1845        """
     1846        Returns sLine with comments stripped.
     1847
     1848        Complains if traces of incomplete multi-line comments are encountered.
     1849        """
     1850        sLine = self.oReComment.sub(" ", sLine);
     1851        if sLine.find('/*') >= 0 or sLine.find('*/') >= 0:
     1852            self.error('Unexpected multi-line comment will not be handled correctly. Please simplify.');
     1853        return sLine;
     1854
     1855    def parseFunctionTable(self, sLine):
     1856        """
     1857        Parses a PFNIEMOP table, updating/checking the @oppfx value.
     1858
     1859        Note! Updates iLine as it consumes the whole table.
     1860        """
     1861
     1862        #
     1863        # Extract the table name.
     1864        #
     1865        sName = re.search(' *([a-zA-Z_0-9]+) *\[', sLine).group(1);
     1866        oMap  = g_dInstructionMapsByIemName.get(sName);
     1867        if not oMap:
     1868            self.debug('No map for PFNIEMOP table: %s' % (sName,));
     1869            oMap = self.oDefaultMap; # This is wrong wrong wrong.
     1870
     1871        #
     1872        # All but the g_apfnOneByteMap & g_apfnEscF1_E0toFF tables uses four
     1873        # entries per byte:
     1874        #       no prefix, 066h prefix, f3h prefix, f2h prefix
     1875        # Those tables has 256 & 32 entries respectively.
     1876        #
     1877        cEntriesPerByte   = 4;
     1878        cValidTableLength = 1024;
     1879        asPrefixes        = ('none', '0x66', '0xf3', '0xf2');
     1880
     1881        oEntriesMatch = re.search('\[ *(256|32) *\]', sLine);
     1882        if oEntriesMatch:
     1883            cEntriesPerByte   = 1;
     1884            cValidTableLength = int(oEntriesMatch.group(1));
     1885            asPrefixes        = (None,);
     1886
     1887        #
     1888        # The next line should be '{' and nothing else.
     1889        #
     1890        if self.iLine >= len(self.asLines) or not re.match('^ *{ *$', self.asLines[self.iLine]):
     1891            return self.errorOnLine(self.iLine + 1, 'Expected lone "{" on line following PFNIEMOP table %s start' % (sName, ));
     1892        self.iLine += 1;
     1893
     1894        #
     1895        # Parse till we find the end of the table.
     1896        #
     1897        iEntry = 0;
     1898        while self.iLine < len(self.asLines):
     1899            # Get the next line and strip comments and spaces (assumes no
     1900            # multi-line comments).
     1901            sLine = self.asLines[self.iLine];
     1902            self.iLine += 1;
     1903            sLine = self.stripComments(sLine).strip();
     1904
     1905            # Split the line up into entries, expanding IEMOP_X4 usage.
     1906            asEntries = sLine.split(',');
     1907            for i in range(len(asEntries) - 1, -1, -1):
     1908                sEntry = asEntries[i].strip();
     1909                if sEntry.startswith('IEMOP_X4(') and sEntry[-1] == ')':
     1910                    sEntry = (sEntry[len('IEMOP_X4('):-1]).strip();
     1911                    asEntries.insert(i + 1, sEntry);
     1912                    asEntries.insert(i + 1, sEntry);
     1913                    asEntries.insert(i + 1, sEntry);
     1914                if sEntry:
     1915                    asEntries[i] = sEntry;
     1916                else:
     1917                    del asEntries[i];
     1918
     1919            # Process the entries.
     1920            for sEntry in asEntries:
     1921                if sEntry in ('};', '}'):
     1922                    if iEntry != cValidTableLength:
     1923                        return self.error('Wrong table length for %s: %#x, expected %#x' % (sName, iEntry, cValidTableLength, ));
     1924                    return True;
     1925                if sEntry.startswith('iemOp_Invalid'):
     1926                    pass; # skip
     1927                else:
     1928                    # Look up matching instruction by function.
     1929                    sPrefix = asPrefixes[iEntry % cEntriesPerByte];
     1930                    sOpcode = '%#04x' % (iEntry // cEntriesPerByte);
     1931                    aoInstr  = g_dAllInstructionsByFunction.get(sEntry);
     1932                    if aoInstr:
     1933                        if not isinstance(aoInstr, list):
     1934                            aoInstr = [aoInstr,];
     1935                        oInstr = None;
     1936                        for oCurInstr in aoInstr:
     1937                            if oCurInstr.sOpcode == sOpcode and oCurInstr.sPrefix == sPrefix:
     1938                                pass;
     1939                            elif oCurInstr.sOpcode == sOpcode and oCurInstr.sPrefix is None:
     1940                                oCurInstr.sPrefix = sPrefix;
     1941                            elif oCurInstr.sOpcode is None and oCurInstr.sPrefix is None:
     1942                                oCurInstr.sOpcode = sOpcode;
     1943                                oCurInstr.sPrefix = sPrefix;
     1944                            else:
     1945                                continue;
     1946                            oInstr = oCurInstr;
     1947                            break;
     1948                        if not oInstr:
     1949                            oInstr = aoInstr[0].copy(oMap = oMap, sOpcode = sOpcode, sPrefix = sPrefix);
     1950                            aoInstr.append(oInstr);
     1951                            g_dAllInstructionsByFunction[sEntry] = aoInstr;
     1952                            g_aoAllInstructions.append(oInstr);
     1953                            oMap.aoInstructions.append(oInstr);
     1954                    else:
     1955                        self.debug('Function "%s", entry %#04x / byte %#04x in %s, is not associated with an instruction.'
     1956                                   % (sEntry, iEntry, iEntry // cEntriesPerByte, sName,));
     1957                iEntry += 1;
     1958
     1959        return self.error('Unexpected end of file in PFNIEMOP table');
    17281960
    17291961    def addInstruction(self, iLine = None):
     
    18702102
    18712103        self.sComment     = '';
    1872         self.aoCurInstrs   = [];
     2104        self.aoCurInstrs  = [];
    18732105        return True;
    18742106
     
    25842816                            self.errorComment(iTagLine, '%s: invalid %s field "%s" in "%s"\nvalid fields: %s'
    25852817                                                         % ( sTag, sDesc, sField, sItem,
    2586                                                              ', '.join([sKey for sKey in TestInOut.kdFields
    2587                                                                         if TestInOut.kdFields[sKey][1] in asValidFieldKinds]),));
     2818                                                             ', '.join([sKey for sKey, asVal in TestInOut.kdFields.items()
     2819                                                                        if asVal[1] in asValidFieldKinds]),));
    25882820                        break;
    25892821                    if oItem is not None:
     
    32883520                self.doneInstructions();
    32893521
     3522            # Look for instruction table on the form 'IEM_STATIC const PFNIEMOP g_apfnVexMap3'
     3523            # so we can check/add @oppfx info from it.
     3524            elif self.iState == self.kiCode and sLine.find('PFNIEMOP') > 0 and self.oReFunTable.match(sLine):
     3525                self.parseFunctionTable(sLine);
     3526
    32903527        self.doneInstructions();
    32913528        self.debug('%3s stubs out of %3s instructions in %s'
     
    33023539    #
    33033540    try:
    3304         oFile = open(sSrcFile, "r");
     3541        oFile = open(sSrcFile, "r");    # pylint: disable=consider-using-with
    33053542    except Exception as oXcpt:
    33063543        raise Exception("failed to open %s for reading: %s" % (sSrcFile, oXcpt,));
     
    34003637# Generators (may perhaps move later).
    34013638#
     3639def __formatDisassemblerTableEntry(oInstr):
     3640    """
     3641    """
     3642    sMacro = 'OP';
     3643    cMaxOperands = 3;
     3644    if len(oInstr.aoOperands) > 3:
     3645        sMacro = 'OPVEX'
     3646        cMaxOperands = 4;
     3647        assert len(oInstr.aoOperands) <= cMaxOperands;
     3648
     3649    #
     3650    # Format string.
     3651    #
     3652    sTmp = '%s("%s' % (sMacro, oInstr.sMnemonic,);
     3653    for iOperand, oOperand in enumerate(oInstr.aoOperands):
     3654        sTmp += ' ' if iOperand == 0 else ',';
     3655        if g_kdOpTypes[oOperand.sType][2][0] != '%':        ## @todo remove upper() later.
     3656            sTmp += g_kdOpTypes[oOperand.sType][2].upper(); ## @todo remove upper() later.
     3657        else:
     3658            sTmp += g_kdOpTypes[oOperand.sType][2];
     3659    sTmp += '",';
     3660    asColumns = [ sTmp, ];
     3661
     3662    #
     3663    # Decoders.
     3664    #
     3665    iStart = len(asColumns);
     3666    if oInstr.sEncoding is None:
     3667        pass;
     3668    elif oInstr.sEncoding == 'ModR/M':
     3669        # ASSUME the first operand is using the ModR/M encoding
     3670        assert len(oInstr.aoOperands) >= 1 and oInstr.aoOperands[0].usesModRM();
     3671        asColumns.append('IDX_ParseModRM,');
     3672    elif oInstr.sEncoding in [ 'prefix', ]:
     3673        for oOperand in oInstr.aoOperands:
     3674            asColumns.append('0,');
     3675    elif oInstr.sEncoding in [ 'fixed', 'VEX.fixed' ]:
     3676        pass;
     3677    elif oInstr.sEncoding == 'VEX.ModR/M':
     3678        asColumns.append('IDX_ParseModRM,');
     3679    elif oInstr.sEncoding == 'vex2':
     3680        asColumns.append('IDX_ParseVex2b,')
     3681    elif oInstr.sEncoding == 'vex3':
     3682        asColumns.append('IDX_ParseVex3b,')
     3683    elif oInstr.sEncoding in g_dInstructionMaps:
     3684        asColumns.append(g_dInstructionMaps[oInstr.sEncoding].sDisParse + ',');
     3685    else:
     3686        ## @todo
     3687        #IDX_ParseTwoByteEsc,
     3688        #IDX_ParseGrp1,
     3689        #IDX_ParseShiftGrp2,
     3690        #IDX_ParseGrp3,
     3691        #IDX_ParseGrp4,
     3692        #IDX_ParseGrp5,
     3693        #IDX_Parse3DNow,
     3694        #IDX_ParseGrp6,
     3695        #IDX_ParseGrp7,
     3696        #IDX_ParseGrp8,
     3697        #IDX_ParseGrp9,
     3698        #IDX_ParseGrp10,
     3699        #IDX_ParseGrp12,
     3700        #IDX_ParseGrp13,
     3701        #IDX_ParseGrp14,
     3702        #IDX_ParseGrp15,
     3703        #IDX_ParseGrp16,
     3704        #IDX_ParseThreeByteEsc4,
     3705        #IDX_ParseThreeByteEsc5,
     3706        #IDX_ParseModFence,
     3707        #IDX_ParseEscFP,
     3708        #IDX_ParseNopPause,
     3709        #IDX_ParseInvOpModRM,
     3710        assert False, str(oInstr);
     3711
     3712    # Check for immediates and stuff in the remaining operands.
     3713    for oOperand in oInstr.aoOperands[len(asColumns) - iStart:]:
     3714        sIdx = g_kdOpTypes[oOperand.sType][0];
     3715        #if sIdx != 'IDX_UseModRM':
     3716        asColumns.append(sIdx + ',');
     3717    asColumns.extend(['0,'] * (cMaxOperands - (len(asColumns) - iStart)));
     3718
     3719    #
     3720    # Opcode and operands.
     3721    #
     3722    assert oInstr.sDisEnum, str(oInstr);
     3723    asColumns.append(oInstr.sDisEnum + ',');
     3724    iStart = len(asColumns)
     3725    for oOperand in oInstr.aoOperands:
     3726        asColumns.append('OP_PARM_' + g_kdOpTypes[oOperand.sType][3] + ',');
     3727    asColumns.extend(['OP_PARM_NONE,'] * (cMaxOperands - (len(asColumns) - iStart)));
     3728
     3729    #
     3730    # Flags.
     3731    #
     3732    sTmp = '';
     3733    for sHint in sorted(oInstr.dHints.keys()):
     3734        sDefine = g_kdHints[sHint];
     3735        if sDefine.startswith('DISOPTYPE_'):
     3736            if sTmp:
     3737                sTmp += ' | ' + sDefine;
     3738            else:
     3739                sTmp += sDefine;
     3740    if sTmp:
     3741        sTmp += '),';
     3742    else:
     3743        sTmp += '0),';
     3744    asColumns.append(sTmp);
     3745
     3746    #
     3747    # Format the columns into a line.
     3748    #
     3749    aoffColumns = [4, 29, 49, 65, 77, 89, 109, 125, 141, 157, 183, 199];
     3750    sLine = '';
     3751    for i, s in enumerate(asColumns):
     3752        if len(sLine) < aoffColumns[i]:
     3753            sLine += ' ' * (aoffColumns[i] - len(sLine));
     3754        else:
     3755            sLine += ' ';
     3756        sLine += s;
     3757
     3758    # OP("psrlw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE,
     3759    # DISOPTYPE_HARMLESS),
     3760    # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
     3761    # { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype }
     3762    return sLine;
     3763
     3764def __checkIfShortTable(aoTableOrdered, oMap):
     3765    """
     3766    Returns (iInstr, cInstructions, fShortTable)
     3767    """
     3768
     3769    # Determin how much we can trim off.
     3770    cInstructions = len(aoTableOrdered);
     3771    while cInstructions > 0 and aoTableOrdered[cInstructions - 1] is None:
     3772        cInstructions -= 1;
     3773
     3774    iInstr = 0;
     3775    while iInstr < cInstructions and aoTableOrdered[iInstr] is None:
     3776        iInstr += 1;
     3777
     3778    # If we can save more than 30%, we go for the short table version.
     3779    if iInstr + len(aoTableOrdered) - cInstructions >= len(aoTableOrdered) // 30:
     3780        return (iInstr, cInstructions, True);
     3781    _ = oMap; # Use this for overriding.
     3782
     3783    # Output the full table.
     3784    return (0, len(aoTableOrdered), False);
     3785
    34023786def generateDisassemblerTables(oDstFile = sys.stdout):
    34033787    """
     
    34053789    """
    34063790
     3791    #
     3792    # The disassembler uses a slightly different table layout to save space,
     3793    # since several of the prefix varia
     3794    #
     3795    aoDisasmMaps = [];
    34073796    for sName, oMap in sorted(iter(g_dInstructionMaps.items()),
    34083797                              key = lambda aKV: aKV[1].sEncoding + ''.join(aKV[1].asLeadOpcodes)):
    3409         assert oMap.sName == sName;
     3798        if oMap.sSelector != 'byte+pfx':
     3799            aoDisasmMaps.append(oMap);
     3800        else:
     3801            # Split the map by prefix.
     3802            aoDisasmMaps.append(oMap.copy(oMap.sName,         'none'));
     3803            aoDisasmMaps.append(oMap.copy(oMap.sName + '_66', '0x66'));
     3804            aoDisasmMaps.append(oMap.copy(oMap.sName + '_F3', '0xf3'));
     3805            aoDisasmMaps.append(oMap.copy(oMap.sName + '_F2', '0xf2'));
     3806
     3807    #
     3808    # Dump each map.
     3809    #
     3810    asHeaderLines = [];
     3811    print("debug: maps=%s\n" % (', '.join([oMap.sName for oMap in aoDisasmMaps]),));
     3812    for oMap in aoDisasmMaps:
     3813        sName = oMap.sName;
     3814
     3815        if not sName.startswith("vex"): continue; # only looking at the vex maps at the moment.
     3816
     3817        #
     3818        # Get the instructions for the map and see if we can do a short version or not.
     3819        #
     3820        aoTableOrder    = oMap.getInstructionsInTableOrder();
     3821        cEntriesPerByte = oMap.getEntriesPerByte();
     3822        (iInstrStart, iInstrEnd, fShortTable) = __checkIfShortTable(aoTableOrder, oMap);
     3823
     3824        #
     3825        # Output the table start.
     3826        # Note! Short tables are static and only accessible via the map range record.
     3827        #
    34103828        asLines = [];
    3411 
    34123829        asLines.append('/* Generated from: %-11s  Selector: %-7s  Encoding: %-7s  Lead bytes opcodes: %s */'
    34133830                       % ( oMap.sName, oMap.sSelector, oMap.sEncoding, ' '.join(oMap.asLeadOpcodes), ));
    3414         asLines.append('const DISOPCODE %s[] =' % (oMap.getDisasTableName(),));
     3831        if fShortTable:
     3832            asLines.append('%sconst DISOPCODE %s[] =' % ('static ' if fShortTable else '', oMap.getDisasTableName(),));
     3833        else:
     3834            asHeaderLines.append('extern const DISOPCODE %s[%d];'  % (oMap.getDisasTableName(), iInstrEnd - iInstrStart,));
     3835            asLines.append(             'const DISOPCODE %s[%d] =' % (oMap.getDisasTableName(), iInstrEnd - iInstrStart,));
    34153836        asLines.append('{');
    34163837
    3417         aoffColumns = [4, 29, 49, 65, 77, 89, 109, 125, 141, 157, 183, 199];
    3418 
    3419         aoTableOrder = oMap.getInstructionsInTableOrder();
    3420         for iInstr, oInstr in enumerate(aoTableOrder):
    3421 
    3422             if (iInstr & 0xf) == 0:
    3423                 if iInstr != 0:
     3838        if fShortTable and (iInstrStart & ((0x10 * cEntriesPerByte) - 1)) != 0:
     3839            asLines.append('    /* %#04x: */' % (iInstrStart,));
     3840
     3841        #
     3842        # Output the instructions.
     3843        #
     3844        iInstr = iInstrStart;
     3845        while iInstr < iInstrEnd:
     3846            oInstr = aoTableOrder[iInstr];
     3847            if (iInstr & ((0x10 * cEntriesPerByte) - 1)) == 0:
     3848                if iInstr != iInstrStart:
    34243849                    asLines.append('');
    3425                 asLines.append('    /* %x */' % (iInstr >> 4,));
     3850                asLines.append('    /* %x */' % ((iInstr // cEntriesPerByte) >> 4,));
    34263851
    34273852            if oInstr is None:
    3428                 pass;#asLines.append('    /* %#04x */ None,' % (iInstr));
     3853                # Invalid. Optimize blocks of invalid instructions.
     3854                cInvalidInstrs = 1;
     3855                while iInstr + cInvalidInstrs < len(aoTableOrder) and aoTableOrder[iInstr + cInvalidInstrs] is None:
     3856                    cInvalidInstrs += 1;
     3857                if (iInstr & (0x10 * cEntriesPerByte - 1)) == 0 and cInvalidInstrs >= 0x10 * cEntriesPerByte:
     3858                    asLines.append('    INVALID_OPCODE_BLOCK_%u,' % (0x10 * cEntriesPerByte,));
     3859                    iInstr += 0x10 * cEntriesPerByte - 1;
     3860                elif cEntriesPerByte > 1:
     3861                    if (iInstr & (cEntriesPerByte - 1)) == 0 and cInvalidInstrs >= cEntriesPerByte:
     3862                        asLines.append('    INVALID_OPCODE_BLOCK_%u,' % (cEntriesPerByte,));
     3863                        iInstr += 3;
     3864                    else:
     3865                        asLines.append('    /* %#04x/%d */ INVALID_OPCODE,'
     3866                                       % (iInstr // cEntriesPerByte, iInstr % cEntriesPerByte));
     3867                else:
     3868                    asLines.append('    /* %#04x */ INVALID_OPCODE,' % (iInstr));
    34293869            elif isinstance(oInstr, list):
    3430                 asLines.append('    /* %#04x */ ComplicatedListStuffNeedingWrapper,' % (iInstr));
     3870                if len(oInstr) != 0:
     3871                    asLines.append('    /* %#04x */ ComplicatedListStuffNeedingWrapper, /* \n -- %s */'
     3872                                   % (iInstr, '\n -- '.join([str(oItem) for oItem in oInstr]),));
     3873                else:
     3874                    asLines.append(__formatDisassemblerTableEntry(oInstr));
    34313875            else:
    3432                 sMacro = 'OP';
    3433                 cMaxOperands = 3;
    3434                 if len(oInstr.aoOperands) > 3:
    3435                     sMacro = 'OPVEX'
    3436                     cMaxOperands = 4;
    3437                     assert len(oInstr.aoOperands) <= cMaxOperands;
    3438 
    3439                 #
    3440                 # Format string.
    3441                 #
    3442                 sTmp = '%s("%s' % (sMacro, oInstr.sMnemonic,);
    3443                 for iOperand, oOperand in enumerate(oInstr.aoOperands):
    3444                     sTmp += ' ' if iOperand == 0 else ',';
    3445                     if g_kdOpTypes[oOperand.sType][2][0] != '%':        ## @todo remove upper() later.
    3446                         sTmp += g_kdOpTypes[oOperand.sType][2].upper(); ## @todo remove upper() later.
    3447                     else:
    3448                         sTmp += g_kdOpTypes[oOperand.sType][2];
    3449                 sTmp += '",';
    3450                 asColumns = [ sTmp, ];
    3451 
    3452                 #
    3453                 # Decoders.
    3454                 #
    3455                 iStart = len(asColumns);
    3456                 if oInstr.sEncoding is None:
    3457                     pass;
    3458                 elif oInstr.sEncoding == 'ModR/M':
    3459                     # ASSUME the first operand is using the ModR/M encoding
    3460                     assert len(oInstr.aoOperands) >= 1 and oInstr.aoOperands[0].usesModRM();
    3461                     asColumns.append('IDX_ParseModRM,');
    3462                     ## @todo IDX_ParseVexDest
    3463                     # Is second operand using ModR/M too?
    3464                     if len(oInstr.aoOperands) > 1 and oInstr.aoOperands[1].usesModRM():
    3465                         asColumns.append('IDX_UseModRM,')
    3466                 elif oInstr.sEncoding in [ 'prefix', ]:
    3467                     for oOperand in oInstr.aoOperands:
    3468                         asColumns.append('0,');
    3469                 elif oInstr.sEncoding in [ 'fixed' ]:
    3470                     pass;
    3471                 elif oInstr.sEncoding == 'vex2':
    3472                     asColumns.append('IDX_ParseVex2b,')
    3473                 elif oInstr.sEncoding == 'vex3':
    3474                     asColumns.append('IDX_ParseVex3b,')
    3475                 elif oInstr.sEncoding in g_dInstructionMaps:
    3476                     asColumns.append(g_dInstructionMaps[oInstr.sEncoding].sDisParse + ',');
    3477                 else:
    3478                     ## @todo
    3479                     #IDX_ParseTwoByteEsc,
    3480                     #IDX_ParseGrp1,
    3481                     #IDX_ParseShiftGrp2,
    3482                     #IDX_ParseGrp3,
    3483                     #IDX_ParseGrp4,
    3484                     #IDX_ParseGrp5,
    3485                     #IDX_Parse3DNow,
    3486                     #IDX_ParseGrp6,
    3487                     #IDX_ParseGrp7,
    3488                     #IDX_ParseGrp8,
    3489                     #IDX_ParseGrp9,
    3490                     #IDX_ParseGrp10,
    3491                     #IDX_ParseGrp12,
    3492                     #IDX_ParseGrp13,
    3493                     #IDX_ParseGrp14,
    3494                     #IDX_ParseGrp15,
    3495                     #IDX_ParseGrp16,
    3496                     #IDX_ParseThreeByteEsc4,
    3497                     #IDX_ParseThreeByteEsc5,
    3498                     #IDX_ParseModFence,
    3499                     #IDX_ParseEscFP,
    3500                     #IDX_ParseNopPause,
    3501                     #IDX_ParseInvOpModRM,
    3502                     assert False, str(oInstr);
    3503 
    3504                 # Check for immediates and stuff in the remaining operands.
    3505                 for oOperand in oInstr.aoOperands[len(asColumns) - iStart:]:
    3506                     sIdx = g_kdOpTypes[oOperand.sType][0];
    3507                     if sIdx != 'IDX_UseModRM':
    3508                         asColumns.append(sIdx + ',');
    3509                 asColumns.extend(['0,'] * (cMaxOperands - (len(asColumns) - iStart)));
    3510 
    3511                 #
    3512                 # Opcode and operands.
    3513                 #
    3514                 assert oInstr.sDisEnum, str(oInstr);
    3515                 asColumns.append(oInstr.sDisEnum + ',');
    3516                 iStart = len(asColumns)
    3517                 for oOperand in oInstr.aoOperands:
    3518                     asColumns.append('OP_PARM_' + g_kdOpTypes[oOperand.sType][3] + ',');
    3519                 asColumns.extend(['OP_PARM_NONE,'] * (cMaxOperands - (len(asColumns) - iStart)));
    3520 
    3521                 #
    3522                 # Flags.
    3523                 #
    3524                 sTmp = '';
    3525                 for sHint in sorted(oInstr.dHints.keys()):
    3526                     sDefine = g_kdHints[sHint];
    3527                     if sDefine.startswith('DISOPTYPE_'):
    3528                         if sTmp:
    3529                             sTmp += ' | ' + sDefine;
    3530                         else:
    3531                             sTmp += sDefine;
    3532                 if sTmp:
    3533                     sTmp += '),';
    3534                 else:
    3535                     sTmp += '0),';
    3536                 asColumns.append(sTmp);
    3537 
    3538                 #
    3539                 # Format the columns into a line.
    3540                 #
    3541                 sLine = '';
    3542                 for i, s in enumerate(asColumns):
    3543                     if len(sLine) < aoffColumns[i]:
    3544                         sLine += ' ' * (aoffColumns[i] - len(sLine));
    3545                     else:
    3546                         sLine += ' ';
    3547                     sLine += s;
    3548 
    3549                 # OP("psrlw %Vdq,%Wdq", IDX_ParseModRM, IDX_UseModRM, 0, OP_PSRLW, OP_PARM_Vdq, OP_PARM_Wdq, OP_PARM_NONE,
    3550                 # DISOPTYPE_HARMLESS),
    3551                 # define OP(pszOpcode, idxParse1, idxParse2, idxParse3, opcode, param1, param2, param3, optype) \
    3552                 # { pszOpcode, idxParse1, idxParse2, idxParse3, 0, opcode, param1, param2, param3, 0, 0, optype }
    3553 
    3554                 asLines.append(sLine);
     3876                asLines.append(__formatDisassemblerTableEntry(oInstr));
     3877
     3878            iInstr += 1;
     3879
     3880        if iInstrStart >= iInstrEnd:
     3881            asLines.append('    /* dummy */ INVALID_OPCODE');
    35553882
    35563883        asLines.append('};');
    3557         asLines.append('AssertCompile(RT_ELEMENTS(%s) == %s);' % (oMap.getDisasTableName(), oMap.getTableSize(),));
     3884        asLines.append('AssertCompile(RT_ELEMENTS(%s) == %s);' % (oMap.getDisasTableName(), iInstrEnd - iInstrStart,));
     3885
     3886        #
     3887        # We always emit a map range record, assuming the linker will eliminate the unnecessary ones.
     3888        #
     3889        asHeaderLines.append('extern const DISOPMAPDESC %sRange;'  % (oMap.getDisasRangeName()));
     3890        asLines.append('const DISOPMAPDESC %s = { &%s[0], %#04x, RT_ELEMENTS(%s) };'
     3891                       % (oMap.getDisasRangeName(), oMap.getDisasTableName(), iInstrStart, oMap.getDisasTableName(),));
    35583892
    35593893        #
     
    35623896        oDstFile.write('\n'.join(asLines));
    35633897        oDstFile.write('\n');
    3564         break; #for now
     3898        oDstFile.write('\n');
     3899        #break; #for now
    35653900
    35663901if __name__ == '__main__':
Note: See TracChangeset for help on using the changeset viewer.

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