VirtualBox

Changeset 65524 in vbox for trunk


Ignore:
Timestamp:
Jan 30, 2017 6:35:49 PM (8 years ago)
Author:
vboxsync
Message:

bs3-cpu-decoding-1: Working on testing undefined areas since these may include ModR/M and immediate decoding as well as unused 3-byte escapes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-decoding-1.c32

    r62410 r65524  
    3232#include <iprt/asm-amd64-x86.h>
    3333
     34
     35/*********************************************************************************************************************************
     36*   Structures and Typedefs                                                                                                      *
     37*********************************************************************************************************************************/
    3438/**
    3539 * Simple test.
     
    3741typedef struct CPUDECODE1TST
    3842{
    39     uint8_t fFlags;
    40     uint8_t cbUd;
    41     uint8_t cbOpcodes;
    42     uint8_t abOpcodes[21];
     43    uint16_t fFlags;
     44    uint8_t  cbOpcodes;
     45    uint8_t  abOpcodes[20];
     46    uint8_t  cbUd;
    4347} CPUDECODE1TST;
    4448typedef CPUDECODE1TST BS3_FAR *PCPUDECODE1TST;
     
    5660#define P_RN  X86_OP_PRF_REPNZ
    5761
    58 #define RM_EAX_EAX          ((3 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xAX))
    59 #define RM_EAX_DEREF_EBX    ((0 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xBX))
    60 
    61 #define F_486   0
    62 #define F_SSE2  1
    63 #define F_SSE3  2
    64 #define F_SSE42 4
    65 #define F_MOVBE 80
    66 
     62#define RM_EAX_EAX              ((3 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xAX))
     63#define RM_EAX_DEREF_EBX        ((0 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xBX))
     64#define RM_EAX_DEREF_EBX_DISP8  ((1 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xBX))
     65#define RM_EAX_DEREF_EBX_DISP32 ((2 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | (X86_GREG_xBX))
     66#define RM_EAX_SIB              ((0 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | 4)
     67#define RM_EAX_SIB_DISP8        ((1 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | 4)
     68#define RM_EAX_SIB_DISP32       ((2 << X86_MODRM_MOD_SHIFT) | (X86_GREG_xAX <<  X86_MODRM_REG_SHIFT) | 4)
     69
     70#define SIB_EBX_X1_NONE         ((0 << X86_SIB_SCALE_SHIFT) | (4            <<  X86_SIB_INDEX_SHIFT) | (X86_GREG_xBX))
     71#define SIB_EBX_X2_NONE         ((1 << X86_SIB_SCALE_SHIFT) | (4            <<  X86_SIB_INDEX_SHIFT) | (X86_GREG_xBX))
     72#define SIB_EBX_X4_NONE         ((2 << X86_SIB_SCALE_SHIFT) | (4            <<  X86_SIB_INDEX_SHIFT) | (X86_GREG_xBX))
     73#define SIB_EBX_X8_NONE         ((3 << X86_SIB_SCALE_SHIFT) | (4            <<  X86_SIB_INDEX_SHIFT) | (X86_GREG_xBX))
     74
     75#define F_486   UINT16_C(0x0000)
     76#define F_SSE2  UINT16_C(0x0001)
     77#define F_SSE3  UINT16_C(0x0002)
     78#define F_SSE42 UINT16_C(0x0004)
     79#define F_MOVBE UINT16_C(0x0080)
     80#define F_CBUD  UINT16_C(0x4000)
     81#define F_UD    UINT16_C(0x8000)
     82#define F_OK    UINT16_C(0x0000)
     83
     84
     85/**
     86 * This is an exploratory testcase.  It tries to figure out how exactly the
     87 * different Intel and AMD CPUs implements SSE and similar instructions that
     88 * uses the size, repz, repnz and lock prefixes in the encoding.
     89 */
    6790CPUDECODE1TST const g_aSimpleTests[] =
    6891{
     
    7093     *  fFlags, cbUd, cbOpcodes, abOpcodes
    7194     */
     95#if 0
     96    /* Using currently undefined 0x0f 0x7a sequences. */
     97    {           F_UD, 3,               { 0x0f, 0x7a, RM_EAX_EAX, } },
     98    {           F_UD, 3+1,       { P_LK, 0x0f, 0x7a, RM_EAX_EAX, } },
     99    {           F_UD, 3+1,       { P_RN, 0x0f, 0x7a, RM_EAX_EAX, } },
     100    {           F_UD, 3+1,       { P_RZ, 0x0f, 0x7a, RM_EAX_EAX, } },
     101    {           F_UD, 3+2, { P_LK, P_LK, 0x0f, 0x7a, RM_EAX_EAX, } },
     102    {           F_UD, 4,               { 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP8, 0 } },
     103    {           F_UD, 4+1,       { P_LK, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP8, 0 } },
     104    {           F_UD, 4+1,       { P_RN, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP8, 0 } },
     105    {           F_UD, 4+1,       { P_RZ, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP8, 0 } },
     106    {           F_UD, 4+2, { P_LK, P_LK, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP8, 0 } },
     107    {           F_UD, 7,               { 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 } },
     108    {           F_UD, 7+1,       { P_LK, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 } },
     109    {           F_UD, 7+1,       { P_RN, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 } },
     110    {           F_UD, 7+1,       { P_RZ, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 } },
     111    {           F_UD, 7+2, { P_LK, P_LK, 0x0f, 0x7a, RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 } },
     112#endif
     113#if 0
     114    /* Ditto for currently undefined sequence: 0x0f 0x7b */
     115    {           F_UD, 3,               { 0x0f, 0x7b, RM_EAX_EAX, } },
     116    {           F_UD, 3+1,       { P_LK, 0x0f, 0x7b, RM_EAX_EAX, } },
     117    {           F_UD, 3+1,       { P_RN, 0x0f, 0x7b, RM_EAX_EAX, } },
     118    {           F_UD, 3+1,       { P_RZ, 0x0f, 0x7b, RM_EAX_EAX, } },
     119    {           F_UD, 3+2, { P_LK, P_LK, 0x0f, 0x7b, RM_EAX_EAX, } },
     120#endif
    72121#if 1
    73     /* Using currently undefined 0x0f 0x7a sequences. */
    74     {        0, 3,   3,               { 0x0f, 0x7a, RM_EAX_EAX, } },
    75     {        0, 3+1, 3+1,       { P_LK, 0x0f, 0x7a, RM_EAX_EAX, } },
    76     {        0, 3+1, 3+1,       { P_RN, 0x0f, 0x7a, RM_EAX_EAX, } },
    77     {        0, 3+1, 3+1,       { P_RZ, 0x0f, 0x7a, RM_EAX_EAX, } },
    78     {        0, 3+2, 3+2, { P_LK, P_LK, 0x0f, 0x7a, RM_EAX_EAX, } },
     122    /* Ditto for currently undefined sequence: 0x0f 0x24 */
     123    {           F_UD, 3,               { 0x0f, 0x24, RM_EAX_EAX, } },
     124    {           F_UD, 3+1,       { P_LK, 0x0f, 0x24, RM_EAX_EAX, } },
     125    {           F_UD, 3+1,       { P_RN, 0x0f, 0x24, RM_EAX_EAX, } },
     126    {           F_UD, 3+1,       { P_RZ, 0x0f, 0x24, RM_EAX_EAX, } },
     127    {           F_UD, 3+2, { P_LK, P_LK, 0x0f, 0x24, RM_EAX_EAX, } },
    79128#endif
    80129#if 0
    81130    /* The XADD instruction has empty lines for 66, f3 and f2 prefixes.
    82131       AMD doesn't do anything special for XADD Ev,Gv as the intel table would indicate. */
    83     {    F_486,   99,  3,             { 0x0f, 0xc1, RM_EAX_EAX, } },
    84     {    F_486,   99,  4,       { P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
    85     {    F_486,   99,  4,       { P_RN, 0x0f, 0xc1, RM_EAX_EAX, } },
    86     {    F_486,   99,  5, { P_OZ, P_RN, 0x0f, 0xc1, RM_EAX_EAX, } },
    87     {    F_486,   99,  5, { P_RN, P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
    88     {    F_486,   99,  4,       { P_RZ, 0x0f, 0xc1, RM_EAX_EAX, } },
    89     {    F_486,   99,  5, { P_OZ, P_RZ, 0x0f, 0xc1, RM_EAX_EAX, } },
    90     {    F_486,   99,  5, { P_RZ, P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
     132    {    F_486 | F_OK,  3,             { 0x0f, 0xc1, RM_EAX_EAX, } },
     133    {    F_486 | F_OK,  4,       { P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
     134    {    F_486 | F_OK,  4,       { P_RN, 0x0f, 0xc1, RM_EAX_EAX, } },
     135    {    F_486 | F_OK,  5, { P_OZ, P_RN, 0x0f, 0xc1, RM_EAX_EAX, } },
     136    {    F_486 | F_OK,  5, { P_RN, P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
     137    {    F_486 | F_OK,  4,       { P_RZ, 0x0f, 0xc1, RM_EAX_EAX, } },
     138    {    F_486 | F_OK,  5, { P_OZ, P_RZ, 0x0f, 0xc1, RM_EAX_EAX, } },
     139    {    F_486 | F_OK,  5, { P_RZ, P_OZ, 0x0f, 0xc1, RM_EAX_EAX, } },
    91140#endif
    92141#if 0
    93142    /* The movnti instruction is confined to the unprefixed lined in the intel manuals. Check how the other lines work. */
    94     {   F_SSE2,    3,  3,             { 0x0f, 0xc3, RM_EAX_EAX, } },        /* invalid - reg,reg */
    95     {   F_SSE2,   99,  3,             { 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },
    96     {   F_SSE2,    4,  4,       { P_OZ, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
    97     {   F_SSE2,    4,  4,       { P_RN, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
    98     {   F_SSE2,    4,  4,       { P_RZ, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
    99     {   F_SSE2,    4,  4,       { P_LK, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
    100     {   F_SSE2,    5,  5, { P_RZ, P_LK, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
    101 #endif
    102 #if 1
     143    {   F_SSE2 | F_UD,  3,             { 0x0f, 0xc3, RM_EAX_EAX, } },        /* invalid - reg,reg */
     144    {   F_SSE2 | F_OK,  3,             { 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },
     145    {   F_SSE2 | F_UD,  4,       { P_OZ, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
     146    {   F_SSE2 | F_UD,  4,       { P_RN, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
     147    {   F_SSE2 | F_UD,  4,       { P_RZ, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
     148    {   F_SSE2 | F_UD,  4,       { P_LK, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
     149    {   F_SSE2 | F_UD,  5, { P_RZ, P_LK, 0x0f, 0xc3, RM_EAX_DEREF_EBX, } },  /* invalid */
     150#endif
     151#if 0
    103152    /* The lddqu instruction requires a 0xf2 prefix, intel only lists 0x66 and empty
    104153       prefix for it.  Check what they really mean by that*/
    105     {   F_SSE3,    4,  4,            { P_RZ, 0x0f, 0xf0, RM_EAX_EAX, } },          /* invalid - reg, reg  */
    106     {   F_SSE3,   99,  4,            { P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    107     {   F_SSE3,   99,  5,      { P_RZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    108     {   F_SSE3,    3,  3,      {             0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    109     {   F_SSE3,    4,  4,      {       P_RN, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    110     {   F_SSE3,    4,  4,      {       P_OZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    111     {   F_SSE3,    4,  4,      {       P_LK, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    112     {   F_SSE3,    5,  5,      { P_RZ, P_RN, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    113     {   F_SSE3,   99,  5,      { P_RZ, P_OZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } }, // AMD,why?
    114     {   F_SSE3,    5,  5,      { P_RZ, P_LK, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    115     {   F_SSE3,   99,  5,      { P_RN, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    116     {   F_SSE3,   99,  5,      { P_OZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    117     {   F_SSE3,    5,  5,      { P_LK, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    118     {   F_SSE3,   99,  5,      { P_OZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    119     {   F_SSE3,   99,  6,{ P_OZ, P_RN, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
    120 #endif
    121     {   F_SSE2,   99,  3,            { 0x0f, 0x7e, RM_EAX_EAX, } },
    122     {   F_SSE2,   99,  4,      { P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } },
    123     {   F_SSE2,    5,  5,{ P_RZ, P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } }, // WTF?
    124     {   F_SSE2,    5,  5,{ P_OZ, P_RZ, 0x0f, 0x7e, RM_EAX_EAX, } },
    125     {   F_SSE2,   99,  5,{ P_RN, P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } },
    126     {   F_SSE2,   99,  4,      { P_RN, 0x0f, 0x7e, RM_EAX_EAX, } },
    127     {   F_SSE2,    4,  4,      { P_RZ, 0x0f, 0x7e, RM_EAX_EAX, } },
     154    {   F_SSE3 | F_UD,  4,            { P_RZ, 0x0f, 0xf0, RM_EAX_EAX, } },          /* invalid - reg, reg  */
     155    {   F_SSE3 | F_OK,  4,            { P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     156    {   F_SSE3 | F_OK,  5,      { P_RZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     157    {   F_SSE3 | F_UD,  3,      {             0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     158    {   F_SSE3 | F_UD,  4,      {       P_RN, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     159    {   F_SSE3 | F_UD,  4,      {       P_OZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     160    {   F_SSE3 | F_UD,  4,      {       P_LK, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     161    {   F_SSE3 | F_UD,  5,      { P_RZ, P_RN, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     162    {   F_SSE3 | F_OK,  5,      { P_RZ, P_OZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } }, // AMD,why?
     163    {   F_SSE3 | F_UD,  5,      { P_RZ, P_LK, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     164    {   F_SSE3 | F_OK,  5,      { P_RN, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     165    {   F_SSE3 | F_OK,  5,      { P_OZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     166    {   F_SSE3 | F_UD,  5,      { P_LK, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     167    {   F_SSE3 | F_OK,  5,      { P_OZ, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     168    {   F_SSE3 | F_OK,  6,{ P_OZ, P_RN, P_RZ, 0x0f, 0xf0, RM_EAX_DEREF_EBX, } },
     169#endif
     170#if 0
     171    {   F_SSE2 | F_OK,  3,            { 0x0f, 0x7e, RM_EAX_EAX, } },
     172    {   F_SSE2 | F_OK,  4,      { P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } },
     173    {   F_SSE2 | F_UD,  5,{ P_RZ, P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } }, // WTF?
     174    {   F_SSE2 | F_UD,  5,{ P_OZ, P_RZ, 0x0f, 0x7e, RM_EAX_EAX, } },
     175    {   F_SSE2 | F_OK,  5,{ P_RN, P_OZ, 0x0f, 0x7e, RM_EAX_EAX, } },
     176    {   F_SSE2 | F_OK,  4,      { P_RN, 0x0f, 0x7e, RM_EAX_EAX, } },
     177    {   F_SSE2 | F_UD,  4,      { P_RZ, 0x0f, 0x7e, RM_EAX_EAX, } },
     178#endif
    128179/** @todo crc32 / movbe  */
    129180};
     
    153204        for (i = 0; i < RT_ELEMENTS(g_aSimpleTests); i++)
    154205        {
    155             unsigned cb = g_aSimpleTests[i].cbOpcodes;
     206            unsigned const cbOpcodes = g_aSimpleTests[i].cbOpcodes;
     207            uint16_t const fFlags    = g_aSimpleTests[i].fFlags;
     208            unsigned cb;
     209            /** @todo check if supported. */
     210
     211            /*
     212             * Place the instruction exactly at the page boundrary and proceed to
     213             * move it across it and check that we get #PFs then.
     214             */
     215            cb = cbOpcodes;
    156216            while (cb >= 1)
    157217            {
     
    161221                Bs3RegCtxSetRipCsFromFlat(&Ctx, (uintptr_t)pbRip);
    162222                Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
    163 #if 0
    164                 Bs3TestPrintf("\ni=%d cb=%#x (cbUd=%#x cbOpcodes=%#x)\n", i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes);
    165                 Bs3TrapPrintFrame(&TrapFrame);
    166 #endif
    167                 if (cb >= g_aSimpleTests[i].cbUd)
     223#if 1
     224                Bs3TestPrintf("\ni=%d cb=%#x (cbOpcodes=%#x fFlags=%#x)\n", i, cb, cbOpcodes, fFlags);
     225//                Bs3TrapPrintFrame(&TrapFrame);
     226#endif
     227                if (cb >= cbOpcodes && (g_aSimpleTests[i].fFlags & F_UD))
    168228                {
    169229                    if (TrapFrame.bXcpt != X86_XCPT_UD)
    170                         Bs3TestFailedF("i=%d cb=%d cbUd=%d cbOp=%d: expected #UD got %#x at %RX32\n",
    171                                        i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes,
    172                                        TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
     230                        Bs3TestFailedF("i=%d cb=%d cbOp=%d fFlags=%#x: expected #UD got %#x at %RX32\n",
     231                                       i, cb, cbOpcodes, fFlags, TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
    173232                }
    174                 else if (cb < g_aSimpleTests[i].cbOpcodes)
     233                else if (cb < cbOpcodes)
    175234                {
    176235                    if (TrapFrame.bXcpt != X86_XCPT_PF)
    177                         Bs3TestFailedF("i=%d cb=%d cbUd=%d cbOp=%d: expected #PF (on) got %#x at %RX32\n",
    178                                        i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes,
    179                                        TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
     236                        Bs3TestFailedF("i=%d cb=%d cbOp=%d fFlags=%#x: expected #PF (on) got %#x at %RX32\n",
     237                                       i, cb, cbOpcodes, fFlags, TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
    180238                    else if (TrapFrame.Ctx.rip.u32 != (uintptr_t)pbRip)
    181                         Bs3TestFailedF("i=%d cb=%d cbUd=%d cbOp=%d: expected #PF rip of %p (on) got %#RX32\n",
    182                                        i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes,
    183                                        pbRip, TrapFrame.Ctx.rip.u32);
     239                        Bs3TestFailedF("i=%d cb=%d cbOp=%d fFlags=%#x: expected #PF rip of %p (on) got %#RX32\n",
     240                                       i, cb, cbOpcodes, fFlags, pbRip, TrapFrame.Ctx.rip.u32);
    184241                }
    185242                else
    186243                {
    187244                    if (TrapFrame.bXcpt != X86_XCPT_PF)
    188                         Bs3TestFailedF("i=%d cb=%d cbUd=%d cbOp=%d: expected #PF (after) got %#x at %RX32\n",
    189                                        i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes,
    190                                        TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
     245                        Bs3TestFailedF("i=%d cb=%d cbOp=%d fFlags=%#x: expected #PF (after) got %#x at %RX32\n",
     246                                       i, cb, cbOpcodes, fFlags, TrapFrame.bXcpt, TrapFrame.Ctx.rip.u32);
    191247                    else if (TrapFrame.Ctx.rip.u32 != (uintptr_t)&pbPages[X86_PAGE_SIZE])
    192                         Bs3TestFailedF("i=%d cb=%d cbUd=%d cbOp=%d: expected #PF rip of %p (after) got %#RX32\n",
    193                                        i, cb, g_aSimpleTests[i].cbUd, g_aSimpleTests[i].cbOpcodes,
    194                                        &pbPages[X86_PAGE_SIZE], TrapFrame.Ctx.rip.u32);
     248                        Bs3TestFailedF("i=%d cb=%d cbOp=%d fFlags=%#x: expected #PF rip of %p (after) got %#RX32\n",
     249                                       i, cb, cbOpcodes, fFlags, &pbPages[X86_PAGE_SIZE], TrapFrame.Ctx.rip.u32);
    195250                }
    196251                if (Bs3TestSubErrorCount() != cErrorsBefore)
    197252                {
    198253                    Bs3TestPrintf("  %.*Rhxs", cb, &g_aSimpleTests[i].abOpcodes[0]);
    199                     if (cb < g_aSimpleTests[i].cbOpcodes)
    200                         Bs3TestPrintf("[%.*Rhxs]", g_aSimpleTests[i].cbOpcodes - cb, &g_aSimpleTests[i].abOpcodes[cb]);
     254                    if (cb < cbOpcodes)
     255                        Bs3TestPrintf("[%.*Rhxs]", cbOpcodes - cb, &g_aSimpleTests[i].abOpcodes[cb]);
    201256                    Bs3TestPrintf("\n");
    202257                }
     
    220275
    221276
     277/**
     278 * Undefined opcode test.
     279 */
     280typedef struct CPUDECODE1UDTST
     281{
     282    /** Type of undefined opcode decoding logic - UD_T_XXX. */
     283    uint8_t     enmType;
     284    /** Core opcodes length. */
     285    uint8_t     cbOpcodes;
     286    /** Core opcodes. */
     287    uint8_t     abOpcodes[5];
     288    /** UD_F_XXX. */
     289    uint8_t     fFlags;
     290} CPUDECODE1UDTST;
     291typedef CPUDECODE1UDTST const BS3_FAR *PCCPUDECODE1UDTST;
     292
     293#define UD_T_EXACT          0
     294#define UD_T_MODRM          1
     295#define UD_T_MODRM_IMM8     2
     296
     297#define UD_F_ANY_PFX 0
     298#define UD_F_NOT_NO_PFX     UINT8_C(0x01)  /**< Must have some kind of prefix to be \#UD. */
     299#define UD_F_NOT_OZ_PFX     UINT8_C(0x02)  /**< Skip the size prefix. */
     300#define UD_F_NOT_RZ_PFX     UINT8_C(0x04)  /**< Skip the REPZ prefix. */
     301#define UD_F_NOT_RN_PFX     UINT8_C(0x08)  /**< Skip the REPNZ prefix. */
     302#define UD_F_NOT_LK_PFX     UINT8_C(0x10)  /**< Skip the LOCK prefix. */
     303#define UD_F_3BYTE_ESC      UINT8_C(0x20)  /**< Unused 3 byte escape table. Test all 256 entries */
     304
     305CPUDECODE1UDTST const g_aUdTest[] =
     306{
     307    /* Two byte opcodes. */
     308#if 1
     309    {  UD_T_EXACT, 2, { 0x0f, 0x04 }, UD_F_ANY_PFX },
     310    {  UD_T_EXACT, 2, { 0x0f, 0x0a }, UD_F_ANY_PFX },
     311    {  UD_T_EXACT, 2, { 0x0f, 0x0c }, UD_F_ANY_PFX },
     312    {  UD_T_EXACT, 2, { 0x0f, 0x0e }, UD_F_ANY_PFX },
     313    {  UD_T_EXACT, 2, { 0x0f, 0x0f }, UD_F_ANY_PFX },
     314    {  UD_T_MODRM, 2, { 0x0f, 0x13 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     315    {  UD_T_MODRM, 2, { 0x0f, 0x14 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     316    {  UD_T_MODRM, 2, { 0x0f, 0x15 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     317    {  UD_T_MODRM, 2, { 0x0f, 0x16 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX | UD_F_NOT_RN_PFX },
     318    {  UD_T_MODRM, 2, { 0x0f, 0x17 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     319    /** @todo figure when 0f 019 and 0f 0c-0f were made into NOPs. */
     320    {  UD_T_EXACT, 2, { 0x0f, 0x24 }, UD_F_ANY_PFX },
     321    {  UD_T_EXACT, 2, { 0x0f, 0x25 }, UD_F_ANY_PFX },
     322    {  UD_T_EXACT, 2, { 0x0f, 0x26 }, UD_F_ANY_PFX },
     323    {  UD_T_EXACT, 2, { 0x0f, 0x27 }, UD_F_ANY_PFX },
     324    {  UD_T_MODRM, 2, { 0x0f, 0x28 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     325    {  UD_T_MODRM, 2, { 0x0f, 0x29 }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     326    {  UD_T_MODRM, 2, { 0x0f, 0x2b }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     327    {  UD_T_MODRM, 2, { 0x0f, 0x2e }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     328    {  UD_T_MODRM, 2, { 0x0f, 0x2f }, UD_F_NOT_NO_PFX | UD_F_NOT_OZ_PFX },
     329    {  UD_T_EXACT, 2, { 0x0f, 0x36 }, UD_F_ANY_PFX },
     330    {  UD_T_MODRM,      3, { 0x0f, 0x39, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     331    {  UD_T_MODRM_IMM8, 3, { 0x0f, 0x3b, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     332    {  UD_T_MODRM,      3, { 0x0f, 0x3c, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     333    {  UD_T_MODRM,      3, { 0x0f, 0x3d, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     334    {  UD_T_MODRM_IMM8, 3, { 0x0f, 0x3e, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     335    {  UD_T_MODRM_IMM8, 3, { 0x0f, 0x3f, 0x00 }, UD_F_3BYTE_ESC | UD_F_ANY_PFX }, /* Three byte escape table, just unused.  */
     336#endif
     337
     338#if 1
     339    {  UD_T_MODRM, 2, { 0x0f, 0x7a }, UD_F_ANY_PFX },
     340    {  UD_T_MODRM, 2, { 0x0f, 0x7b }, UD_F_ANY_PFX },
     341#endif
     342};
     343
     344
     345void DecodeUdEdgeTest(PCCPUDECODE1UDTST paTests, unsigned cTests)
     346{
     347    /*
     348     * Allocate and initialize a page pair
     349     */
     350    uint8_t BS3_FAR *pbPages;
     351    pbPages  = Bs3MemGuardedTestPageAlloc(BS3MEMKIND_FLAT32);
     352    if (pbPages)
     353    {
     354        unsigned        iTest;
     355        BS3REGCTX       Ctx;
     356        BS3REGCTX       ExpectCtx;
     357        BS3TRAPFRAME    TrapFrame;
     358
     359        Bs3MemZero(&Ctx, sizeof(Ctx));
     360        Bs3MemZero(&ExpectCtx, sizeof(ExpectCtx));
     361        Bs3MemZero(&TrapFrame, sizeof(TrapFrame));
     362
     363        /* Enable SSE. */
     364        ASMSetCR0((ASMGetCR0() & ~(X86_CR0_EM | X86_CR0_TS)) | X86_CR0_MP);
     365        ASMSetCR4(ASMGetCR4() | X86_CR4_OSFXSR);
     366
     367        /* Create a test context. */
     368        Bs3RegCtxSaveEx(&Ctx, BS3_MODE_CODE_32, 512);
     369        Ctx.rbx.u = (uintptr_t)pbPages;
     370        Ctx.rcx.u = (uintptr_t)pbPages;
     371        Ctx.rdx.u = (uintptr_t)pbPages;
     372        Ctx.rax.u = (uintptr_t)pbPages;
     373        Ctx.rbp.u = (uintptr_t)pbPages;
     374        Ctx.rsi.u = (uintptr_t)pbPages;
     375        Ctx.rdi.u = (uintptr_t)pbPages;
     376
     377        Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
     378        ExpectCtx.rflags.u32 |= X86_EFL_RF;
     379
     380        /* Loop thru the tests. */
     381        g_usBs3TestStep = 0;
     382        for (iTest = 0; iTest < cTests; iTest++)
     383        {
     384            typedef struct CPUDECODE1UDSEQ
     385            {
     386                uint8_t cb;
     387                uint8_t ab[10];
     388                uint8_t fIncompatible;
     389            } CPUDECODE1UDSEQ;
     390            typedef CPUDECODE1UDSEQ const BS3_FAR *PCCPUDECODE1UDSEQ;
     391
     392            static CPUDECODE1UDSEQ const s_aPrefixes[] =
     393            {
     394                { 0, { 0    },              UD_F_NOT_NO_PFX },
     395                { 1, { P_OZ },              UD_F_NOT_OZ_PFX },
     396                { 1, { P_RZ },              UD_F_NOT_RZ_PFX },
     397                { 1, { P_RN },              UD_F_NOT_RN_PFX },
     398                { 1, { P_LK },              UD_F_NOT_LK_PFX },
     399                { 2, { P_OZ, P_OZ },        UD_F_NOT_OZ_PFX | UD_F_NOT_OZ_PFX },
     400                { 2, { P_RZ, P_OZ },        UD_F_NOT_RZ_PFX | UD_F_NOT_OZ_PFX },
     401                { 2, { P_RN, P_OZ },        UD_F_NOT_RN_PFX | UD_F_NOT_OZ_PFX },
     402                { 2, { P_LK, P_OZ },        UD_F_NOT_LK_PFX | UD_F_NOT_OZ_PFX },
     403                { 2, { P_OZ, P_RZ },        UD_F_NOT_OZ_PFX | UD_F_NOT_RZ_PFX },
     404                { 2, { P_RZ, P_RZ },        UD_F_NOT_RZ_PFX | UD_F_NOT_RZ_PFX },
     405                { 2, { P_RN, P_RZ },        UD_F_NOT_RN_PFX | UD_F_NOT_RZ_PFX },
     406                { 2, { P_LK, P_RZ },        UD_F_NOT_LK_PFX | UD_F_NOT_RZ_PFX },
     407                { 2, { P_OZ, P_RN },        UD_F_NOT_OZ_PFX | UD_F_NOT_RN_PFX },
     408                { 2, { P_RZ, P_RN },        UD_F_NOT_RZ_PFX | UD_F_NOT_RN_PFX },
     409                { 2, { P_RN, P_RN },        UD_F_NOT_RN_PFX | UD_F_NOT_RN_PFX },
     410                { 2, { P_LK, P_RN },        UD_F_NOT_LK_PFX | UD_F_NOT_RN_PFX },
     411                { 2, { P_OZ, P_LK },        UD_F_NOT_OZ_PFX | UD_F_NOT_LK_PFX },
     412                { 2, { P_RZ, P_LK },        UD_F_NOT_RZ_PFX | UD_F_NOT_LK_PFX },
     413                { 2, { P_RN, P_LK },        UD_F_NOT_RN_PFX | UD_F_NOT_LK_PFX },
     414                { 2, { P_LK, P_LK },        UD_F_NOT_LK_PFX | UD_F_NOT_LK_PFX },
     415            };
     416
     417            static CPUDECODE1UDSEQ const s_aExact[] = { { 0, { 0 }, 0 } };
     418            static CPUDECODE1UDSEQ const s_aModRm[] =
     419            {
     420                { 1, { RM_EAX_EAX, },                                       0 },
     421                { 2, { RM_EAX_DEREF_EBX_DISP8, 0 },                         0 },
     422                { 5, { RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0 },               0 },
     423                { 2, { RM_EAX_SIB, SIB_EBX_X1_NONE, },                      0 },
     424                { 3, { RM_EAX_SIB_DISP8,  SIB_EBX_X1_NONE, 0 },             0 },
     425                { 6, { RM_EAX_SIB_DISP32, SIB_EBX_X1_NONE, 0, 0, 0, 0 },    0 },
     426            };
     427            static CPUDECODE1UDSEQ const s_aModRmImm8[] =
     428            {
     429                { 1 + 1, { RM_EAX_EAX, 0x11 },                                      0 },
     430                { 2 + 1, { RM_EAX_DEREF_EBX_DISP8, 0, 0x11 },                       0 },
     431                { 5 + 1, { RM_EAX_DEREF_EBX_DISP32, 0, 0, 0, 0, 0x11 },             0 },
     432                { 2 + 1, { RM_EAX_SIB, SIB_EBX_X1_NONE, 0x11 },                     0 },
     433                { 3 + 1, { RM_EAX_SIB_DISP8,  SIB_EBX_X1_NONE, 0, 0x11 },           0 },
     434                { 6 + 1, { RM_EAX_SIB_DISP32, SIB_EBX_X1_NONE, 0, 0, 0, 0, 0x11 },  0 },
     435            };
     436            unsigned            iPrefix;
     437            unsigned            cSuffixes;
     438            PCCPUDECODE1UDSEQ   paSuffixes;
     439            unsigned const      cSubTabEntries = paTests[iTest].fFlags & UD_F_3BYTE_ESC ? 256 : 1;
     440            unsigned            cImmEntries    = 1;
     441
     442            /*
     443             * Skip if implemented.
     444             */
     445
     446            /*
     447             * Produce a number of opcode sequences by varying the prefixes and
     448             * ModR/M parts.  Each opcode sequence is then treated to the edge test.
     449             */
     450            switch (paTests[iTest].enmType)
     451            {
     452                case UD_T_EXACT:
     453                    cSuffixes   = RT_ELEMENTS(s_aExact);
     454                    paSuffixes  = s_aExact;
     455                    break;
     456                case UD_T_MODRM:
     457                    cSuffixes   = RT_ELEMENTS(s_aModRm);
     458                    paSuffixes  = s_aModRm;
     459                    break;
     460                case UD_T_MODRM_IMM8:
     461                    cSuffixes   = RT_ELEMENTS(s_aModRmImm8);
     462                    paSuffixes  = s_aModRmImm8;
     463                    cImmEntries = 256;
     464                    break;
     465                default:
     466                    Bs3TestPrintf("#%u: enmType=%d\n", paTests[iTest].enmType);
     467                    continue;
     468            }
     469
     470            for (iPrefix = 0; iPrefix < RT_ELEMENTS(s_aPrefixes); iPrefix++)
     471                if (!(s_aPrefixes[iPrefix].fIncompatible & paTests[iTest].fFlags))
     472                {
     473                    unsigned iSubTab;
     474                    unsigned cbOpcodesLead;
     475                    uint8_t  abOpcodes[32];
     476
     477                    Bs3MemCpy(&abOpcodes[0], &s_aPrefixes[iPrefix].ab[0], s_aPrefixes[iPrefix].cb);
     478                    cbOpcodesLead  = s_aPrefixes[iPrefix].cb;
     479                    Bs3MemCpy(&abOpcodes[cbOpcodesLead], &paTests[iTest].abOpcodes[0], paTests[iTest].cbOpcodes);
     480                    cbOpcodesLead += paTests[iTest].cbOpcodes;
     481
     482                    for (iSubTab = 0; iSubTab < cSubTabEntries; iSubTab++)
     483                    {
     484                        unsigned iSuffix;
     485
     486                        if (cSubTabEntries > 1)
     487                            abOpcodes[cbOpcodesLead - 1] = iSubTab;
     488
     489                        for (iSuffix = 0; iSuffix < cSuffixes; iSuffix++)
     490                            if (!(paSuffixes[iSuffix].fIncompatible & paTests[iTest].fFlags))
     491                            {
     492                                unsigned const  cbOpcodes    = cbOpcodesLead + paSuffixes[iSuffix].cb;
     493                                unsigned        cbOpcodesMin = 1;
     494                                unsigned        iImm;
     495                                Bs3MemCpy(&abOpcodes[cbOpcodesLead], paSuffixes[iSuffix].ab, paSuffixes[iSuffix].cb);
     496
     497                                for (iImm = 0; iImm < cImmEntries; iImm++)
     498                                {
     499                                    unsigned cb;
     500
     501                                    if (cImmEntries > 1)
     502                                        abOpcodes[cbOpcodes - 1] = iImm;
     503
     504                                    /*
     505                                     * Do the edge thing.
     506                                     */
     507                                    cb = cbOpcodes;
     508                                    while (cb >= cbOpcodesMin)
     509                                    {
     510                                        uint8_t BS3_FAR *pbRip = &pbPages[X86_PAGE_SIZE - cb];
     511                                        uint8_t          bXcptExpected;
     512
     513                                        Bs3RegCtxSetRipCsFromFlat(&Ctx, (uintptr_t)pbRip);
     514                                        ExpectCtx.rip = Ctx.rip;
     515                                        ExpectCtx.cs  = Ctx.cs;
     516                                        if (cb >= cbOpcodes)
     517                                        {
     518                                            ExpectCtx.cr2 = Ctx.cr2;
     519                                            bXcptExpected = X86_XCPT_UD;
     520                                        }
     521                                        else
     522                                        {
     523                                            ExpectCtx.cr2.u = (uintptr_t)&pbPages[X86_PAGE_SIZE];
     524                                            bXcptExpected = X86_XCPT_PF;
     525                                        }
     526
     527                                        Bs3MemCpy(pbRip, &abOpcodes[0], cb);
     528                                        Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
     529#if 0
     530                                        Bs3TestPrintf("iTest=%d iPrefix=%d (%d/%#x) iSubTab=%d iSuffix=%d (%d/%#x) iImm=%d cb=%d cbOp=%d: %.*Rhxs\n",
     531                                                       iTest, iPrefix, s_aPrefixes[iPrefix].cb, s_aPrefixes[iPrefix].fIncompatible,
     532                                                       iSubTab, iSuffix, paSuffixes[iSuffix].cb, paSuffixes[iSuffix].fIncompatible, iImm,
     533                                                       cb, cbOpcodes,
     534                                                       cbOpcodes, abOpcodes);
     535#endif
     536
     537                                        if (   !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/,
     538                                                                     0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "mode",  0)
     539                                            || TrapFrame.bXcpt != bXcptExpected)
     540                                        {
     541                                            Bs3TestFailedF("iTest=%d iPrefix=%d (%d/%#x) iSubTab=%u iSuffix=%d (%d/%#x) cb=%d cbOp=%d: %.*Rhxs\n",
     542                                                           iTest, iPrefix, s_aPrefixes[iPrefix].cb, s_aPrefixes[iPrefix].fIncompatible,
     543                                                           iSubTab, iSuffix, paSuffixes[iSuffix].cb, paSuffixes[iSuffix].fIncompatible,
     544                                                           cb, cbOpcodes,
     545                                                           cbOpcodes, abOpcodes);
     546                                            if (TrapFrame.bXcpt != bXcptExpected)
     547                                                Bs3TestFailedF("Expected bXcpt=%#x got %#x\n", bXcptExpected, TrapFrame.bXcpt);
     548                                            Bs3TrapPrintFrame(&TrapFrame);
     549                                            Bs3Shutdown();
     550                                        }
     551
     552                                        /* next */
     553                                        g_usBs3TestStep++;
     554                                        cb--;
     555                                    }
     556
     557                                    /* For iImm > 0 only test cb == cbOpcode since the byte isn't included when cb < cbOpcode. */
     558                                    cbOpcodesMin = cbOpcodes;
     559                                }
     560                            }
     561                    }
     562                }
     563        }
     564
     565        Bs3MemGuardedTestPageFree(pbPages);
     566    }
     567    else
     568        Bs3TestFailed("Failed to allocate two pages!\n");
     569}
     570
     571
     572
     573
    222574BS3_DECL(void) Main_pp32()
    223575{
     
    225577    Bs3TestPrintf("g_uBs3CpuDetected=%#x\n", g_uBs3CpuDetected);
    226578
    227     DecodeEdgeTest();
     579    //DecodeEdgeTest();
     580    Bs3TestSub("undefined opcodes");
     581    DecodeUdEdgeTest(g_aUdTest, RT_ELEMENTS(g_aUdTest));
    228582
    229583    Bs3TestTerm();
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