- Timestamp:
- Jan 30, 2017 6:35:49 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-decoding-1.c32
r62410 r65524 32 32 #include <iprt/asm-amd64-x86.h> 33 33 34 35 /********************************************************************************************************************************* 36 * Structures and Typedefs * 37 *********************************************************************************************************************************/ 34 38 /** 35 39 * Simple test. … … 37 41 typedef struct CPUDECODE1TST 38 42 { 39 uint 8_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; 43 47 } CPUDECODE1TST; 44 48 typedef CPUDECODE1TST BS3_FAR *PCPUDECODE1TST; … … 56 60 #define P_RN X86_OP_PRF_REPNZ 57 61 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 */ 67 90 CPUDECODE1TST const g_aSimpleTests[] = 68 91 { … … 70 93 * fFlags, cbUd, cbOpcodes, abOpcodes 71 94 */ 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 72 121 #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, } }, 79 128 #endif 80 129 #if 0 81 130 /* The XADD instruction has empty lines for 66, f3 and f2 prefixes. 82 131 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, } }, 91 140 #endif 92 141 #if 0 93 142 /* 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 1143 { 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 103 152 /* The lddqu instruction requires a 0xf2 prefix, intel only lists 0x66 and empty 104 153 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 128 179 /** @todo crc32 / movbe */ 129 180 }; … … 153 204 for (i = 0; i < RT_ELEMENTS(g_aSimpleTests); i++) 154 205 { 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; 156 216 while (cb >= 1) 157 217 { … … 161 221 Bs3RegCtxSetRipCsFromFlat(&Ctx, (uintptr_t)pbRip); 162 222 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame); 163 #if 0164 Bs3TestPrintf("\ni=%d cb=%#x (cb Ud=%#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)) 168 228 { 169 229 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); 173 232 } 174 else if (cb < g_aSimpleTests[i].cbOpcodes)233 else if (cb < cbOpcodes) 175 234 { 176 235 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); 180 238 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); 184 241 } 185 242 else 186 243 { 187 244 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); 191 247 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); 195 250 } 196 251 if (Bs3TestSubErrorCount() != cErrorsBefore) 197 252 { 198 253 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]); 201 256 Bs3TestPrintf("\n"); 202 257 } … … 220 275 221 276 277 /** 278 * Undefined opcode test. 279 */ 280 typedef 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; 291 typedef 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 305 CPUDECODE1UDTST 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 345 void 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 222 574 BS3_DECL(void) Main_pp32() 223 575 { … … 225 577 Bs3TestPrintf("g_uBs3CpuDetected=%#x\n", g_uBs3CpuDetected); 226 578 227 DecodeEdgeTest(); 579 //DecodeEdgeTest(); 580 Bs3TestSub("undefined opcodes"); 581 DecodeUdEdgeTest(g_aUdTest, RT_ELEMENTS(g_aUdTest)); 228 582 229 583 Bs3TestTerm();
Note:
See TracChangeset
for help on using the changeset viewer.