VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c@ 66289

Last change on this file since 66289 was 66286, checked in by vboxsync, 8 years ago

bs3-cpu-generated-1: 16 byte SSE alignment check.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 119.0 KB
Line 
1/* $Id: bs3-cpu-generated-1-template.c 66286 2017-03-28 10:17:15Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-generated-1, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#ifndef BS3_INSTANTIATING_CMN
28# error "BS3_INSTANTIATING_CMN not defined"
29#endif
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <iprt/asm.h>
36#include <iprt/asm-amd64-x86.h>
37
38#include "bs3-cpu-generated-1.h"
39
40
41/*********************************************************************************************************************************
42* Defined Constants And Macros *
43*********************************************************************************************************************************/
44#define P_CS X86_OP_PRF_CS
45#define P_SS X86_OP_PRF_SS
46#define P_DS X86_OP_PRF_DS
47#define P_ES X86_OP_PRF_ES
48#define P_FS X86_OP_PRF_FS
49#define P_GS X86_OP_PRF_GS
50#define P_OZ X86_OP_PRF_SIZE_OP
51#define P_AZ X86_OP_PRF_SIZE_ADDR
52#define P_LK X86_OP_PRF_LOCK
53#define P_RN X86_OP_PRF_REPNZ
54#define P_RZ X86_OP_PRF_REPZ
55
56#define REX_WRBX (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_B | X86_OP_REX_X)
57#define REX_W___ (X86_OP_REX_W)
58#define REX_WR__ (X86_OP_REX_W | X86_OP_REX_R)
59#define REX_W_B_ (X86_OP_REX_W | X86_OP_REX_B)
60#define REX_W__X (X86_OP_REX_W | X86_OP_REX_X)
61#define REX_WRB_ (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_B)
62#define REX_WR_X (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_X)
63#define REX_W_BX (X86_OP_REX_W | X86_OP_REX_B | X86_OP_REX_X)
64#define REX__R__ (X86_OP_REX_R)
65#define REX__RB_ (X86_OP_REX_R | X86_OP_REX_B)
66#define REX__R_X (X86_OP_REX_R | X86_OP_REX_X)
67#define REX__RBX (X86_OP_REX_R | X86_OP_REX_B | X86_OP_REX_X)
68#define REX___B_ (X86_OP_REX_B)
69#define REX___BX (X86_OP_REX_B | X86_OP_REX_X)
70#define REX____X (X86_OP_REX_X)
71#define REX_____ (0x40)
72
73
74/** @def BS3CG1_DPRINTF
75 * Debug print macro.
76 */
77#if 0
78# define BS3CG1_DPRINTF(a_ArgList) Bs3TestPrintf a_ArgList
79//# define BS3CG1_DEBUG_CTX_MOD
80#else
81# define BS3CG1_DPRINTF(a_ArgList) do { } while (0)
82#endif
83
84
85
86/*********************************************************************************************************************************
87* Structures and Typedefs *
88*********************************************************************************************************************************/
89/** Operand value location. */
90typedef enum BS3CG1OPLOC
91{
92 BS3CG1OPLOC_INVALID = 0,
93 BS3CG1OPLOC_CTX,
94 BS3CG1OPLOC_IMM,
95 BS3CG1OPLOC_MEM,
96 BS3CG1OPLOC_MEM_RW,
97 BS3CG1OPLOC_END
98} BS3CG1OPLOC;
99
100/**
101 * The state.
102 */
103typedef struct BS3CG1STATE
104{
105 /** @name Instruction details (expanded from BS3CG1INSTR).
106 * @{ */
107 /** Pointer to the mnemonic string (not terminated) (g_achBs3Cg1Mnemonics). */
108 const char BS3_FAR *pchMnemonic;
109 /** Pointer to the test header. */
110 PCBS3CG1TESTHDR pTestHdr;
111 /** Pointer to the per operand flags (g_abBs3Cg1Operands). */
112 const uint8_t BS3_FAR *pabOperands;
113 /** Opcode bytes (g_abBs3Cg1Opcodes). */
114 const uint8_t BS3_FAR *pabOpcodes;
115 /** The current instruction number in the input array (for error reporting). */
116 uint32_t iInstr;
117
118 /** The instruction flags. */
119 uint32_t fFlags;
120 /** The encoding. */
121 BS3CG1ENC enmEncoding;
122 /** The CPU test / CPU ID. */
123 BS3CG1CPU enmCpuTest;
124 /** Prefix sensitivity and requirements. */
125 BS3CG1PFXKIND enmPrefixKind;
126 /** Exception type (SSE, AVX). */
127 BS3CG1XCPTTYPE enmXcptType;
128 /** Per operand flags. */
129 BS3CG1OP aenmOperands[4];
130 /** Opcode bytes. */
131 uint8_t abOpcodes[4];
132
133 /** The length of the mnemonic. */
134 uint8_t cchMnemonic;
135 /** Whether to advance the mnemonic pointer or not. */
136 uint8_t fAdvanceMnemonic;
137 /** The number of opcode bytes. */
138 uint8_t cbOpcodes;
139 /** Number of operands. */
140 uint8_t cOperands;
141 /** @} */
142
143 /** Operand size in bytes (0 if not applicable). */
144 uint8_t cbOperand;
145 /** Current target ring (0..3). */
146 uint8_t uCpl;
147
148 /** The current test number. */
149 uint8_t iTest;
150
151 /** Target mode (g_bBs3CurrentMode). */
152 uint8_t bMode;
153 /** First ring being tested. */
154 uint8_t iFirstRing;
155 /** End of rings being tested. */
156 uint8_t iEndRing;
157
158
159 /** @name Current encoded instruction.
160 * @{ */
161 /** The size of the current instruction that we're testing. */
162 uint8_t cbCurInstr;
163 /** The size the prefixes. */
164 uint8_t cbCurPrefix;
165 /** The offset into abCurInstr of the immediate. */
166 uint8_t offCurImm;
167 /** Buffer for assembling the current instruction. */
168 uint8_t abCurInstr[24];
169
170 /** Set if the encoding can't be tested in the same ring as this test code.
171 * This is used to deal with encodings modifying SP/ESP/RSP. */
172 bool fSameRingNotOkay;
173 /** Whether to work the extended context too. */
174 bool fWorkExtCtx;
175 /** The aOperands index of the modrm.reg operand (if applicable). */
176 uint8_t iRegOp;
177 /** The aOperands index of the modrm.rm operand (if applicable). */
178 uint8_t iRmOp;
179
180 /** Operands details. */
181 struct
182 {
183 uint8_t cbOp;
184 /** BS3CG1OPLOC_XXX. */
185 uint8_t enmLocation;
186 /** The BS3CG1DST value for this field.
187 * Set to BS3CG1DST_INVALID if memory or immediate. */
188 uint8_t idxField;
189 /** Depends on enmLocation.
190 * - BS3CG1OPLOC_IMM: offset relative to start of the instruction.
191 * - BS3CG1OPLOC_MEM: offset should be subtracted from &pbDataPg[_4K].
192 * - BS3CG1OPLOC_MEM_RW: offset should be subtracted from &pbDataPg[_4K].
193 * - BS3CG1OPLOC_CTX: not used (use idxField instead).
194 */
195 uint8_t off;
196 } aOperands[4];
197 /** @} */
198
199 /** Page to put code in. When paging is enabled, the page before and after
200 * are marked not-present. */
201 uint8_t BS3_FAR *pbCodePg;
202 /** The flat address corresponding to pbCodePg. */
203 uintptr_t uCodePgFlat;
204 /** The 16-bit address corresponding to pbCodePg if relevant for bMode. */
205 RTFAR16 CodePgFar;
206 /** The IP/EIP/RIP value for pbCodePg[0] relative to CS (bMode). */
207 uintptr_t CodePgRip;
208
209 /** Page for placing data operands in. When paging is enabled, the page before
210 * and after are marked not-present. */
211 uint8_t BS3_FAR *pbDataPg;
212 /** The flat address corresponding to pbDataPg. */
213 uintptr_t uDataPgFlat;
214 /** The 16-bit address corresponding to pbDataPg. */
215 RTFAR16 DataPgFar;
216
217 /** The name corresponding to bMode. */
218 const char BS3_FAR *pszMode;
219 /** The short name corresponding to bMode. */
220 const char BS3_FAR *pszModeShort;
221
222 /** @name Expected result (modifiable by output program).
223 * @{ */
224 /** The expected exception based on operand values or result.
225 * UINT8_MAX if no special exception expected. */
226 uint8_t bValueXcpt;
227 /** @} */
228 /** Alignment exception expected by the encoder.
229 * UINT8_MAX if no special exception expected. */
230 uint8_t bAlignmentXcpt;
231
232 /** The context we're working on. */
233 BS3REGCTX Ctx;
234 /** The trap context and frame. */
235 BS3TRAPFRAME TrapFrame;
236 /** Initial contexts, one for each ring. */
237 BS3REGCTX aInitialCtxs[4];
238
239 /** The extended context we're working on (input, expected output). */
240 PBS3EXTCTX pExtCtx;
241 /** The extended result context (analoguous to TrapFrame). */
242 PBS3EXTCTX pResultExtCtx;
243 /** The initial extended context. */
244 PBS3EXTCTX pInitialExtCtx;
245
246 /** Memory operand scratch space. */
247 union
248 {
249 uint8_t ab[128];
250 uint16_t au16[128 / sizeof(uint16_t)];
251 uint32_t au32[128 / sizeof(uint32_t)];
252 uint64_t au64[128 / sizeof(uint64_t)];
253 } MemOp;
254
255 /** Array parallel to aInitialCtxs for saving segment registers. */
256 struct
257 {
258 RTSEL ds;
259 } aSavedSegRegs[4];
260
261} BS3CG1STATE;
262/** Pointer to the generated test state. */
263typedef BS3CG1STATE *PBS3CG1STATE;
264
265
266#define BS3CG1_PF_OZ UINT16_C(0x0001)
267#define BS3CG1_PF_AZ UINT16_C(0x0002)
268#define BS3CG1_PF_CS UINT16_C(0x0004)
269#define BS3CG1_PF_DS UINT16_C(0x0008)
270#define BS3CG1_PF_ES UINT16_C(0x0010)
271#define BS3CG1_PF_FS UINT16_C(0x0020)
272#define BS3CG1_PF_GS UINT16_C(0x0040)
273#define BS3CG1_PF_SS UINT16_C(0x0080)
274#define BS3CG1_PF_SEGS (BS3CG1_PF_CS | BS3CG1_PF_DS | BS3CG1_PF_ES | BS3CG1_PF_FS | BS3CG1_PF_GS | BS3CG1_PF_SS)
275#define BS3CG1_PF_MEM (BS3CG1_PF_SEGS | BS3CG1_PF_AZ)
276#define BS3CG1_PF_LK UINT16_C(0x0100)
277#define BS3CG1_PF_RN UINT16_C(0x0200)
278#define BS3CG1_PF_RZ UINT16_C(0x0400)
279#define BS3CG1_PF_W UINT16_C(0x0800) /**< REX.W */
280#define BS3CG1_PF_R UINT16_C(0x1000) /**< REX.R */
281#define BS3CG1_PF_B UINT16_C(0x2000) /**< REX.B */
282#define BS3CG1_PF_X UINT16_C(0x4000) /**< REX.X */
283
284
285/** Used in g_cbBs3Cg1DstFields to indicate that it's one of the 4 operands. */
286#define BS3CG1DSTSIZE_OPERAND UINT8_C(255)
287/** Used in g_cbBs3Cg1DstFields to indicate that the operand size determins
288 * the field size (2, 4, or 8). */
289#define BS3CG1DSTSIZE_OPERAND_SIZE_GRP UINT8_C(254)
290
291
292
293/*********************************************************************************************************************************
294* Global Variables *
295*********************************************************************************************************************************/
296/** Destination field sizes indexed by bBS3CG1DST.
297 * Zero means operand size sized. */
298static const uint8_t g_acbBs3Cg1DstFields[] =
299{
300 /* [BS3CG1DST_INVALID] = */ BS3CG1DSTSIZE_OPERAND,
301
302 /* [BS3CG1DST_OP1] = */ BS3CG1DSTSIZE_OPERAND,
303 /* [BS3CG1DST_OP2] = */ BS3CG1DSTSIZE_OPERAND,
304 /* [BS3CG1DST_OP3] = */ BS3CG1DSTSIZE_OPERAND,
305 /* [BS3CG1DST_OP4] = */ BS3CG1DSTSIZE_OPERAND,
306 /* [BS3CG1DST_EFL] = */ 4,
307 /* [BS3CG1DST_EFL_UNDEF]=*/ 4,
308
309 /* [BS3CG1DST_AL] = */ 1,
310 /* [BS3CG1DST_CL] = */ 1,
311 /* [BS3CG1DST_DL] = */ 1,
312 /* [BS3CG1DST_BL] = */ 1,
313 /* [BS3CG1DST_AH] = */ 1,
314 /* [BS3CG1DST_CH] = */ 1,
315 /* [BS3CG1DST_DH] = */ 1,
316 /* [BS3CG1DST_BH] = */ 1,
317 /* [BS3CG1DST_SPL] = */ 1,
318 /* [BS3CG1DST_BPL] = */ 1,
319 /* [BS3CG1DST_SIL] = */ 1,
320 /* [BS3CG1DST_DIL] = */ 1,
321 /* [BS3CG1DST_R8L] = */ 1,
322 /* [BS3CG1DST_R9L] = */ 1,
323 /* [BS3CG1DST_R10L] = */ 1,
324 /* [BS3CG1DST_R11L] = */ 1,
325 /* [BS3CG1DST_R12L] = */ 1,
326 /* [BS3CG1DST_R13L] = */ 1,
327 /* [BS3CG1DST_R14L] = */ 1,
328 /* [BS3CG1DST_R15L] = */ 1,
329
330 /* [BS3CG1DST_AX] = */ 2,
331 /* [BS3CG1DST_CX] = */ 2,
332 /* [BS3CG1DST_DX] = */ 2,
333 /* [BS3CG1DST_BX] = */ 2,
334 /* [BS3CG1DST_SP] = */ 2,
335 /* [BS3CG1DST_BP] = */ 2,
336 /* [BS3CG1DST_SI] = */ 2,
337 /* [BS3CG1DST_DI] = */ 2,
338 /* [BS3CG1DST_R8W] = */ 2,
339 /* [BS3CG1DST_R9W] = */ 2,
340 /* [BS3CG1DST_R10W] = */ 2,
341 /* [BS3CG1DST_R11W] = */ 2,
342 /* [BS3CG1DST_R12W] = */ 2,
343 /* [BS3CG1DST_R13W] = */ 2,
344 /* [BS3CG1DST_R14W] = */ 2,
345 /* [BS3CG1DST_R15W] = */ 2,
346
347 /* [BS3CG1DST_EAX] = */ 4,
348 /* [BS3CG1DST_ECX] = */ 4,
349 /* [BS3CG1DST_EDX] = */ 4,
350 /* [BS3CG1DST_EBX] = */ 4,
351 /* [BS3CG1DST_ESP] = */ 4,
352 /* [BS3CG1DST_EBP] = */ 4,
353 /* [BS3CG1DST_ESI] = */ 4,
354 /* [BS3CG1DST_EDI] = */ 4,
355 /* [BS3CG1DST_R8D] = */ 4,
356 /* [BS3CG1DST_R9D] = */ 4,
357 /* [BS3CG1DST_R10D] = */ 4,
358 /* [BS3CG1DST_R11D] = */ 4,
359 /* [BS3CG1DST_R12D] = */ 4,
360 /* [BS3CG1DST_R13D] = */ 4,
361 /* [BS3CG1DST_R14D] = */ 4,
362 /* [BS3CG1DST_R15D] = */ 4,
363
364 /* [BS3CG1DST_RAX] = */ 8,
365 /* [BS3CG1DST_RCX] = */ 8,
366 /* [BS3CG1DST_RDX] = */ 8,
367 /* [BS3CG1DST_RBX] = */ 8,
368 /* [BS3CG1DST_RSP] = */ 8,
369 /* [BS3CG1DST_RBP] = */ 8,
370 /* [BS3CG1DST_RSI] = */ 8,
371 /* [BS3CG1DST_RDI] = */ 8,
372 /* [BS3CG1DST_R8] = */ 8,
373 /* [BS3CG1DST_R9] = */ 8,
374 /* [BS3CG1DST_R10] = */ 8,
375 /* [BS3CG1DST_R11] = */ 8,
376 /* [BS3CG1DST_R12] = */ 8,
377 /* [BS3CG1DST_R13] = */ 8,
378 /* [BS3CG1DST_R14] = */ 8,
379 /* [BS3CG1DST_R15] = */ 8,
380
381 /* [BS3CG1DST_OZ_RAX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
382 /* [BS3CG1DST_OZ_RCX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
383 /* [BS3CG1DST_OZ_RDX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
384 /* [BS3CG1DST_OZ_RBX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
385 /* [BS3CG1DST_OZ_RSP] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
386 /* [BS3CG1DST_OZ_RBP] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
387 /* [BS3CG1DST_OZ_RSI] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
388 /* [BS3CG1DST_OZ_RDI] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
389 /* [BS3CG1DST_OZ_R8] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
390 /* [BS3CG1DST_OZ_R9] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
391 /* [BS3CG1DST_OZ_R10] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
392 /* [BS3CG1DST_OZ_R11] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
393 /* [BS3CG1DST_OZ_R12] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
394 /* [BS3CG1DST_OZ_R13] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
395 /* [BS3CG1DST_OZ_R14] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
396 /* [BS3CG1DST_OZ_R15] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
397
398 /* [BS3CG1DST_FCW] = */ 2,
399 /* [BS3CG1DST_FSW] = */ 2,
400 /* [BS3CG1DST_FTW] = */ 2,
401 /* [BS3CG1DST_FOP] = */ 2,
402 /* [BS3CG1DST_FPUIP] = */ 2,
403 /* [BS3CG1DST_FPUCS] = */ 2,
404 /* [BS3CG1DST_FPUDP] = */ 2,
405 /* [BS3CG1DST_FPUDS] = */ 2,
406 /* [BS3CG1DST_MXCSR] = */ 4,
407 /* [BS3CG1DST_MXCSR_MASK] = */ 4,
408 /* [BS3CG1DST_ST0] = */ 12,
409 /* [BS3CG1DST_ST1] = */ 12,
410 /* [BS3CG1DST_ST2] = */ 12,
411 /* [BS3CG1DST_ST3] = */ 12,
412 /* [BS3CG1DST_ST4] = */ 12,
413 /* [BS3CG1DST_ST5] = */ 12,
414 /* [BS3CG1DST_ST6] = */ 12,
415 /* [BS3CG1DST_ST7] = */ 12,
416 /* [BS3CG1DST_MM0] = */ 8,
417 /* [BS3CG1DST_MM1] = */ 8,
418 /* [BS3CG1DST_MM2] = */ 8,
419 /* [BS3CG1DST_MM3] = */ 8,
420 /* [BS3CG1DST_MM4] = */ 8,
421 /* [BS3CG1DST_MM5] = */ 8,
422 /* [BS3CG1DST_MM6] = */ 8,
423 /* [BS3CG1DST_MM7] = */ 8,
424 /* [BS3CG1DST_XMM0] = */ 16,
425 /* [BS3CG1DST_XMM1] = */ 16,
426 /* [BS3CG1DST_XMM2] = */ 16,
427 /* [BS3CG1DST_XMM3] = */ 16,
428 /* [BS3CG1DST_XMM4] = */ 16,
429 /* [BS3CG1DST_XMM5] = */ 16,
430 /* [BS3CG1DST_XMM6] = */ 16,
431 /* [BS3CG1DST_XMM7] = */ 16,
432 /* [BS3CG1DST_XMM8] = */ 16,
433 /* [BS3CG1DST_XMM9] = */ 16,
434 /* [BS3CG1DST_XMM10] = */ 16,
435 /* [BS3CG1DST_XMM11] = */ 16,
436 /* [BS3CG1DST_XMM12] = */ 16,
437 /* [BS3CG1DST_XMM13] = */ 16,
438 /* [BS3CG1DST_XMM14] = */ 16,
439 /* [BS3CG1DST_XMM15] = */ 16,
440 /* [BS3CG1DST_XMM0_LO] = */ 8,
441 /* [BS3CG1DST_XMM1_LO] = */ 8,
442 /* [BS3CG1DST_XMM2_LO] = */ 8,
443 /* [BS3CG1DST_XMM3_LO] = */ 8,
444 /* [BS3CG1DST_XMM4_LO] = */ 8,
445 /* [BS3CG1DST_XMM5_LO] = */ 8,
446 /* [BS3CG1DST_XMM6_LO] = */ 8,
447 /* [BS3CG1DST_XMM7_LO] = */ 8,
448 /* [BS3CG1DST_XMM8_LO] = */ 8,
449 /* [BS3CG1DST_XMM9_LO] = */ 8,
450 /* [BS3CG1DST_XMM10_LO] = */ 8,
451 /* [BS3CG1DST_XMM11_LO] = */ 8,
452 /* [BS3CG1DST_XMM12_LO] = */ 8,
453 /* [BS3CG1DST_XMM13_LO] = */ 8,
454 /* [BS3CG1DST_XMM14_LO] = */ 8,
455 /* [BS3CG1DST_XMM15_LO] = */ 8,
456 /* [BS3CG1DST_XMM0_HI] = */ 8,
457 /* [BS3CG1DST_XMM1_HI] = */ 8,
458 /* [BS3CG1DST_XMM2_HI] = */ 8,
459 /* [BS3CG1DST_XMM3_HI] = */ 8,
460 /* [BS3CG1DST_XMM4_HI] = */ 8,
461 /* [BS3CG1DST_XMM5_HI] = */ 8,
462 /* [BS3CG1DST_XMM6_HI] = */ 8,
463 /* [BS3CG1DST_XMM7_HI] = */ 8,
464 /* [BS3CG1DST_XMM8_HI] = */ 8,
465 /* [BS3CG1DST_XMM9_HI] = */ 8,
466 /* [BS3CG1DST_XMM10_HI] = */ 8,
467 /* [BS3CG1DST_XMM11_HI] = */ 8,
468 /* [BS3CG1DST_XMM12_HI] = */ 8,
469 /* [BS3CG1DST_XMM13_HI] = */ 8,
470 /* [BS3CG1DST_XMM14_HI] = */ 8,
471 /* [BS3CG1DST_XMM15_HI] = */ 8,
472 /* [BS3CG1DST_YMM0] = */ 32,
473 /* [BS3CG1DST_YMM1] = */ 32,
474 /* [BS3CG1DST_YMM2] = */ 32,
475 /* [BS3CG1DST_YMM3] = */ 32,
476 /* [BS3CG1DST_YMM4] = */ 32,
477 /* [BS3CG1DST_YMM5] = */ 32,
478 /* [BS3CG1DST_YMM6] = */ 32,
479 /* [BS3CG1DST_YMM7] = */ 32,
480 /* [BS3CG1DST_YMM8] = */ 32,
481 /* [BS3CG1DST_YMM9] = */ 32,
482 /* [BS3CG1DST_YMM10] = */ 32,
483 /* [BS3CG1DST_YMM11] = */ 32,
484 /* [BS3CG1DST_YMM12] = */ 32,
485 /* [BS3CG1DST_YMM13] = */ 32,
486 /* [BS3CG1DST_YMM14] = */ 32,
487 /* [BS3CG1DST_YMM15] = */ 32,
488
489 /* [BS3CG1DST_VALUE_XCPT] = */ 1,
490};
491AssertCompile(RT_ELEMENTS(g_acbBs3Cg1DstFields) == BS3CG1DST_END);
492
493/** Destination field offset indexed by bBS3CG1DST.
494 * Zero means operand size sized. */
495static const unsigned g_aoffBs3Cg1DstFields[] =
496{
497 /* [BS3CG1DST_INVALID] = */ ~0U,
498 /* [BS3CG1DST_OP1] = */ ~0U,
499 /* [BS3CG1DST_OP2] = */ ~0U,
500 /* [BS3CG1DST_OP3] = */ ~0U,
501 /* [BS3CG1DST_OP4] = */ ~0U,
502 /* [BS3CG1DST_EFL] = */ RT_OFFSETOF(BS3REGCTX, rflags),
503 /* [BS3CG1DST_EFL_UNDEF]=*/ ~0, /* special field */
504
505 /* [BS3CG1DST_AL] = */ RT_OFFSETOF(BS3REGCTX, rax.u8),
506 /* [BS3CG1DST_CL] = */ RT_OFFSETOF(BS3REGCTX, rcx.u8),
507 /* [BS3CG1DST_DL] = */ RT_OFFSETOF(BS3REGCTX, rdx.u8),
508 /* [BS3CG1DST_BL] = */ RT_OFFSETOF(BS3REGCTX, rbx.u8),
509 /* [BS3CG1DST_AH] = */ RT_OFFSETOF(BS3REGCTX, rax.b.bHi),
510 /* [BS3CG1DST_CH] = */ RT_OFFSETOF(BS3REGCTX, rcx.b.bHi),
511 /* [BS3CG1DST_DH] = */ RT_OFFSETOF(BS3REGCTX, rdx.b.bHi),
512 /* [BS3CG1DST_BH] = */ RT_OFFSETOF(BS3REGCTX, rbx.b.bHi),
513 /* [BS3CG1DST_SPL] = */ RT_OFFSETOF(BS3REGCTX, rsp.u8),
514 /* [BS3CG1DST_BPL] = */ RT_OFFSETOF(BS3REGCTX, rbp.u8),
515 /* [BS3CG1DST_SIL] = */ RT_OFFSETOF(BS3REGCTX, rsi.u8),
516 /* [BS3CG1DST_DIL] = */ RT_OFFSETOF(BS3REGCTX, rdi.u8),
517 /* [BS3CG1DST_R8L] = */ RT_OFFSETOF(BS3REGCTX, r8.u8),
518 /* [BS3CG1DST_R9L] = */ RT_OFFSETOF(BS3REGCTX, r9.u8),
519 /* [BS3CG1DST_R10L] = */ RT_OFFSETOF(BS3REGCTX, r10.u8),
520 /* [BS3CG1DST_R11L] = */ RT_OFFSETOF(BS3REGCTX, r11.u8),
521 /* [BS3CG1DST_R12L] = */ RT_OFFSETOF(BS3REGCTX, r12.u8),
522 /* [BS3CG1DST_R13L] = */ RT_OFFSETOF(BS3REGCTX, r13.u8),
523 /* [BS3CG1DST_R14L] = */ RT_OFFSETOF(BS3REGCTX, r14.u8),
524 /* [BS3CG1DST_R15L] = */ RT_OFFSETOF(BS3REGCTX, r15.u8),
525
526 /* [BS3CG1DST_AX] = */ RT_OFFSETOF(BS3REGCTX, rax.u16),
527 /* [BS3CG1DST_CX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u16),
528 /* [BS3CG1DST_DX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u16),
529 /* [BS3CG1DST_BX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u16),
530 /* [BS3CG1DST_SP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u16),
531 /* [BS3CG1DST_BP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u16),
532 /* [BS3CG1DST_SI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u16),
533 /* [BS3CG1DST_DI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u16),
534 /* [BS3CG1DST_R8W] = */ RT_OFFSETOF(BS3REGCTX, r8.u16),
535 /* [BS3CG1DST_R9W] = */ RT_OFFSETOF(BS3REGCTX, r9.u16),
536 /* [BS3CG1DST_R10W] = */ RT_OFFSETOF(BS3REGCTX, r10.u16),
537 /* [BS3CG1DST_R11W] = */ RT_OFFSETOF(BS3REGCTX, r11.u16),
538 /* [BS3CG1DST_R12W] = */ RT_OFFSETOF(BS3REGCTX, r12.u16),
539 /* [BS3CG1DST_R13W] = */ RT_OFFSETOF(BS3REGCTX, r13.u16),
540 /* [BS3CG1DST_R14W] = */ RT_OFFSETOF(BS3REGCTX, r14.u16),
541 /* [BS3CG1DST_R15W] = */ RT_OFFSETOF(BS3REGCTX, r15.u16),
542
543 /* [BS3CG1DST_EAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u32),
544 /* [BS3CG1DST_ECX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u32),
545 /* [BS3CG1DST_EDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u32),
546 /* [BS3CG1DST_EBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u32),
547 /* [BS3CG1DST_ESP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u32),
548 /* [BS3CG1DST_EBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u32),
549 /* [BS3CG1DST_ESI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u32),
550 /* [BS3CG1DST_EDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u32),
551 /* [BS3CG1DST_R8D] = */ RT_OFFSETOF(BS3REGCTX, r8.u32),
552 /* [BS3CG1DST_R9D] = */ RT_OFFSETOF(BS3REGCTX, r9.u32),
553 /* [BS3CG1DST_R10D] = */ RT_OFFSETOF(BS3REGCTX, r10.u32),
554 /* [BS3CG1DST_R11D] = */ RT_OFFSETOF(BS3REGCTX, r11.u32),
555 /* [BS3CG1DST_R12D] = */ RT_OFFSETOF(BS3REGCTX, r12.u32),
556 /* [BS3CG1DST_R13D] = */ RT_OFFSETOF(BS3REGCTX, r13.u32),
557 /* [BS3CG1DST_R14D] = */ RT_OFFSETOF(BS3REGCTX, r14.u32),
558 /* [BS3CG1DST_R15D] = */ RT_OFFSETOF(BS3REGCTX, r15.u32),
559
560 /* [BS3CG1DST_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u64),
561 /* [BS3CG1DST_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u64),
562 /* [BS3CG1DST_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u64),
563 /* [BS3CG1DST_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u64),
564 /* [BS3CG1DST_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u64),
565 /* [BS3CG1DST_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u64),
566 /* [BS3CG1DST_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u64),
567 /* [BS3CG1DST_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u64),
568 /* [BS3CG1DST_R8] = */ RT_OFFSETOF(BS3REGCTX, r8.u64),
569 /* [BS3CG1DST_R9] = */ RT_OFFSETOF(BS3REGCTX, r9.u64),
570 /* [BS3CG1DST_R10] = */ RT_OFFSETOF(BS3REGCTX, r10.u64),
571 /* [BS3CG1DST_R11] = */ RT_OFFSETOF(BS3REGCTX, r11.u64),
572 /* [BS3CG1DST_R12] = */ RT_OFFSETOF(BS3REGCTX, r12.u64),
573 /* [BS3CG1DST_R13] = */ RT_OFFSETOF(BS3REGCTX, r13.u64),
574 /* [BS3CG1DST_R14] = */ RT_OFFSETOF(BS3REGCTX, r14.u64),
575 /* [BS3CG1DST_R15] = */ RT_OFFSETOF(BS3REGCTX, r15.u64),
576
577 /* [BS3CG1DST_OZ_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax),
578 /* [BS3CG1DST_OZ_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx),
579 /* [BS3CG1DST_OZ_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx),
580 /* [BS3CG1DST_OZ_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx),
581 /* [BS3CG1DST_OZ_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp),
582 /* [BS3CG1DST_OZ_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp),
583 /* [BS3CG1DST_OZ_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi),
584 /* [BS3CG1DST_OZ_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi),
585 /* [BS3CG1DST_OZ_R8] = */ RT_OFFSETOF(BS3REGCTX, r8),
586 /* [BS3CG1DST_OZ_R9] = */ RT_OFFSETOF(BS3REGCTX, r9),
587 /* [BS3CG1DST_OZ_R10] = */ RT_OFFSETOF(BS3REGCTX, r10),
588 /* [BS3CG1DST_OZ_R11] = */ RT_OFFSETOF(BS3REGCTX, r11),
589 /* [BS3CG1DST_OZ_R12] = */ RT_OFFSETOF(BS3REGCTX, r12),
590 /* [BS3CG1DST_OZ_R13] = */ RT_OFFSETOF(BS3REGCTX, r13),
591 /* [BS3CG1DST_OZ_R14] = */ RT_OFFSETOF(BS3REGCTX, r14),
592 /* [BS3CG1DST_OZ_R15] = */ RT_OFFSETOF(BS3REGCTX, r15),
593
594 /* [BS3CG1DST_FCW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FCW),
595 /* [BS3CG1DST_FSW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FSW),
596 /* [BS3CG1DST_FTW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FTW),
597 /* [BS3CG1DST_FOP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FOP),
598 /* [BS3CG1DST_FPUIP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUIP),
599 /* [BS3CG1DST_FPUCS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.CS),
600 /* [BS3CG1DST_FPUDP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUDP),
601 /* [BS3CG1DST_FPUDS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.DS),
602 /* [BS3CG1DST_MXCSR] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.MXCSR),
603 /* [BS3CG1DST_MXCSR_MASK] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.MXCSR_MASK),
604 /* [BS3CG1DST_ST0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
605 /* [BS3CG1DST_ST1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
606 /* [BS3CG1DST_ST2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
607 /* [BS3CG1DST_ST3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
608 /* [BS3CG1DST_ST4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
609 /* [BS3CG1DST_ST5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
610 /* [BS3CG1DST_ST6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
611 /* [BS3CG1DST_ST7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
612 /* [BS3CG1DST_MM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
613 /* [BS3CG1DST_MM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
614 /* [BS3CG1DST_MM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
615 /* [BS3CG1DST_MM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
616 /* [BS3CG1DST_MM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
617 /* [BS3CG1DST_MM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
618 /* [BS3CG1DST_MM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
619 /* [BS3CG1DST_MM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
620
621 /* [BS3CG1DST_XMM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
622 /* [BS3CG1DST_XMM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
623 /* [BS3CG1DST_XMM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
624 /* [BS3CG1DST_XMM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
625 /* [BS3CG1DST_XMM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
626 /* [BS3CG1DST_XMM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
627 /* [BS3CG1DST_XMM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
628 /* [BS3CG1DST_XMM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
629 /* [BS3CG1DST_XMM8] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
630 /* [BS3CG1DST_XMM9] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
631 /* [BS3CG1DST_XMM10] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
632 /* [BS3CG1DST_XMM11] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
633 /* [BS3CG1DST_XMM12] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
634 /* [BS3CG1DST_XMM13] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
635 /* [BS3CG1DST_XMM14] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
636 /* [BS3CG1DST_XMM15] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
637 /* [BS3CG1DST_XMM0_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
638 /* [BS3CG1DST_XMM1_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
639 /* [BS3CG1DST_XMM2_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
640 /* [BS3CG1DST_XMM3_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
641 /* [BS3CG1DST_XMM4_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
642 /* [BS3CG1DST_XMM5_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
643 /* [BS3CG1DST_XMM6_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
644 /* [BS3CG1DST_XMM7_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
645 /* [BS3CG1DST_XMM8_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
646 /* [BS3CG1DST_XMM9_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
647 /* [BS3CG1DST_XMM10_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
648 /* [BS3CG1DST_XMM11_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
649 /* [BS3CG1DST_XMM12_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
650 /* [BS3CG1DST_XMM13_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
651 /* [BS3CG1DST_XMM14_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
652 /* [BS3CG1DST_XMM15_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
653 /* [BS3CG1DST_XMM0_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]) + sizeof(uint64_t),
654 /* [BS3CG1DST_XMM1_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]) + sizeof(uint64_t),
655 /* [BS3CG1DST_XMM2_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]) + sizeof(uint64_t),
656 /* [BS3CG1DST_XMM3_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]) + sizeof(uint64_t),
657 /* [BS3CG1DST_XMM4_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]) + sizeof(uint64_t),
658 /* [BS3CG1DST_XMM5_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]) + sizeof(uint64_t),
659 /* [BS3CG1DST_XMM6_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]) + sizeof(uint64_t),
660 /* [BS3CG1DST_XMM7_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]) + sizeof(uint64_t),
661 /* [BS3CG1DST_XMM8_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]) + sizeof(uint64_t),
662 /* [BS3CG1DST_XMM9_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]) + sizeof(uint64_t),
663 /* [BS3CG1DST_XMM10_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]) + sizeof(uint64_t),
664 /* [BS3CG1DST_XMM11_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]) + sizeof(uint64_t),
665 /* [BS3CG1DST_XMM12_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]) + sizeof(uint64_t),
666 /* [BS3CG1DST_XMM13_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]) + sizeof(uint64_t),
667 /* [BS3CG1DST_XMM14_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]) + sizeof(uint64_t),
668 /* [BS3CG1DST_XMM15_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) + sizeof(uint64_t),
669
670 /* [BS3CG1DST_YMM0] = */ ~0U,
671 /* [BS3CG1DST_YMM1] = */ ~0U,
672 /* [BS3CG1DST_YMM2] = */ ~0U,
673 /* [BS3CG1DST_YMM3] = */ ~0U,
674 /* [BS3CG1DST_YMM4] = */ ~0U,
675 /* [BS3CG1DST_YMM5] = */ ~0U,
676 /* [BS3CG1DST_YMM6] = */ ~0U,
677 /* [BS3CG1DST_YMM7] = */ ~0U,
678 /* [BS3CG1DST_YMM8] = */ ~0U,
679 /* [BS3CG1DST_YMM9] = */ ~0U,
680 /* [BS3CG1DST_YMM10] = */ ~0U,
681 /* [BS3CG1DST_YMM11] = */ ~0U,
682 /* [BS3CG1DST_YMM12] = */ ~0U,
683 /* [BS3CG1DST_YMM13] = */ ~0U,
684 /* [BS3CG1DST_YMM14] = */ ~0U,
685 /* [BS3CG1DST_YMM15] = */ ~0U,
686
687 /* [BS3CG1DST_VALUE_XCPT] = */ ~0U,
688};
689AssertCompile(RT_ELEMENTS(g_aoffBs3Cg1DstFields) == BS3CG1DST_END);
690
691#ifdef BS3CG1_DEBUG_CTX_MOD
692/** Destination field names. */
693static const struct { char sz[8]; } g_aszBs3Cg1DstFields[] =
694{
695 { "INVALID" },
696 { "OP1" },
697 { "OP2" },
698 { "OP3" },
699 { "OP4" },
700 { "EFL" },
701 { "EFL_UND" },
702
703 { "AL" },
704 { "CL" },
705 { "DL" },
706 { "BL" },
707 { "AH" },
708 { "CH" },
709 { "DH" },
710 { "BH" },
711 { "SPL" },
712 { "BPL" },
713 { "SIL" },
714 { "DIL" },
715 { "R8L" },
716 { "R9L" },
717 { "R10L" },
718 { "R11L" },
719 { "R12L" },
720 { "R13L" },
721 { "R14L" },
722 { "R15L" },
723
724 { "AX" },
725 { "CX" },
726 { "DX" },
727 { "BX" },
728 { "SP" },
729 { "BP" },
730 { "SI" },
731 { "DI" },
732 { "R8W" },
733 { "R9W" },
734 { "R10W" },
735 { "R11W" },
736 { "R12W" },
737 { "R13W" },
738 { "R14W" },
739 { "R15W" },
740
741 { "EAX" },
742 { "ECX" },
743 { "EDX" },
744 { "EBX" },
745 { "ESP" },
746 { "EBP" },
747 { "ESI" },
748 { "EDI" },
749 { "R8D" },
750 { "R9D" },
751 { "R10D" },
752 { "R11D" },
753 { "R12D" },
754 { "R13D" },
755 { "R14D" },
756 { "R15D" },
757
758 { "RAX" },
759 { "RCX" },
760 { "RDX" },
761 { "RBX" },
762 { "RSP" },
763 { "RBP" },
764 { "RSI" },
765 { "RDI" },
766 { "R8" },
767 { "R9" },
768 { "R10" },
769 { "R11" },
770 { "R12" },
771 { "R13" },
772 { "R14" },
773 { "R15" },
774
775 { "OZ_RAX" },
776 { "OZ_RCX" },
777 { "OZ_RDX" },
778 { "OZ_RBX" },
779 { "OZ_RSP" },
780 { "OZ_RBP" },
781 { "OZ_RSI" },
782 { "OZ_RDI" },
783 { "OZ_R8" },
784 { "OZ_R9" },
785 { "OZ_R10" },
786 { "OZ_R11" },
787 { "OZ_R12" },
788 { "OZ_R13" },
789 { "OZ_R14" },
790 { "OZ_R15" },
791
792 { "FCW" },
793 { "FSW" },
794 { "FTW" },
795 { "FOP" },
796 { "FPUIP" },
797 { "FPUCS" },
798 { "FPUDP" },
799 { "FPUDS" },
800 { "MXCSR" },
801 { "MXCSR_M" },
802 { "ST0" },
803 { "ST1" },
804 { "ST2" },
805 { "ST3" },
806 { "ST4" },
807 { "ST5" },
808 { "ST6" },
809 { "ST7" },
810 { "MM0" },
811 { "MM1" },
812 { "MM2" },
813 { "MM3" },
814 { "MM4" },
815 { "MM5" },
816 { "MM6" },
817 { "MM7" },
818 { "XMM0" },
819 { "XMM1" },
820 { "XMM2" },
821 { "XMM3" },
822 { "XMM4" },
823 { "XMM5" },
824 { "XMM6" },
825 { "XMM7" },
826 { "XMM8" },
827 { "XMM9" },
828 { "XMM10" },
829 { "XMM11" },
830 { "XMM12" },
831 { "XMM13" },
832 { "XMM14" },
833 { "XMM15" },
834 { "XMM0_LO" },
835 { "XMM1_LO" },
836 { "XMM2_LO" },
837 { "XMM3_LO" },
838 { "XMM4_LO" },
839 { "XMM5_LO" },
840 { "XMM6_LO" },
841 { "XMM7_LO" },
842 { "XMM8_LO" },
843 { "XMM9_LO" },
844 { "XMM10_LO" },
845 { "XMM11_LO" },
846 { "XMM12_LO" },
847 { "XMM13_LO" },
848 { "XMM14_LO" },
849 { "XMM15_LO" },
850 { "XMM0_HI" },
851 { "XMM1_HI" },
852 { "XMM2_HI" },
853 { "XMM3_HI" },
854 { "XMM4_HI" },
855 { "XMM5_HI" },
856 { "XMM6_HI" },
857 { "XMM7_HI" },
858 { "XMM8_HI" },
859 { "XMM9_HI" },
860 { "XMM10_HI" },
861 { "XMM11_HI" },
862 { "XMM12_HI" },
863 { "XMM13_HI" },
864 { "XMM14_HI" },
865 { "XMM15_HI" },
866 { "YMM0" },
867 { "YMM1" },
868 { "YMM2" },
869 { "YMM3" },
870 { "YMM4" },
871 { "YMM5" },
872 { "YMM6" },
873 { "YMM7" },
874 { "YMM8" },
875 { "YMM9" },
876 { "YMM10" },
877 { "YMM11" },
878 { "YMM12" },
879 { "YMM13" },
880 { "YMM14" },
881 { "YMM15" },
882
883 { "VALXCPT" },
884};
885AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) == BS3CG1DST_END);
886
887#endif
888
889#if 0
890static const struct
891{
892 uint8_t cbPrefixes;
893 uint8_t abPrefixes[14];
894 uint16_t fEffective;
895} g_aPrefixVariations[] =
896{
897 { 0, { 0x00 }, BS3CG1_PF_NONE },
898
899 { 1, { P_OZ }, BS3CG1_PF_OZ },
900 { 1, { P_CS }, BS3CG1_PF_CS },
901 { 1, { P_DS }, BS3CG1_PF_DS },
902 { 1, { P_ES }, BS3CG1_PF_ES },
903 { 1, { P_FS }, BS3CG1_PF_FS },
904 { 1, { P_GS }, BS3CG1_PF_GS },
905 { 1, { P_SS }, BS3CG1_PF_SS },
906 { 1, { P_LK }, BS3CG1_PF_LK },
907
908 { 2, { P_CS, P_OZ, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
909 { 2, { P_DS, P_OZ, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
910 { 2, { P_ES, P_OZ, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
911 { 2, { P_FS, P_OZ, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
912 { 2, { P_GS, P_OZ, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
913 { 2, { P_GS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
914 { 2, { P_SS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
915
916 { 2, { P_OZ, P_CS, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
917 { 2, { P_OZ, P_DS, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
918 { 2, { P_OZ, P_ES, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
919 { 2, { P_OZ, P_FS, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
920 { 2, { P_OZ, P_GS, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
921 { 2, { P_OZ, P_GS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
922 { 2, { P_OZ, P_SS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
923};
924
925static const uint16_t g_afPfxKindToIgnoredFlags[BS3CG1PFXKIND_END] =
926{
927 /* [BS3CG1PFXKIND_INVALID] = */ UINT16_MAX,
928 /* [BS3CG1PFXKIND_MODRM] = */ 0,
929 /* [BS3CG1PFXKIND_MODRM_NO_OP_SIZES] = */ BS3CG1_PF_OZ | BS3CG1_PF_W,
930};
931
932#endif
933
934
935/**
936 * Checks if >= 16 byte SSE/AVX alignment are exempted for the exception type.
937 *
938 * @returns true / false.
939 * @param enmXcptType The type to check.
940 */
941static bool Bs3Cg1XcptTypeIsUnaligned(BS3CG1XCPTTYPE enmXcptType)
942{
943 switch (enmXcptType)
944 {
945 case BS3CG1XCPTTYPE_4UA:
946 case BS3CG1XCPTTYPE_5:
947 return true;
948 default:
949 return false;
950 }
951}
952
953
954DECLINLINE(unsigned) Bs3Cg1InsertReqPrefix(PBS3CG1STATE pThis, unsigned offDst)
955{
956 switch (pThis->enmPrefixKind)
957 {
958 case BS3CG1PFXKIND_REQ_66:
959 pThis->abCurInstr[offDst] = 0x66;
960 break;
961 case BS3CG1PFXKIND_REQ_F2:
962 pThis->abCurInstr[offDst] = 0xf2;
963 break;
964 case BS3CG1PFXKIND_REQ_F3:
965 pThis->abCurInstr[offDst] = 0xf3;
966 break;
967 default:
968 return offDst;
969 }
970 return offDst + 1;
971}
972
973
974DECLINLINE(unsigned) Bs3Cg1InsertOpcodes(PBS3CG1STATE pThis, unsigned offDst)
975{
976 switch (pThis->cbOpcodes)
977 {
978 case 4: pThis->abCurInstr[offDst + 3] = pThis->abOpcodes[3];
979 case 3: pThis->abCurInstr[offDst + 2] = pThis->abOpcodes[2];
980 case 2: pThis->abCurInstr[offDst + 1] = pThis->abOpcodes[1];
981 case 1: pThis->abCurInstr[offDst] = pThis->abOpcodes[0];
982 return offDst + pThis->cbOpcodes;
983
984 default:
985 BS3_ASSERT(0);
986 return 0;
987 }
988}
989
990
991/**
992 * Cleans up state and context changes made by the encoder.
993 *
994 * @param pThis The state.
995 */
996static void Bs3Cg1EncodeCleanup(PBS3CG1STATE pThis)
997{
998 /* Restore the DS registers in the contexts. */
999 unsigned iRing = 4;
1000 while (iRing-- > 0)
1001 pThis->aInitialCtxs[iRing].ds = pThis->aSavedSegRegs[iRing].ds;
1002
1003 switch (pThis->enmEncoding)
1004 {
1005 /* Most encodings currently doesn't need any special cleaning up. */
1006 default:
1007 return;
1008 }
1009}
1010
1011
1012static unsigned Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
1013 uint8_t cbOp, uint8_t cbMissalign, BS3CG1OPLOC enmLocation)
1014{
1015 pThis->aOperands[pThis->iRmOp].idxField = BS3CG1DST_INVALID;
1016 pThis->aOperands[pThis->iRmOp].enmLocation = enmLocation;
1017 pThis->aOperands[pThis->iRmOp].cbOp = cbOp;
1018 pThis->aOperands[pThis->iRmOp].off = cbOp + cbMissalign;
1019
1020 if ( BS3_MODE_IS_16BIT_CODE(pThis->bMode)
1021 || (fAddrOverride && BS3_MODE_IS_32BIT_CODE(pThis->bMode)) )
1022 {
1023 /*
1024 * 16-bit code doing 16-bit or 32-bit addressing,
1025 * or 32-bit code doing 16-bit addressing.
1026 */
1027 unsigned iRing = 4;
1028 if (BS3_MODE_IS_RM_OR_V86(pThis->bMode))
1029 while (iRing-- > 0)
1030 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel;
1031 else
1032 while (iRing-- > 0)
1033 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel | iRing;
1034 if (!fAddrOverride || BS3_MODE_IS_32BIT_CODE(pThis->bMode))
1035 {
1036 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 6 /*disp16*/);
1037 *(uint16_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
1038 off += 2;
1039 }
1040 else
1041 {
1042 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1043 *(uint32_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
1044 off += 4;
1045 }
1046 }
1047 else
1048 {
1049 /*
1050 * 32-bit code doing 32-bit addressing,
1051 * or 64-bit code doing either 64-bit or 32-bit addressing.
1052 */
1053 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1054 *(uint32_t *)&pThis->abCurInstr[off] = BS3_FP_OFF(pThis->pbDataPg) + X86_PAGE_SIZE - cbOp - cbMissalign;
1055
1056 /* In 64-bit mode we always have a rip relative encoding regardless of fAddrOverride. */
1057 if (BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1058 *(uint32_t *)&pThis->abCurInstr[off] -= BS3_FP_OFF(&pThis->pbCodePg[X86_PAGE_SIZE]);
1059 off += 4;
1060 }
1061
1062 return off;
1063}
1064
1065
1066/**
1067 * Encodes the next instruction.
1068 *
1069 * @returns Next iEncoding value. Returns @a iEncoding unchanged to indicate
1070 * that there are no more encodings to test.
1071 * @param pThis The state.
1072 * @param iEncoding The encoding to produce. Meaning is specific to each
1073 * BS3CG1ENC_XXX value and should be considered internal.
1074 */
1075static unsigned Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEncoding)
1076{
1077 unsigned off;
1078 unsigned cbOp;
1079
1080 pThis->bAlignmentXcpt = UINT8_MAX;
1081
1082 switch (pThis->enmEncoding)
1083 {
1084 case BS3CG1ENC_MODRM_Eb_Gb:
1085 /* Start by reg,reg encoding. */
1086 if (iEncoding == 0)
1087 {
1088 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1089 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xAX, X86_GREG_xCX);
1090 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_AL;
1091 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_CL;
1092 }
1093 else if (iEncoding == 1)
1094 {
1095 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_CH;
1096 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1097 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, 1, 0, BS3CG1OPLOC_MEM_RW);
1098 }
1099 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1100 {
1101 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_BH;
1102 pThis->abCurInstr[0] = P_AZ;
1103 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1104 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, 1, 0, BS3CG1OPLOC_MEM_RW);
1105 }
1106 else
1107 break;
1108 pThis->cbCurInstr = off;
1109 iEncoding++;
1110 break;
1111
1112 case BS3CG1ENC_MODRM_Gb_Eb:
1113 /* Start by reg,reg encoding. */
1114 if (iEncoding == 0)
1115 {
1116 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1117 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xAX, X86_GREG_xCX);
1118 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_AL;
1119 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_CL;
1120 }
1121 else if (iEncoding == 1)
1122 {
1123 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_CH;
1124 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1125 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, 1, 0, BS3CG1OPLOC_MEM);
1126 }
1127 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1128 {
1129 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_BH;
1130 pThis->abCurInstr[0] = P_AZ;
1131 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1132 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, 1, 0, BS3CG1OPLOC_MEM);
1133 }
1134 else
1135 break;
1136 pThis->cbCurInstr = off;
1137 iEncoding++;
1138 break;
1139
1140 case BS3CG1ENC_MODRM_Gv_Ev:
1141 case BS3CG1ENC_MODRM_Ev_Gv:
1142 if (iEncoding == 0)
1143 {
1144 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1145 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1146 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1147 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBX;
1148 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_OZ_RDX;
1149 }
1150 else if (iEncoding == 1)
1151 {
1152 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1153 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1154 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1155 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp, 0,
1156 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1157 }
1158 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1159 {
1160 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1161 pThis->abCurInstr[0] = P_OZ;
1162 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1163 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1164 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBX;
1165 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_OZ_RDX;
1166 pThis->aOperands[pThis->iRmOp ].enmLocation = BS3CG1OPLOC_CTX;
1167 }
1168 else if (iEncoding == 3)
1169 {
1170 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1171 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RSI;
1172 pThis->abCurInstr[0] = P_OZ;
1173 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1174 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xSI, cbOp, 0,
1175 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1176 }
1177 else if (iEncoding == 4)
1178 {
1179 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1180 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RDI;
1181 pThis->abCurInstr[0] = P_AZ;
1182 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1183 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, cbOp, 0,
1184 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1185 }
1186 else if (iEncoding == 5)
1187 {
1188 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1189 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RSI;
1190 pThis->abCurInstr[0] = P_OZ;
1191 pThis->abCurInstr[1] = P_AZ;
1192 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
1193 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xSI, cbOp, 0,
1194 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1195 }
1196 else if (iEncoding == 6 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1197 {
1198 cbOp = 8;
1199 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1200 pThis->abCurInstr[off++] = REX_W___;
1201 off = Bs3Cg1InsertOpcodes(pThis, off);
1202 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1203 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_RBX;
1204 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_RDX;
1205 pThis->aOperands[pThis->iRmOp ].enmLocation = BS3CG1OPLOC_CTX;
1206 }
1207 else
1208 break;
1209 pThis->aOperands[0].cbOp = cbOp;
1210 pThis->aOperands[1].cbOp = cbOp;
1211 pThis->cbOperand = cbOp;
1212 pThis->cbCurInstr = off;
1213 iEncoding++;
1214 break;
1215
1216 case BS3CG1ENC_MODRM_Wsd_Vsd:
1217 if (iEncoding == 0)
1218 {
1219 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1220 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1221 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
1222 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO;
1223 }
1224 else if (iEncoding == 1)
1225 {
1226 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
1227 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1228 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_RW);
1229 }
1230 else if (iEncoding == 2)
1231 {
1232 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
1233 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1234 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1235 }
1236 else
1237 break;
1238 pThis->cbCurInstr = off;
1239 iEncoding++;
1240 break;
1241
1242 case BS3CG1ENC_MODRM_Wps_Vps:
1243 if (iEncoding == 0)
1244 {
1245 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1246 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1247 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
1248 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
1249 }
1250 else if (iEncoding == 1)
1251 {
1252 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
1253 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1254 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM_RW);
1255 }
1256 else if (iEncoding == 2)
1257 {
1258 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
1259 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1260 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1261 if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
1262 pThis->bAlignmentXcpt = X86_XCPT_GP;
1263 }
1264 else
1265 break;
1266 pThis->cbCurInstr = off;
1267 iEncoding++;
1268 break;
1269
1270
1271 case BS3CG1ENC_MODRM_Gv_Ma:
1272 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1273 if (iEncoding == 0)
1274 {
1275 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1276 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1277 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1278 }
1279 else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1280 {
1281 cbOp = cbOp == 2 ? 4 : 2;
1282 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1283 pThis->abCurInstr[0] = P_OZ;
1284 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1285 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1286 }
1287 else if (iEncoding == 2)
1288 {
1289 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1290 pThis->abCurInstr[0] = P_AZ;
1291 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1292 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1293 }
1294 else if (iEncoding == 3)
1295 {
1296 cbOp = cbOp == 2 ? 4 : 2;
1297 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1298 pThis->abCurInstr[0] = P_AZ;
1299 pThis->abCurInstr[1] = P_OZ;
1300 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
1301 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1302 }
1303 else
1304 break;
1305 pThis->aOperands[pThis->iRegOp].cbOp = cbOp;
1306 pThis->cbOperand = cbOp;
1307 pThis->cbCurInstr = off;
1308 iEncoding++;
1309 break;
1310
1311 case BS3CG1ENC_FIXED:
1312 if (iEncoding == 0)
1313 {
1314 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1315 pThis->cbCurInstr = off;
1316 iEncoding++;
1317 }
1318 break;
1319
1320 case BS3CG1ENC_FIXED_AL_Ib:
1321 if (iEncoding == 0)
1322 {
1323 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1324 pThis->aOperands[1].off = (uint8_t)off;
1325 pThis->abCurInstr[off++] = 0xff;
1326 pThis->cbCurInstr = off;
1327 iEncoding++;
1328 }
1329 break;
1330
1331 case BS3CG1ENC_FIXED_rAX_Iz:
1332 if (iEncoding == 0)
1333 {
1334 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1335 pThis->aOperands[1].off = (uint8_t)off;
1336 if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
1337 {
1338 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
1339 off += 2;
1340 pThis->aOperands[0].cbOp = 2;
1341 pThis->aOperands[1].cbOp = 2;
1342 pThis->cbOperand = 2;
1343 }
1344 else
1345 {
1346 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1347 off += 4;
1348 pThis->aOperands[0].cbOp = 4;
1349 pThis->aOperands[1].cbOp = 4;
1350 pThis->cbOperand = 4;
1351 }
1352 }
1353 else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1354 {
1355 pThis->abCurInstr[0] = P_OZ;
1356 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1357 pThis->aOperands[1].off = (uint8_t)off;
1358 if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
1359 {
1360 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
1361 off += 2;
1362 pThis->aOperands[0].cbOp = 2;
1363 pThis->aOperands[1].cbOp = 2;
1364 pThis->cbOperand = 2;
1365 }
1366 else
1367 {
1368 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1369 off += 4;
1370 pThis->aOperands[0].cbOp = 4;
1371 pThis->aOperands[1].cbOp = 4;
1372 pThis->cbOperand = 4;
1373 }
1374 }
1375 else if (iEncoding == 2 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1376 {
1377 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1378 pThis->abCurInstr[off++] = REX_W___;
1379 off = Bs3Cg1InsertOpcodes(pThis, off);
1380 pThis->aOperands[1].off = (uint8_t)off;
1381 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1382 off += 4;
1383 pThis->aOperands[0].cbOp = 8;
1384 pThis->aOperands[1].cbOp = 4;
1385 pThis->cbOperand = 8;
1386 }
1387 else
1388 break;
1389 pThis->cbCurInstr = off;
1390 iEncoding++;
1391 break;
1392
1393 default:
1394 Bs3TestFailedF("Internal error! BS3CG1ENC_XXX = %u not implemented", pThis->enmEncoding);
1395 break;
1396 }
1397
1398
1399 return iEncoding;
1400}
1401
1402
1403/**
1404 * Prepares doing instruction encodings.
1405 *
1406 * This is in part specific to how the instruction is encoded, but generally it
1407 * sets up basic operand values that doesn't change (much) when Bs3Cg1EncodeNext
1408 * is called from within the loop.
1409 *
1410 * @returns Success indicator (true/false).
1411 * @param pThis The state.
1412 */
1413static bool Bs3Cg1EncodePrep(PBS3CG1STATE pThis)
1414{
1415 unsigned iRing = 4;
1416 while (iRing-- > 0)
1417 pThis->aSavedSegRegs[iRing].ds = pThis->aInitialCtxs[iRing].ds;
1418
1419 pThis->iRmOp = RT_ELEMENTS(pThis->aOperands) - 1;
1420 pThis->iRegOp = RT_ELEMENTS(pThis->aOperands) - 1;
1421 pThis->fSameRingNotOkay = false;
1422 pThis->cbOperand = 0;
1423
1424 switch (pThis->enmEncoding)
1425 {
1426 case BS3CG1ENC_MODRM_Eb_Gb:
1427 pThis->iRmOp = 0;
1428 pThis->iRegOp = 1;
1429 pThis->aOperands[0].cbOp = 1;
1430 pThis->aOperands[1].cbOp = 1;
1431 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1432 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1433 break;
1434
1435 case BS3CG1ENC_MODRM_Ev_Gv:
1436 pThis->iRmOp = 0;
1437 pThis->iRegOp = 1;
1438 pThis->cbOperand = 2;
1439 pThis->aOperands[0].cbOp = 2;
1440 pThis->aOperands[1].cbOp = 2;
1441 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1442 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1443 break;
1444
1445 case BS3CG1ENC_MODRM_Gb_Eb:
1446 pThis->iRmOp = 1;
1447 pThis->iRegOp = 0;
1448 pThis->aOperands[0].cbOp = 1;
1449 pThis->aOperands[1].cbOp = 1;
1450 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1451 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1452 break;
1453
1454 case BS3CG1ENC_MODRM_Gv_Ev:
1455 pThis->iRmOp = 1;
1456 pThis->iRegOp = 0;
1457 pThis->cbOperand = 2;
1458 pThis->aOperands[0].cbOp = 2;
1459 pThis->aOperands[1].cbOp = 2;
1460 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1461 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1462 break;
1463
1464 case BS3CG1ENC_MODRM_Gv_Ma:
1465 pThis->iRmOp = 1;
1466 pThis->iRegOp = 0;
1467 pThis->cbOperand = 2;
1468 pThis->aOperands[0].cbOp = 2;
1469 pThis->aOperands[1].cbOp = 4;
1470 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1471 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
1472 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1473 break;
1474
1475 case BS3CG1ENC_MODRM_Wsd_Vsd:
1476 pThis->iRmOp = 0;
1477 pThis->iRegOp = 1;
1478 pThis->aOperands[0].cbOp = 8;
1479 pThis->aOperands[1].cbOp = 8;
1480 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1481 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1482 break;
1483
1484 case BS3CG1ENC_MODRM_Wps_Vps:
1485 pThis->iRmOp = 0;
1486 pThis->iRegOp = 1;
1487 pThis->aOperands[0].cbOp = 16;
1488 pThis->aOperands[1].cbOp = 16;
1489 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1490 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1491 break;
1492
1493 case BS3CG1ENC_FIXED:
1494 /* nothing to do here */
1495 break;
1496
1497 case BS3CG1ENC_FIXED_AL_Ib:
1498 pThis->aOperands[0].cbOp = 1;
1499 pThis->aOperands[1].cbOp = 1;
1500 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1501 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
1502 pThis->aOperands[0].idxField = BS3CG1DST_AL;
1503 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1504 break;
1505
1506 case BS3CG1ENC_FIXED_rAX_Iz:
1507 pThis->aOperands[0].cbOp = 2;
1508 pThis->aOperands[1].cbOp = 2;
1509 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1510 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
1511 pThis->aOperands[0].idxField = BS3CG1DST_OZ_RAX;
1512 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1513 break;
1514
1515 default:
1516 return Bs3TestFailedF("Invalid/unimplemented enmEncoding for instruction #%RU32 (%.*s): %d",
1517 pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic, pThis->enmEncoding);
1518 }
1519 return true;
1520}
1521
1522
1523/**
1524 * Sets up SSE and maybe AVX.
1525 *
1526 * @returns true (if successful, false if not and the SSE instructions ends up
1527 * being invalid).
1528 * @param pThis The state.
1529 */
1530static bool Bs3Cg3SetupSseAndAvx(PBS3CG1STATE pThis)
1531{
1532 if (!pThis->fWorkExtCtx)
1533 {
1534 unsigned i;
1535 uint32_t cr0 = ASMGetCR0();
1536 uint32_t cr4 = ASMGetCR4();
1537
1538 cr0 &= ~(X86_CR0_TS | X86_CR0_MP | X86_CR0_EM);
1539 cr0 |= X86_CR0_NE;
1540 ASMSetCR0(cr0);
1541 if (pThis->pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
1542 {
1543 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE;
1544 ASMSetCR4(cr4);
1545 ASMSetXcr0(pThis->pExtCtx->fXcr0);
1546 }
1547 else
1548 {
1549 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT;
1550 ASMSetCR4(cr4);
1551 }
1552
1553 for (i = 0; i < RT_ELEMENTS(pThis->aInitialCtxs); i++)
1554 {
1555 pThis->aInitialCtxs[i].cr0.u32 = cr0;
1556 pThis->aInitialCtxs[i].cr4.u32 = cr4;
1557 }
1558 pThis->fWorkExtCtx = true;
1559 }
1560
1561 return true;
1562}
1563
1564
1565/**
1566 * Next CPU configuration to test the current instruction in.
1567 *
1568 * This is for testing FPU, SSE and AVX instructions with the various lazy state
1569 * load and enable bits in different configurations to ensure we're getting the
1570 * right response.
1571 *
1572 * This also cleans up the CPU and test driver state.
1573 *
1574 * @returns true if we're to do another round, false if we're done.
1575 * @param pThis The state.
1576 * @param iCpuSetup The current CPU setup number.
1577 * @param pfInvalidInstr Where to indicate whether the setup causes an
1578 * invalid instruction or not. This is also used as
1579 * input to avoid unnecessary CPUID work.
1580 */
1581static bool Bs3Cg1CpuSetupNext(PBS3CG1STATE pThis, unsigned iCpuSetup, bool *pfInvalidInstr)
1582{
1583 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
1584 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1585 return false;
1586
1587 switch (pThis->enmCpuTest)
1588 {
1589 case BS3CG1CPU_ANY:
1590 case BS3CG1CPU_GE_80186:
1591 case BS3CG1CPU_GE_80286:
1592 case BS3CG1CPU_GE_80386:
1593 case BS3CG1CPU_GE_80486:
1594 case BS3CG1CPU_GE_Pentium:
1595 return false;
1596
1597 case BS3CG1CPU_SSE:
1598 case BS3CG1CPU_SSE2:
1599 case BS3CG1CPU_SSE3:
1600 case BS3CG1CPU_AVX:
1601 case BS3CG1CPU_AVX2:
1602 if (iCpuSetup > 0 || *pfInvalidInstr)
1603 {
1604 /** @todo do more configs here. */
1605 pThis->fWorkExtCtx = false;
1606 ASMSetCR0(ASMGetCR0() | X86_CR0_EM | X86_CR0_MP);
1607 ASMSetCR4(ASMGetCR4() & ~(X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE));
1608 return false;
1609 }
1610 return false;
1611
1612 default:
1613 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
1614 return false;
1615 }
1616}
1617
1618
1619/**
1620 * Check if the instruction is supported by the CPU, possibly making state
1621 * adjustments to enable support for it.
1622 *
1623 * @returns true if supported, false if not.
1624 * @param pThis The state.
1625 */
1626static bool Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
1627{
1628 uint32_t fEax;
1629 uint32_t fEbx;
1630 uint32_t fEcx;
1631 uint32_t fEdx;
1632
1633 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
1634 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1635 return false;
1636
1637 switch (pThis->enmCpuTest)
1638 {
1639 case BS3CG1CPU_ANY:
1640 return true;
1641
1642 case BS3CG1CPU_GE_80186:
1643 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80186)
1644 return true;
1645 return false;
1646
1647 case BS3CG1CPU_GE_80286:
1648 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80286)
1649 return true;
1650 return false;
1651
1652 case BS3CG1CPU_GE_80386:
1653 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1654 return true;
1655 return false;
1656
1657 case BS3CG1CPU_GE_80486:
1658 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486)
1659 return true;
1660 return false;
1661
1662 case BS3CG1CPU_GE_Pentium:
1663 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_Pentium)
1664 return true;
1665 return false;
1666
1667 case BS3CG1CPU_SSE:
1668 case BS3CG1CPU_SSE2:
1669 case BS3CG1CPU_SSE3:
1670 case BS3CG1CPU_AVX:
1671 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1672 {
1673 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, &fEdx);
1674 switch (pThis->enmCpuTest)
1675 {
1676 case BS3CG1CPU_SSE:
1677 if (fEdx & X86_CPUID_FEATURE_EDX_SSE)
1678 return Bs3Cg3SetupSseAndAvx(pThis);
1679 return false;
1680 case BS3CG1CPU_SSE2:
1681 if (fEdx & X86_CPUID_FEATURE_EDX_SSE2)
1682 return Bs3Cg3SetupSseAndAvx(pThis);
1683 return false;
1684 case BS3CG1CPU_SSE3:
1685 if (fEcx & X86_CPUID_FEATURE_ECX_SSE3)
1686 return Bs3Cg3SetupSseAndAvx(pThis);
1687 return false;
1688 case BS3CG1CPU_AVX:
1689 if (fEcx & X86_CPUID_FEATURE_ECX_AVX)
1690 return Bs3Cg3SetupSseAndAvx(pThis);
1691 return false;
1692 default: BS3_ASSERT(0); /* impossible */
1693 }
1694 }
1695 return false;
1696
1697 case BS3CG1CPU_AVX2:
1698 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1699 {
1700 ASMCpuIdExSlow(7, 0, 0/*leaf*/, 0, &fEax, &fEbx, &fEcx, &fEdx);
1701
1702 switch (pThis->enmCpuTest)
1703 {
1704 case BS3CG1CPU_AVX2:
1705 if (fEbx & X86_CPUID_STEXT_FEATURE_EBX_AVX2)
1706 return Bs3Cg3SetupSseAndAvx(pThis);
1707 return false;
1708 default: BS3_ASSERT(0); return false; /* impossible */
1709 }
1710 }
1711 return false;
1712
1713 default:
1714 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
1715 return false;
1716 }
1717}
1718
1719
1720
1721/**
1722 * Checks the preconditions for a test.
1723 *
1724 * @returns true if the test be executed, false if not.
1725 * @param pThis The state.
1726 * @param pHdr The test header.
1727 */
1728static bool Bs3Cg1RunSelector(PBS3CG1STATE pThis, PCBS3CG1TESTHDR pHdr)
1729{
1730
1731 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1);
1732 unsigned cbLeft = pHdr->cbSelector;
1733 while (cbLeft-- > 0)
1734 {
1735 switch (*pbCode++)
1736 {
1737#define CASE_PRED(a_Pred, a_Expr) \
1738 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_TRUE: \
1739 if (!(a_Expr)) return false; \
1740 break; \
1741 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_FALSE: \
1742 if (a_Expr) return false; \
1743 break
1744 CASE_PRED(BS3CG1PRED_SIZE_O16, pThis->cbOperand == 2);
1745 CASE_PRED(BS3CG1PRED_SIZE_O32, pThis->cbOperand == 4);
1746 CASE_PRED(BS3CG1PRED_SIZE_O64, pThis->cbOperand == 8);
1747 CASE_PRED(BS3CG1PRED_RING_0, pThis->uCpl == 0);
1748 CASE_PRED(BS3CG1PRED_RING_1, pThis->uCpl == 1);
1749 CASE_PRED(BS3CG1PRED_RING_2, pThis->uCpl == 2);
1750 CASE_PRED(BS3CG1PRED_RING_3, pThis->uCpl == 3);
1751 CASE_PRED(BS3CG1PRED_RING_0_THRU_2, pThis->uCpl <= 2);
1752 CASE_PRED(BS3CG1PRED_RING_1_THRU_3, pThis->uCpl >= 1);
1753 CASE_PRED(BS3CG1PRED_CODE_64BIT, BS3_MODE_IS_64BIT_CODE(pThis->bMode));
1754 CASE_PRED(BS3CG1PRED_CODE_32BIT, BS3_MODE_IS_32BIT_CODE(pThis->bMode));
1755 CASE_PRED(BS3CG1PRED_CODE_16BIT, BS3_MODE_IS_16BIT_CODE(pThis->bMode));
1756 CASE_PRED(BS3CG1PRED_MODE_REAL, BS3_MODE_IS_RM_SYS(pThis->bMode));
1757 CASE_PRED(BS3CG1PRED_MODE_PROT, BS3_MODE_IS_PM_SYS(pThis->bMode));
1758 CASE_PRED(BS3CG1PRED_MODE_LONG, BS3_MODE_IS_64BIT_SYS(pThis->bMode));
1759 CASE_PRED(BS3CG1PRED_MODE_SMM, false);
1760 CASE_PRED(BS3CG1PRED_MODE_VMX, false);
1761 CASE_PRED(BS3CG1PRED_MODE_SVM, false);
1762 CASE_PRED(BS3CG1PRED_PAGING_ON, BS3_MODE_IS_PAGED(pThis->bMode));
1763 CASE_PRED(BS3CG1PRED_PAGING_OFF, !BS3_MODE_IS_PAGED(pThis->bMode));
1764
1765#undef CASE_PRED
1766 default:
1767 return Bs3TestFailedF("Invalid selector opcode %#x!", pbCode[-1]);
1768 }
1769 }
1770
1771 return true;
1772}
1773
1774
1775#ifdef BS3CG1_DEBUG_CTX_MOD
1776/**
1777 * Translates the operator into a string.
1778 *
1779 * @returns Read-only string pointer.
1780 * @param bOpcode The context modifier program opcode.
1781 */
1782static const char BS3_FAR *Bs3Cg1CtxOpToString(uint8_t bOpcode)
1783{
1784 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
1785 {
1786 case BS3CG1_CTXOP_ASSIGN: return "=";
1787 case BS3CG1_CTXOP_OR: return "|=";
1788 case BS3CG1_CTXOP_AND: return "&=";
1789 case BS3CG1_CTXOP_AND_INV: return "&~=";
1790 }
1791}
1792#endif
1793
1794
1795/**
1796 * Runs a context modifier program.
1797 *
1798 * @returns Success indicator (true/false).
1799 * @param pThis The state.
1800 * @param pCtx The context.
1801 * @param pHdr The program header.
1802 * @param off The program offset relative to the end of the header.
1803 * @param cb The program size.
1804 * @param pEflCtx The context to take undefined EFLAGS from. (This is NULL
1805 * if we're processing a input context modifier program.)
1806 * @param pbInstr Points to the first instruction byte. For storing
1807 * immediate operands during input context modification.
1808 * NULL for output contexts.
1809 */
1810static bool Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCTX pCtx, PCBS3CG1TESTHDR pHdr, unsigned off, unsigned cb,
1811 PCBS3REGCTX pEflCtx, uint8_t BS3_FAR *pbInstr)
1812{
1813 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1) + off;
1814 int cbLeft = cb;
1815 while (cbLeft-- > 0)
1816 {
1817 /*
1818 * Decode the instruction.
1819 */
1820 uint8_t const bOpcode = *pbCode++;
1821 unsigned cbValue;
1822 unsigned cbDst;
1823 BS3CG1DST idxField;
1824 BS3PTRUNION PtrField;
1825
1826 /* Expand the destiation field (can be escaped). */
1827 switch (bOpcode & BS3CG1_CTXOP_DST_MASK)
1828 {
1829 case BS3CG1_CTXOP_OP1:
1830 idxField = pThis->aOperands[0].idxField;
1831 if (idxField == BS3CG1DST_INVALID)
1832 idxField = BS3CG1DST_OP1;
1833 break;
1834
1835 case BS3CG1_CTXOP_OP2:
1836 idxField = pThis->aOperands[1].idxField;
1837 if (idxField == BS3CG1DST_INVALID)
1838 idxField = BS3CG1DST_OP2;
1839 break;
1840
1841 case BS3CG1_CTXOP_EFL:
1842 idxField = BS3CG1DST_EFL;
1843 break;
1844
1845 case BS3CG1_CTXOP_DST_ESC:
1846 if (cbLeft-- > 0)
1847 {
1848 idxField = (BS3CG1DST)*pbCode++;
1849 if (idxField <= BS3CG1DST_OP4)
1850 {
1851 if (idxField > BS3CG1DST_INVALID)
1852 {
1853 uint8_t idxField2 = pThis->aOperands[idxField - BS3CG1DST_OP1].idxField;
1854 if (idxField2 != BS3CG1DST_INVALID)
1855 idxField = idxField2;
1856 break;
1857 }
1858 }
1859 else if (idxField < BS3CG1DST_END)
1860 break;
1861 return Bs3TestFailedF("Malformed context instruction: idxField=%d", idxField);
1862 }
1863 /* fall thru */
1864 default:
1865 return Bs3TestFailed("Malformed context instruction: Destination");
1866 }
1867
1868
1869 /* Expand value size (can be escaped). */
1870 switch (bOpcode & BS3CG1_CTXOP_SIZE_MASK)
1871 {
1872 case BS3CG1_CTXOP_1_BYTE: cbValue = 1; break;
1873 case BS3CG1_CTXOP_2_BYTES: cbValue = 2; break;
1874 case BS3CG1_CTXOP_4_BYTES: cbValue = 4; break;
1875 case BS3CG1_CTXOP_8_BYTES: cbValue = 8; break;
1876 case BS3CG1_CTXOP_16_BYTES: cbValue = 16; break;
1877 case BS3CG1_CTXOP_32_BYTES: cbValue = 32; break;
1878 case BS3CG1_CTXOP_12_BYTES: cbValue = 12; break;
1879 case BS3CG1_CTXOP_SIZE_ESC:
1880 if (cbLeft-- > 0)
1881 {
1882 cbValue = *pbCode++;
1883 if (cbValue)
1884 break;
1885 }
1886 /* fall thru */
1887 default:
1888 return Bs3TestFailed("Malformed context instruction: size");
1889 }
1890
1891 /* Make sure there is enough instruction bytes for the value. */
1892 if (cbValue <= cbLeft)
1893 { /* likely */ }
1894 else
1895 return Bs3TestFailedF("Malformed context instruction: %u bytes value, %u bytes left", cbValue, cbLeft);
1896
1897 /*
1898 * Do value processing specific to the target field size.
1899 */
1900 cbDst = g_acbBs3Cg1DstFields[idxField];
1901 if (cbDst == BS3CG1DSTSIZE_OPERAND)
1902 cbDst = pThis->aOperands[idxField - BS3CG1DST_OP1].cbOp;
1903 else if (cbDst == BS3CG1DSTSIZE_OPERAND_SIZE_GRP)
1904 cbDst = pThis->cbOperand;
1905 if (cbDst <= 8)
1906 {
1907 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
1908
1909 /*
1910 * Deal with fields up to 8-byte wide.
1911 */
1912 /* Get the value. */
1913 uint64_t uValue;
1914 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT))
1915 switch (cbValue)
1916 {
1917 case 1: uValue = *(int8_t const BS3_FAR *)pbCode; break;
1918 case 2: uValue = *(int16_t const BS3_FAR *)pbCode; break;
1919 case 4: uValue = *(int32_t const BS3_FAR *)pbCode; break;
1920 default:
1921 if (cbValue >= 8)
1922 {
1923 uValue = *(uint64_t const BS3_FAR *)pbCode;
1924 break;
1925 }
1926 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
1927 }
1928 else
1929 switch (cbValue)
1930 {
1931 case 1: uValue = *(uint8_t const BS3_FAR *)pbCode; break;
1932 case 2: uValue = *(uint16_t const BS3_FAR *)pbCode; break;
1933 case 4: uValue = *(uint32_t const BS3_FAR *)pbCode; break;
1934 default:
1935 if (cbValue >= 8)
1936 {
1937 uValue = *(uint64_t const BS3_FAR *)pbCode;
1938 break;
1939 }
1940 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
1941 }
1942
1943 /* Find the field. */
1944 if (offField < sizeof(BS3REGCTX))
1945 PtrField.pu8 = (uint8_t BS3_FAR *)pCtx + offField;
1946 /* Non-register operands: */
1947 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
1948 {
1949 unsigned const idxOp = idxField - BS3CG1DST_OP1;
1950
1951 switch (pThis->aOperands[idxOp].enmLocation)
1952 {
1953 case BS3CG1OPLOC_IMM:
1954 if (pbInstr)
1955 PtrField.pu8 = &pbInstr[pThis->aOperands[idxOp].off];
1956 else
1957 return Bs3TestFailedF("Immediate operand referenced in output context!");
1958 break;
1959
1960 case BS3CG1OPLOC_MEM:
1961 if (!pbInstr)
1962 return Bs3TestFailedF("Read only operand specified in output!");
1963 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
1964 break;
1965
1966 case BS3CG1OPLOC_MEM_RW:
1967 if (pbInstr)
1968 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
1969 else
1970 PtrField.pu8 = pThis->MemOp.ab;
1971 break;
1972
1973 default:
1974 return Bs3TestFailedF("Internal error: cbDst=%u idxField=%d (%d) offField=%#x: enmLocation=%u off=%#x idxField=%u",
1975 cbDst, idxField, idxOp, offField, pThis->aOperands[idxOp].enmLocation,
1976 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
1977 }
1978 }
1979 /* Special field: Copying in undefined EFLAGS from the result context. */
1980 else if (idxField == BS3CG1DST_EFL_UNDEF)
1981 {
1982 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN)
1983 return Bs3TestFailed("Invalid BS3CG1DST_EFL_UNDEF usage");
1984 PtrField.pu32 = &pCtx->rflags.u32;
1985 uValue = (*PtrField.pu32 & ~(uint32_t)uValue) | (pEflCtx->rflags.u32 & (uint32_t)uValue);
1986 }
1987 /* Special field: Expected value (in/result) exception. */
1988 else if (idxField == BS3CG1DST_VALUE_XCPT)
1989 {
1990 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN || cbDst != 1)
1991 return Bs3TestFailed("Invalid BS3CG1DST_VALUE_XCPT usage");
1992 PtrField.pu8 = &pThis->bValueXcpt;
1993 }
1994 /* FPU and FXSAVE format. */
1995 else if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
1996 && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
1997 {
1998 if (!pThis->fWorkExtCtx)
1999 return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
2000 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
2001 }
2002 /** @todo other FPU fields and FPU state formats. */
2003 else
2004 return Bs3TestFailedF("Todo implement me: cbDst=%u idxField=%d offField=%#x", cbDst, idxField, offField);
2005
2006#ifdef BS3CG1_DEBUG_CTX_MOD
2007 switch (cbDst)
2008 {
2009 case 1:
2010 BS3CG1_DPRINTF(("dbg: modify %s: %#04RX8 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2011 *PtrField.pu8, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2012 break;
2013 case 2:
2014 BS3CG1_DPRINTF(("dbg: modify %s: %#06RX16 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2015 *PtrField.pu16, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2016 break;
2017 case 4:
2018 BS3CG1_DPRINTF(("dbg: modify %s: %#010RX32 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2019 *PtrField.pu32, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2020 break;
2021 default:
2022 BS3CG1_DPRINTF(("dbg: modify %s: %#018RX64 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2023 *PtrField.pu64, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2024 break;
2025 }
2026#endif
2027
2028 /* Modify the field. */
2029 switch (cbDst)
2030 {
2031 case 1:
2032 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2033 {
2034 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu8 = (uint8_t)uValue; break;
2035 case BS3CG1_CTXOP_OR: *PtrField.pu8 |= (uint8_t)uValue; break;
2036 case BS3CG1_CTXOP_AND: *PtrField.pu8 &= (uint8_t)uValue; break;
2037 case BS3CG1_CTXOP_AND_INV: *PtrField.pu8 &= ~(uint8_t)uValue; break;
2038 }
2039 break;
2040
2041 case 2:
2042 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2043 {
2044 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu16 = (uint16_t)uValue; break;
2045 case BS3CG1_CTXOP_OR: *PtrField.pu16 |= (uint16_t)uValue; break;
2046 case BS3CG1_CTXOP_AND: *PtrField.pu16 &= (uint16_t)uValue; break;
2047 case BS3CG1_CTXOP_AND_INV: *PtrField.pu16 &= ~(uint16_t)uValue; break;
2048 }
2049 break;
2050
2051 case 4:
2052 if (offField <= RT_OFFSETOF(BS3REGCTX, r15)) /* Clear the top dword. */
2053 PtrField.pu32[1] = 0;
2054 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2055 {
2056 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu32 = (uint32_t)uValue; break;
2057 case BS3CG1_CTXOP_OR: *PtrField.pu32 |= (uint32_t)uValue; break;
2058 case BS3CG1_CTXOP_AND: *PtrField.pu32 &= (uint32_t)uValue; break;
2059 case BS3CG1_CTXOP_AND_INV: *PtrField.pu32 &= ~(uint32_t)uValue; break;
2060 }
2061 break;
2062
2063 case 8:
2064 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2065 {
2066 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu64 = (uint64_t)uValue; break;
2067 case BS3CG1_CTXOP_OR: *PtrField.pu64 |= (uint64_t)uValue; break;
2068 case BS3CG1_CTXOP_AND: *PtrField.pu64 &= (uint64_t)uValue; break;
2069 case BS3CG1_CTXOP_AND_INV: *PtrField.pu64 &= ~(uint64_t)uValue; break;
2070 }
2071 break;
2072
2073 default:
2074 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, expected 1, 2, 4, or 8", cbDst);
2075 }
2076
2077#ifdef BS3CG1_DEBUG_CTX_MOD
2078 switch (cbDst)
2079 {
2080 case 1: BS3CG1_DPRINTF(("dbg: --> %s: %#04RX8\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu8)); break;
2081 case 2: BS3CG1_DPRINTF(("dbg: --> %s: %#06RX16\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu16)); break;
2082 case 4: BS3CG1_DPRINTF(("dbg: --> %s: %#010RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu32)); break;
2083 default: BS3CG1_DPRINTF(("dbg: --> %s: %#018RX64\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64)); break;
2084 }
2085#endif
2086
2087 }
2088 /*
2089 * Deal with larger field (FPU, SSE, AVX, ...).
2090 */
2091 else
2092 {
2093 union
2094 {
2095 X86FPUREG FpuReg;
2096 X86XMMREG XmmReg;
2097 X86YMMREG YmmReg;
2098 X86ZMMREG ZmmReg;
2099 uint8_t ab[sizeof(X86ZMMREG)];
2100 uint32_t au32[sizeof(X86ZMMREG) / sizeof(uint32_t)];
2101 } Value;
2102 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
2103
2104 if (!pThis->fWorkExtCtx)
2105 return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
2106
2107 /* Copy the value into the union, doing the zero padding / extending. */
2108 Bs3MemCpy(&Value, pbCode, cbValue);
2109 if (cbValue < sizeof(Value))
2110 {
2111 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT) && (Value.ab[cbValue - 1] & 0x80))
2112 Bs3MemSet(&Value.ab[cbValue], 0xff, sizeof(Value) - cbValue);
2113 else
2114 Bs3MemSet(&Value.ab[cbValue], 0x00, sizeof(Value) - cbValue);
2115 }
2116
2117 /* Optimized access to XMM and STx registers. */
2118 if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
2119 && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
2120 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
2121 /* Non-register operands: */
2122 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
2123 {
2124 unsigned const idxOp = idxField - BS3CG1DST_OP1;
2125 switch (pThis->aOperands[idxOp].enmLocation)
2126 {
2127 case BS3CG1OPLOC_MEM:
2128 if (!pbInstr)
2129 return Bs3TestFailedF("Read only operand specified in output!");
2130 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2131 break;
2132
2133 case BS3CG1OPLOC_MEM_RW:
2134 if (pbInstr)
2135 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2136 else
2137 PtrField.pu8 = pThis->MemOp.ab;
2138 break;
2139
2140 default:
2141 return Bs3TestFailedF("Internal error: Field %d (%d) @ %#x LB %u: enmLocation=%u off=%#x idxField=%u",
2142 idxField, idxOp, offField, cbDst, pThis->aOperands[idxOp].enmLocation,
2143 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
2144 }
2145 }
2146 /* The YMM (AVX) and the first 16 ZMM (AVX512) registers have split storage in
2147 the state, so they need special handling. */
2148 else
2149 {
2150 return Bs3TestFailedF("TODO: implement me: cbDst=%d idxField=%d (AVX and other weird state)", cbDst, idxField);
2151 }
2152
2153 if (PtrField.pb)
2154 {
2155 /* Modify the field / memory. */
2156 unsigned i;
2157 if (cbDst & 3)
2158 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, multiple of 4", cbDst);
2159
2160#ifdef BS3CG1_DEBUG_CTX_MOD
2161 BS3CG1_DPRINTF(("dbg: modify %s: %.*Rhxs (LB %u) %s %.*Rhxs (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2162 cbDst, PtrField.pb, cbDst, Bs3Cg1CtxOpToString(bOpcode), cbValue, Value.ab, cbValue));
2163#endif
2164
2165 i = cbDst / 4;
2166 while (i-- > 0)
2167 {
2168 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2169 {
2170 case BS3CG1_CTXOP_ASSIGN: PtrField.pu32[i] = Value.au32[i]; break;
2171 case BS3CG1_CTXOP_OR: PtrField.pu32[i] |= Value.au32[i]; break;
2172 case BS3CG1_CTXOP_AND: PtrField.pu32[i] &= Value.au32[i]; break;
2173 case BS3CG1_CTXOP_AND_INV: PtrField.pu32[i] &= ~Value.au32[i]; break;
2174 }
2175 }
2176
2177#ifdef BS3CG1_DEBUG_CTX_MOD
2178 BS3CG1_DPRINTF(("dbg: --> %s: %.*Rhxs\n", g_aszBs3Cg1DstFields[idxField].sz, cbDst, PtrField.pb));
2179#endif
2180 }
2181 }
2182
2183 /*
2184 * Advance to the next instruction.
2185 */
2186 pbCode += cbValue;
2187 cbLeft -= cbValue;
2188 }
2189
2190 return true;
2191}
2192
2193
2194/**
2195 * Checks the result of a run.
2196 *
2197 * @returns true if successful, false if not.
2198 * @param pThis The state.
2199 * @param fInvalidInstr Whether this is an invalid instruction.
2200 * @param bTestXcptExpected The exception causing the test code to stop
2201 * executing.
2202 * @param iEncoding For error reporting.
2203 */
2204static bool Bs3Cg1CheckResult(PBS3CG1STATE pThis, bool fInvalidInstr, uint8_t bTestXcptExpected, unsigned iEncoding)
2205{
2206 unsigned iOperand;
2207
2208 /*
2209 * Check the exception state first.
2210 */
2211 uint8_t bExpectedXcpt;
2212 uint8_t cbAdjustPc;
2213 if (!fInvalidInstr)
2214 {
2215 bExpectedXcpt = pThis->bAlignmentXcpt;
2216 if (bExpectedXcpt == UINT8_MAX)
2217 bExpectedXcpt = pThis->bValueXcpt;
2218 if (bExpectedXcpt == UINT8_MAX)
2219 {
2220 cbAdjustPc = pThis->cbCurInstr;
2221 bExpectedXcpt = bTestXcptExpected;
2222 if (bTestXcptExpected == X86_XCPT_PF)
2223 pThis->Ctx.cr2.u = pThis->uCodePgFlat + X86_PAGE_SIZE;
2224 }
2225 else
2226 cbAdjustPc = 0;
2227 }
2228 else
2229 {
2230 cbAdjustPc = 0;
2231 bExpectedXcpt = bTestXcptExpected;
2232 }
2233 if (RT_LIKELY( pThis->TrapFrame.bXcpt == bExpectedXcpt
2234 && pThis->TrapFrame.Ctx.rip.u == pThis->Ctx.rip.u + cbAdjustPc))
2235 {
2236 /*
2237 * Check the register content.
2238 */
2239 bool fOkay = Bs3TestCheckRegCtxEx(&pThis->TrapFrame.Ctx, &pThis->Ctx,
2240 cbAdjustPc, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/,
2241 pThis->pszMode, iEncoding);
2242
2243 /*
2244 * Check memory output operands.
2245 */
2246 iOperand = pThis->cOperands;
2247 while (iOperand-- > 0)
2248 if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
2249 {
2250 BS3PTRUNION PtrUnion;
2251 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
2252 switch (pThis->aOperands[iOperand].cbOp)
2253 {
2254 case 1:
2255 if (*PtrUnion.pu8 == pThis->MemOp.ab[0])
2256 continue;
2257 Bs3TestFailedF("op%u: Wrote %#04RX8, expected %#04RX8", iOperand, *PtrUnion.pu8, pThis->MemOp.ab[0]);
2258 break;
2259 case 2:
2260 if (*PtrUnion.pu16 == pThis->MemOp.au16[0])
2261 continue;
2262 Bs3TestFailedF("op%u: Wrote %#06RX16, expected %#06RX16",
2263 iOperand, *PtrUnion.pu16, pThis->MemOp.au16[0]);
2264 break;
2265 case 4:
2266 if (*PtrUnion.pu32 == pThis->MemOp.au32[0])
2267 continue;
2268 Bs3TestFailedF("op%u: Wrote %#010RX32, expected %#010RX32",
2269 iOperand, *PtrUnion.pu32, pThis->MemOp.au32[0]);
2270 break;
2271 case 8:
2272 if (*PtrUnion.pu64 == pThis->MemOp.au64[0])
2273 continue;
2274 Bs3TestFailedF("op%u: Wrote %#018RX64, expected %#018RX64",
2275 iOperand, *PtrUnion.pu64, pThis->MemOp.au64[0]);
2276 break;
2277 default:
2278 if (Bs3MemCmp(PtrUnion.pb, pThis->MemOp.ab, pThis->aOperands[iOperand].cbOp) == 0)
2279 continue;
2280 Bs3TestFailedF("op%u: Wrote %.*Rhxs, expected %.*Rhxs",
2281 iOperand,
2282 pThis->aOperands[iOperand].cbOp, PtrUnion.pb,
2283 pThis->aOperands[iOperand].cbOp, pThis->MemOp.ab);
2284 break;
2285 }
2286 fOkay = false;
2287 }
2288
2289 /*
2290 * Check extended context if enabled.
2291 */
2292 if (pThis->fWorkExtCtx)
2293 {
2294 PBS3EXTCTX pExpect = pThis->pExtCtx;
2295 PBS3EXTCTX pResult = pThis->pResultExtCtx;
2296 unsigned i;
2297 if ( pExpect->enmMethod == BS3EXTCTXMETHOD_XSAVE
2298 || pExpect->enmMethod == BS3EXTCTXMETHOD_FXSAVE)
2299 {
2300 /* Compare the x87 state, ASSUMING XCR0 bit 1 is set. */
2301#define CHECK_FIELD(a_Field, a_szFmt) \
2302 if (pResult->Ctx.a_Field != pExpect->Ctx.a_Field) fOkay = Bs3TestFailedF(a_szFmt, pResult->Ctx.a_Field, pExpect->Ctx.a_Field)
2303 CHECK_FIELD(x87.FCW, "FCW: %#06x, expected %#06x");
2304 CHECK_FIELD(x87.FSW, "FSW: %#06x, expected %#06x");
2305 CHECK_FIELD(x87.FTW, "FTW: %#06x, expected %#06x");
2306 //CHECK_FIELD(x87.FOP, "FOP: %#06x, expected %#06x");
2307 //CHECK_FIELD(x87.FPUIP, "FPUIP: %#010x, expected %#010x");
2308 //CHECK_FIELD(x87.CS, "FPUCS: %#06x, expected %#06x");
2309 //CHECK_FIELD(x87.Rsrvd1, "Rsrvd1: %#06x, expected %#06x");
2310 //CHECK_FIELD(x87.DP, "FPUDP: %#010x, expected %#010x");
2311 //CHECK_FIELD(x87.DS, "FPUDS: %#06x, expected %#06x");
2312 //CHECK_FIELD(x87.Rsrvd2, "Rsrvd2: %#06x, expected %#06x");
2313 CHECK_FIELD(x87.MXCSR, "MXCSR: %#010x, expected %#010x");
2314 //CHECK_FIELD(x87.MXCSR_MASK, "MXCSR_MASK: %#010x, expected %#010x");
2315#undef CHECK_FIELD
2316 for (i = 0; i < RT_ELEMENTS(pExpect->Ctx.x87.aRegs); i++)
2317 if ( pResult->Ctx.x87.aRegs[i].au64[0] != pExpect->Ctx.x87.aRegs[i].au64[0]
2318 || pResult->Ctx.x87.aRegs[i].au16[4] != pExpect->Ctx.x87.aRegs[i].au16[4])
2319 fOkay = Bs3TestFailedF("ST[%u]: %c m=%#RX64 e=%d, expected %c m=%#RX64 e=%d", i,
2320 pResult->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
2321 pResult->Ctx.x87.aRegs[i].r80Ex.s.u64Mantissa,
2322 pResult->Ctx.x87.aRegs[i].r80Ex.s.uExponent,
2323 pExpect->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
2324 pExpect->Ctx.x87.aRegs[i].r80Ex.s.u64Mantissa,
2325 pExpect->Ctx.x87.aRegs[i].r80Ex.s.uExponent);
2326 for (i = 0; i < (ARCH_BITS == 64 ? 16 : 8); i++)
2327 if ( pResult->Ctx.x87.aXMM[i].au64[0] != pExpect->Ctx.x87.aXMM[i].au64[0]
2328 || pResult->Ctx.x87.aXMM[i].au64[1] != pExpect->Ctx.x87.aXMM[i].au64[1])
2329 fOkay = Bs3TestFailedF("XMM%u: %#010RX64'%08RX64, expected %#010RX64'%08RX64", i,
2330 pResult->Ctx.x87.aXMM[i].au64[0],
2331 pResult->Ctx.x87.aXMM[i].au64[1],
2332 pExpect->Ctx.x87.aXMM[i].au64[0],
2333 pExpect->Ctx.x87.aXMM[i].au64[1]);
2334 }
2335 else
2336 fOkay = Bs3TestFailedF("Unsupported extended CPU context method: %d", pExpect->enmMethod);
2337 }
2338
2339 /*
2340 * Done.
2341 */
2342 if (fOkay)
2343 return true;
2344
2345 /*
2346 * Report failure.
2347 */
2348 Bs3TestFailedF("%RU32[%u]: encoding#%u: %.*Rhxs",
2349 pThis->iInstr, pThis->iTest, iEncoding, pThis->cbCurInstr, pThis->abCurInstr);
2350 }
2351 else
2352 Bs3TestFailedF("%RU32[%u]: bXcpt=%#x expected %#x; rip=%RX64 expected %RX64; encoding#%u: %.*Rhxs",
2353 pThis->iInstr, pThis->iTest,
2354 pThis->TrapFrame.bXcpt, bExpectedXcpt,
2355 pThis->TrapFrame.Ctx.rip.u, pThis->Ctx.rip.u + cbAdjustPc,
2356 iEncoding, pThis->cbCurInstr, pThis->abCurInstr);
2357 Bs3TestPrintf("cpl=%u cbOperands=%u\n", pThis->uCpl, pThis->cbOperand);
2358
2359 /*
2360 * Display memory operands.
2361 */
2362 for (iOperand = 0; iOperand < pThis->cOperands; iOperand++)
2363 {
2364 BS3PTRUNION PtrUnion;
2365 switch (pThis->aOperands[iOperand].enmLocation)
2366 {
2367 case BS3CG1OPLOC_CTX:
2368 {
2369 uint8_t idxField = pThis->aOperands[iOperand].idxField;
2370 unsigned offField = g_aoffBs3Cg1DstFields[idxField];
2371 if (offField <= sizeof(BS3REGCTX))
2372 PtrUnion.pb = (uint8_t BS3_FAR *)&pThis->Ctx + offField;
2373 else
2374 {
2375 Bs3TestPrintf("op%u: ctx%u: xxxx\n", iOperand, pThis->aOperands[iOperand].cbOp * 8);
2376 break;
2377 }
2378 switch (pThis->aOperands[iOperand].cbOp)
2379 {
2380 case 1: Bs3TestPrintf("op%u: ctx08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2381 case 2: Bs3TestPrintf("op%u: ctx16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2382 case 4: Bs3TestPrintf("op%u: ctx32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2383 case 8: Bs3TestPrintf("op%u: ctx64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2384 default:
2385 Bs3TestPrintf("op%u: ctx%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2386 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2387 break;
2388 }
2389 break;
2390 }
2391
2392 case BS3CG1OPLOC_IMM:
2393 PtrUnion.pb = &pThis->pbCodePg[pThis->aOperands[iOperand].off];
2394 switch (pThis->aOperands[iOperand].cbOp)
2395 {
2396 case 1: Bs3TestPrintf("op%u: imm08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2397 case 2: Bs3TestPrintf("op%u: imm16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2398 case 4: Bs3TestPrintf("op%u: imm32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2399 case 8: Bs3TestPrintf("op%u: imm64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2400 default:
2401 Bs3TestPrintf("op%u: imm%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2402 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2403 break;
2404 }
2405 break;
2406
2407 case BS3CG1OPLOC_MEM:
2408 case BS3CG1OPLOC_MEM_RW:
2409 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
2410 switch (pThis->aOperands[iOperand].cbOp)
2411 {
2412 case 1: Bs3TestPrintf("op%u: result mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2413 case 2: Bs3TestPrintf("op%u: result mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2414 case 4: Bs3TestPrintf("op%u: result mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2415 case 8: Bs3TestPrintf("op%u: result mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2416 default:
2417 Bs3TestPrintf("op%u: result mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2418 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2419 break;
2420 }
2421 if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
2422 {
2423 PtrUnion.pb = pThis->MemOp.ab;
2424 switch (pThis->aOperands[iOperand].cbOp)
2425 {
2426 case 1: Bs3TestPrintf("op%u: expect mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2427 case 2: Bs3TestPrintf("op%u: expect mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2428 case 4: Bs3TestPrintf("op%u: expect mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2429 case 8: Bs3TestPrintf("op%u: expect mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2430 default:
2431 Bs3TestPrintf("op%u: expect mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2432 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2433 break;
2434 }
2435 }
2436 break;
2437 }
2438 }
2439
2440 /*
2441 * Display contexts.
2442 */
2443 Bs3TestPrintf("-- Expected context:\n");
2444 Bs3RegCtxPrint(&pThis->Ctx);
2445 Bs3TestPrintf("-- Actual context:\n");
2446 Bs3TrapPrintFrame(&pThis->TrapFrame);
2447 Bs3TestPrintf("\n");
2448 return false;
2449}
2450
2451
2452/**
2453 * Destroys the state, freeing all allocations and such.
2454 *
2455 * @param pThis The state.
2456 */
2457static void Bs3Cg1Destroy(PBS3CG1STATE pThis)
2458{
2459 if (BS3_MODE_IS_PAGED(pThis->bMode))
2460 {
2461#if ARCH_BITS != 16
2462 Bs3MemGuardedTestPageFree(pThis->pbCodePg);
2463 Bs3MemGuardedTestPageFree(pThis->pbDataPg);
2464#endif
2465 }
2466 else
2467 {
2468 Bs3MemFree(pThis->pbCodePg, X86_PAGE_SIZE);
2469 Bs3MemFree(pThis->pbDataPg, X86_PAGE_SIZE);
2470 }
2471
2472 if (pThis->pExtCtx)
2473 Bs3MemFree(pThis->pExtCtx, pThis->pExtCtx->cb * 3);
2474
2475 pThis->pbCodePg = NULL;
2476 pThis->pbDataPg = NULL;
2477 pThis->pExtCtx = NULL;
2478 pThis->pResultExtCtx = NULL;
2479 pThis->pInitialExtCtx = NULL;
2480}
2481
2482
2483/**
2484 * Initializes the state.
2485 *
2486 * @returns Success indicator (true/false)
2487 * @param pThis The state.
2488 * @param bMode The mode being tested.
2489 */
2490bool BS3_CMN_NM(Bs3Cg1Init)(PBS3CG1STATE pThis, uint8_t bMode)
2491{
2492 BS3MEMKIND const enmMemKind = BS3_MODE_IS_RM_OR_V86(bMode) ? BS3MEMKIND_REAL
2493 : !BS3_MODE_IS_64BIT_CODE(bMode) ? BS3MEMKIND_TILED : BS3MEMKIND_FLAT32;
2494 unsigned iRing;
2495 unsigned cb;
2496 unsigned i;
2497 uint64_t fFlags;
2498 PBS3EXTCTX pExtCtx;
2499
2500 Bs3MemSet(pThis, 0, sizeof(*pThis));
2501
2502 pThis->iFirstRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
2503 pThis->iEndRing = BS3_MODE_IS_RM_SYS(bMode) ? 1 : 4;
2504 pThis->bMode = bMode;
2505 pThis->pszMode = Bs3GetModeName(bMode);
2506 pThis->pszModeShort = Bs3GetModeNameShortLower(bMode);
2507 pThis->pchMnemonic = g_achBs3Cg1Mnemonics;
2508 pThis->pabOperands = g_abBs3Cg1Operands;
2509 pThis->pabOpcodes = g_abBs3Cg1Opcodes;
2510 pThis->fAdvanceMnemonic = 1;
2511
2512 /* Allocate extended context structures. */
2513 cb = Bs3ExtCtxGetSize(&fFlags);
2514 pExtCtx = Bs3MemAlloc(BS3MEMKIND_TILED, cb * 3);
2515 if (!pExtCtx)
2516 return Bs3TestFailedF("Bs3MemAlloc(tiled,%#x)", cb * 3);
2517 pThis->pExtCtx = pExtCtx;
2518 pThis->pResultExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb);
2519 pThis->pInitialExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb + cb);
2520
2521 Bs3ExtCtxInit(pThis->pExtCtx, cb, fFlags);
2522 Bs3ExtCtxInit(pThis->pResultExtCtx, cb, fFlags);
2523 Bs3ExtCtxInit(pThis->pInitialExtCtx, cb, fFlags);
2524 //Bs3TestPrintf("fCR0=%RX64 cbExtCtx=%#x method=%d\n", fFlags, cb, pExtCtx->enmMethod);
2525
2526 /* Allocate guarded exectuable and data memory. */
2527 if (BS3_MODE_IS_PAGED(bMode))
2528 {
2529#if ARCH_BITS != 16
2530 pThis->pbCodePg = Bs3MemGuardedTestPageAlloc(enmMemKind);
2531 pThis->pbDataPg = Bs3MemGuardedTestPageAlloc(enmMemKind);
2532 if (!pThis->pbCodePg || !pThis->pbDataPg)
2533 {
2534 Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
2535 Bs3MemPrintInfo();
2536 Bs3Shutdown();
2537 return Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
2538 }
2539 if ( BS3_MODE_IS_64BIT_CODE(bMode)
2540 && (uintptr_t)pThis->pbDataPg >= _2G)
2541 return Bs3TestFailedF("pbDataPg=%p is above 2GB and not simple to address from 64-bit code", pThis->pbDataPg);
2542#else
2543 return Bs3TestFailed("WTF?! #1");
2544#endif
2545 }
2546 else
2547 {
2548 pThis->pbCodePg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
2549 pThis->pbDataPg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
2550 if (!pThis->pbCodePg || !pThis->pbDataPg)
2551 {
2552 Bs3MemPrintInfo();
2553 return Bs3TestFailedF("Bs3MemAlloc(%d,Pg) failed", enmMemKind);
2554 }
2555 }
2556 pThis->uCodePgFlat = Bs3SelPtrToFlat(pThis->pbCodePg);
2557 pThis->uDataPgFlat = Bs3SelPtrToFlat(pThis->pbDataPg);
2558#if ARCH_BITS == 16
2559 pThis->CodePgFar.sel = BS3_FP_SEG(pThis->pbCodePg);
2560 pThis->CodePgFar.off = BS3_FP_OFF(pThis->pbCodePg);
2561 pThis->CodePgRip = BS3_FP_OFF(pThis->pbCodePg);
2562 pThis->DataPgFar.sel = BS3_FP_SEG(pThis->pbDataPg);
2563 pThis->DataPgFar.off = BS3_FP_OFF(pThis->pbDataPg);
2564#else
2565 if (BS3_MODE_IS_RM_OR_V86(bMode))
2566 {
2567 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToRealMode(pThis->uDataPgFlat);
2568 ASMCompilerBarrier();
2569 pThis->CodePgFar.off = 0;
2570 pThis->CodePgFar.sel = pThis->uCodePgFlat >> 4;
2571 pThis->CodePgRip = pThis->CodePgFar.off;
2572 }
2573 else if (BS3_MODE_IS_16BIT_CODE(bMode))
2574 {
2575 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
2576 ASMCompilerBarrier();
2577 pThis->CodePgFar.sel = BS3_SEL_SPARE_00;
2578 pThis->CodePgFar.off = 0;
2579 pThis->CodePgRip = 0;
2580 }
2581 else if (BS3_MODE_IS_32BIT_CODE(bMode))
2582 {
2583 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
2584 ASMCompilerBarrier();
2585 pThis->CodePgFar.sel = 0;
2586 pThis->CodePgFar.off = 0;
2587 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
2588 }
2589 else
2590 {
2591 pThis->DataPgFar.off = 0;
2592 pThis->DataPgFar.sel = 0;
2593 pThis->CodePgFar.off = 0;
2594 pThis->CodePgFar.sel = 0;
2595 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
2596 }
2597#endif
2598
2599 /*
2600 * Create basic context for each target ring.
2601 *
2602 * In protected 16-bit code we need set up code selectors that can access
2603 * pbCodePg.
2604 *
2605 * In long mode we make sure the high 32-bits of GPRs (sans RSP) have some
2606 * bits set so we can check that the implicit clearing is tested.
2607 */
2608 Bs3RegCtxSaveEx(&pThis->aInitialCtxs[pThis->iFirstRing], bMode, 1024 * 3);
2609#if ARCH_BITS == 64
2610 pThis->aInitialCtxs[pThis->iFirstRing].rax.u |= UINT64_C(0x0101010100000000);
2611 pThis->aInitialCtxs[pThis->iFirstRing].rbx.u |= UINT64_C(0x0202020200000000);
2612 pThis->aInitialCtxs[pThis->iFirstRing].rcx.u |= UINT64_C(0x0303030300000000);
2613 pThis->aInitialCtxs[pThis->iFirstRing].rdx.u |= UINT64_C(0x0404040400000000);
2614 pThis->aInitialCtxs[pThis->iFirstRing].rbp.u |= UINT64_C(0x0505050500000000);
2615 pThis->aInitialCtxs[pThis->iFirstRing].rdi.u |= UINT64_C(0x0606060600000000);
2616 pThis->aInitialCtxs[pThis->iFirstRing].rsi.u |= UINT64_C(0x0707070700000000);
2617 pThis->aInitialCtxs[pThis->iFirstRing].r8.u |= UINT64_C(0x0808080800000000);
2618 pThis->aInitialCtxs[pThis->iFirstRing].r9.u |= UINT64_C(0x0909090900000000);
2619 pThis->aInitialCtxs[pThis->iFirstRing].r10.u |= UINT64_C(0x1010101000000000);
2620 pThis->aInitialCtxs[pThis->iFirstRing].r11.u |= UINT64_C(0x1111111100000000);
2621 pThis->aInitialCtxs[pThis->iFirstRing].r12.u |= UINT64_C(0x1212121200000000);
2622 pThis->aInitialCtxs[pThis->iFirstRing].r13.u |= UINT64_C(0x1313131300000000);
2623 pThis->aInitialCtxs[pThis->iFirstRing].r14.u |= UINT64_C(0x1414141400000000);
2624 pThis->aInitialCtxs[pThis->iFirstRing].r15.u |= UINT64_C(0x1515151500000000);
2625#endif
2626
2627 if (BS3_MODE_IS_RM_OR_V86(bMode))
2628 {
2629 pThis->aInitialCtxs[pThis->iFirstRing].cs = pThis->CodePgFar.sel;
2630 BS3_ASSERT(pThis->iFirstRing + 1 == pThis->iEndRing);
2631 }
2632 else if (BS3_MODE_IS_16BIT_CODE(bMode))
2633 {
2634#if ARCH_BITS == 16
2635 uintptr_t const uFlatCodePgSeg = Bs3SelPtrToFlat(BS3_FP_MAKE(BS3_FP_SEG(pThis->pbCodePg), 0));
2636#else
2637 uintptr_t const uFlatCodePgSeg = (uintptr_t)pThis->pbCodePg;
2638#endif
2639 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
2640 {
2641 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
2642 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
2643 }
2644 for (iRing = pThis->iFirstRing; iRing < pThis->iEndRing; iRing++)
2645 {
2646 pThis->aInitialCtxs[iRing].cs = BS3_SEL_SPARE_00 + iRing * 8 + iRing;
2647 Bs3SelSetup16BitCode(&Bs3GdteSpare00 + iRing, uFlatCodePgSeg, iRing);
2648 }
2649 }
2650 else
2651 {
2652 Bs3RegCtxSetRipCsFromCurPtr(&pThis->aInitialCtxs[pThis->iFirstRing], (FPFNBS3FAR)pThis->pbCodePg);
2653 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
2654 {
2655 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
2656 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
2657 }
2658 }
2659
2660 /*
2661 * Create an initial extended CPU context.
2662 */
2663 pExtCtx = pThis->pInitialExtCtx;
2664 if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE
2665 || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
2666 {
2667 pExtCtx->Ctx.x87.FCW = X86_FCW_MASK_ALL | X86_FCW_PC_64 | X86_FCW_RC_NEAREST;
2668 pExtCtx->Ctx.x87.FSW = 0;
2669 pExtCtx->Ctx.x87.MXCSR = X86_MXSCR_IM | X86_MXSCR_DM | X86_MXSCR_RC_NEAREST;
2670 pExtCtx->Ctx.x87.MXCSR_MASK = 0;
2671 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aRegs); i++)
2672 {
2673 pExtCtx->Ctx.x87.aRegs[i].au16[0] = i << 4;
2674 pExtCtx->Ctx.x87.aRegs[i].au16[1] = i << 4;
2675 pExtCtx->Ctx.x87.aRegs[i].au16[2] = i << 4;
2676 pExtCtx->Ctx.x87.aRegs[i].au16[3] = i << 4;
2677 }
2678 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM); i++)
2679 {
2680 pExtCtx->Ctx.x87.aXMM[i].au16[0] = i;
2681 pExtCtx->Ctx.x87.aXMM[i].au16[1] = i;
2682 pExtCtx->Ctx.x87.aXMM[i].au16[2] = i;
2683 pExtCtx->Ctx.x87.aXMM[i].au16[3] = i;
2684 pExtCtx->Ctx.x87.aXMM[i].au16[4] = i;
2685 pExtCtx->Ctx.x87.aXMM[i].au16[5] = i;
2686 pExtCtx->Ctx.x87.aXMM[i].au16[6] = i;
2687 pExtCtx->Ctx.x87.aXMM[i].au16[7] = i;
2688 }
2689 if (pExtCtx->fXcr0 & XSAVE_C_YMM)
2690 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi); i++)
2691 {
2692 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[0] = i << 8;
2693 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[1] = i << 8;
2694 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[2] = i << 8;
2695 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[3] = i << 8;
2696 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[4] = i << 8;
2697 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[5] = i << 8;
2698 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[6] = i << 8;
2699 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[7] = i << 8;
2700 }
2701
2702 }
2703 //else if (pExtCtx->enmMethod == BS3EXTCTXMETHOD_ANCIENT)
2704 else
2705 return Bs3TestFailedF("Unsupported extended CPU context method: %d", pExtCtx->enmMethod);
2706
2707 return true;
2708}
2709
2710
2711static uint8_t BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
2712{
2713 uint8_t iRing;
2714 unsigned iInstr;
2715
2716 /*
2717 * Test the instructions.
2718 */
2719 for (iInstr = 0; iInstr < g_cBs3Cg1Instructions;
2720 iInstr++,
2721 pThis->pchMnemonic += pThis->fAdvanceMnemonic * pThis->cchMnemonic,
2722 pThis->pabOperands += pThis->cOperands,
2723 pThis->pabOpcodes += pThis->cbOpcodes)
2724 {
2725 bool fInvalidInstr = false;
2726 unsigned iCpuSetup;
2727 uint8_t bTestXcptExpected = BS3_MODE_IS_PAGED(pThis->bMode) ? X86_XCPT_PF : X86_XCPT_UD;
2728
2729 /*
2730 * Expand the instruction information into the state.
2731 * Note! 16-bit will switch to a two level test header lookup once we exceed 64KB.
2732 */
2733 PCBS3CG1INSTR pInstr = &g_aBs3Cg1Instructions[iInstr];
2734 pThis->iInstr = iInstr;
2735 pThis->pTestHdr = (PCBS3CG1TESTHDR)&g_abBs3Cg1Tests[pInstr->offTests];
2736 pThis->fFlags = pInstr->fFlags;
2737 pThis->enmEncoding = (BS3CG1ENC)pInstr->enmEncoding;
2738 pThis->enmCpuTest = (BS3CG1CPU)pInstr->enmCpuTest;
2739 pThis->enmPrefixKind = (BS3CG1PFXKIND)pInstr->enmPrefixKind;
2740 pThis->enmXcptType = (BS3CG1XCPTTYPE)pInstr->enmXcptType;
2741 pThis->cchMnemonic = pInstr->cchMnemonic;
2742 if (pThis->fAdvanceMnemonic)
2743 Bs3TestSubF("%s / %.*s", pThis->pszModeShort, pThis->cchMnemonic, pThis->pchMnemonic);
2744 pThis->fAdvanceMnemonic = pInstr->fAdvanceMnemonic;
2745 pThis->cOperands = pInstr->cOperands;
2746 pThis->cbOpcodes = pInstr->cbOpcodes;
2747 switch (pThis->cOperands)
2748 {
2749 case 3: pThis->aenmOperands[3] = (BS3CG1OP)pThis->pabOperands[3];
2750 case 2: pThis->aenmOperands[2] = (BS3CG1OP)pThis->pabOperands[2];
2751 case 1: pThis->aenmOperands[1] = (BS3CG1OP)pThis->pabOperands[1];
2752 case 0: pThis->aenmOperands[0] = (BS3CG1OP)pThis->pabOperands[0];
2753 }
2754
2755 switch (pThis->cbOpcodes)
2756 {
2757 case 3: pThis->abOpcodes[3] = pThis->pabOpcodes[3];
2758 case 2: pThis->abOpcodes[2] = pThis->pabOpcodes[2];
2759 case 1: pThis->abOpcodes[1] = pThis->pabOpcodes[1];
2760 case 0: pThis->abOpcodes[0] = pThis->pabOpcodes[0];
2761 }
2762
2763 /*
2764 * Check if the CPU supports the instruction.
2765 */
2766 if (!Bs3Cg1CpuSetupFirst(pThis))
2767 {
2768 fInvalidInstr = true;
2769 bTestXcptExpected = X86_XCPT_UD;
2770 }
2771
2772 for (iCpuSetup = 0;; iCpuSetup++)
2773 {
2774 unsigned iEncoding;
2775 unsigned iEncodingNext;
2776
2777 /*
2778 * Prep the operands and encoding handling.
2779 */
2780 if (!Bs3Cg1EncodePrep(pThis))
2781 break;
2782
2783 /*
2784 * Encode the instruction in various ways and check out the test values.
2785 */
2786 for (iEncoding = 0;; iEncoding = iEncodingNext)
2787 {
2788 /*
2789 * Encode the next instruction variation.
2790 */
2791 iEncodingNext = Bs3Cg1EncodeNext(pThis, iEncoding);
2792 if (iEncodingNext <= iEncoding)
2793 break;
2794 BS3CG1_DPRINTF(("\ndbg: Encoding #%u: cbCurInst=%u: %.*Rhxs\n",
2795 iEncoding, pThis->cbCurInstr, pThis->cbCurInstr, pThis->abCurInstr));
2796
2797 /*
2798 * Do the rings.
2799 */
2800 for (iRing = pThis->iFirstRing + pThis->fSameRingNotOkay; iRing < pThis->iEndRing; iRing++)
2801 {
2802 PCBS3CG1TESTHDR pHdr;
2803
2804 pThis->uCpl = iRing;
2805 BS3CG1_DPRINTF(("dbg: Ring %u\n", iRing));
2806
2807 /*
2808 * Do the tests one by one.
2809 */
2810 pHdr = pThis->pTestHdr;
2811 for (pThis->iTest = 0;; pThis->iTest++)
2812 {
2813 if (Bs3Cg1RunSelector(pThis, pHdr))
2814 {
2815 /* Okay, set up the execution context. */
2816 unsigned offCode;
2817 uint8_t BS3_FAR *pbCode;
2818
2819 Bs3MemCpy(&pThis->Ctx, &pThis->aInitialCtxs[iRing], sizeof(pThis->Ctx));
2820 if (pThis->fWorkExtCtx)
2821 Bs3ExtCtxCopy(pThis->pExtCtx, pThis->pInitialExtCtx);
2822 if (BS3_MODE_IS_PAGED(pThis->bMode))
2823 {
2824 offCode = X86_PAGE_SIZE - pThis->cbCurInstr;
2825 pbCode = &pThis->pbCodePg[offCode];
2826 //if (iEncoding > 0) { pbCode[-1] = 0xf4; offCode--; }
2827 }
2828 else
2829 {
2830 pbCode = pThis->pbCodePg;
2831 pbCode[pThis->cbCurInstr] = 0x0f; /* UD2 */
2832 pbCode[pThis->cbCurInstr + 1] = 0x0b;
2833 offCode = 0;
2834 }
2835 pThis->Ctx.rip.u = pThis->CodePgRip + offCode;
2836 Bs3MemCpy(pbCode, pThis->abCurInstr, pThis->cbCurInstr);
2837
2838 if (Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr, pHdr->cbSelector, pHdr->cbInput, NULL, pbCode))
2839 {
2840 /* Run the instruction. */
2841 BS3CG1_DPRINTF(("dbg: Running test #%u\n", pThis->iTest));
2842 //Bs3RegCtxPrint(&pThis->Ctx);
2843 if (pThis->fWorkExtCtx)
2844 Bs3ExtCtxRestore(pThis->pExtCtx);
2845 Bs3TrapSetJmpAndRestore(&pThis->Ctx, &pThis->TrapFrame);
2846 if (pThis->fWorkExtCtx)
2847 Bs3ExtCtxSave(pThis->pResultExtCtx);
2848 BS3CG1_DPRINTF(("dbg: bXcpt=%#x rip=%RX64 -> %RX64\n",
2849 pThis->TrapFrame.bXcpt, pThis->Ctx.rip.u, pThis->TrapFrame.Ctx.rip.u));
2850
2851 /*
2852 * Apply the output modification program to the context.
2853 */
2854 pThis->Ctx.rflags.u32 &= ~X86_EFL_RF;
2855 pThis->Ctx.rflags.u32 |= pThis->TrapFrame.Ctx.rflags.u32 & X86_EFL_RF;
2856 pThis->bValueXcpt = UINT8_MAX;
2857 if ( fInvalidInstr
2858 || Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr,
2859 pHdr->cbSelector + pHdr->cbInput, pHdr->cbOutput,
2860 &pThis->TrapFrame.Ctx, NULL /*pbCode*/))
2861 {
2862 Bs3Cg1CheckResult(pThis, fInvalidInstr, bTestXcptExpected, iEncoding);
2863 }
2864 }
2865 }
2866 else
2867 BS3CG1_DPRINTF(("dbg: Skipping #%u\n", pThis->iTest));
2868
2869 /* advance */
2870 if (pHdr->fLast)
2871 {
2872 BS3CG1_DPRINTF(("dbg: Last\n\n"));
2873 break;
2874 }
2875 pHdr = (PCBS3CG1TESTHDR)((uint8_t BS3_FAR *)(pHdr + 1) + pHdr->cbInput + pHdr->cbOutput + pHdr->cbSelector);
2876 }
2877 }
2878 }
2879
2880 /*
2881 * Clean up (segment registers, etc) and get the next CPU config.
2882 */
2883 Bs3Cg1EncodeCleanup(pThis);
2884 if (!Bs3Cg1CpuSetupNext(pThis, iCpuSetup, &fInvalidInstr))
2885 break;
2886 }
2887 }
2888
2889 return 0;
2890}
2891
2892
2893BS3_DECL_FAR(uint8_t) BS3_CMN_NM(Bs3Cg1Worker)(uint8_t bMode)
2894{
2895 uint8_t bRet = 1;
2896 BS3CG1STATE This;
2897
2898#if 0
2899 /* (for debugging) */
2900 if (bMode != BS3_MODE_PP32)
2901 return BS3TESTDOMODE_SKIPPED;
2902#endif
2903
2904 if (BS3_CMN_NM(Bs3Cg1Init)(&This, bMode))
2905 {
2906 bRet = BS3_CMN_NM(Bs3Cg1WorkerInner)(&This);
2907 Bs3TestSubDone();
2908 }
2909 Bs3Cg1Destroy(&This);
2910
2911#if 0
2912 /* (for debugging) */
2913 if (bMode >= BS3_MODE_PE16_32)
2914 {
2915 Bs3TestTerm();
2916 Bs3Shutdown();
2917 }
2918#endif
2919 return bRet;
2920}
2921
Note: See TracBrowser for help on using the repository browser.

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