VirtualBox

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

Last change on this file since 66403 was 66392, checked in by vboxsync, 8 years ago

x86.h,IEMAll.cpp,bs3-cpu-generated-1: s/X86_MXSCR_/X86_MXCSR_/

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 135.7 KB
Line 
1/* $Id: bs3-cpu-generated-1-template.c 66392 2017-04-02 19:44:26Z 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_ST0] = */ 12,
408 /* [BS3CG1DST_ST1] = */ 12,
409 /* [BS3CG1DST_ST2] = */ 12,
410 /* [BS3CG1DST_ST3] = */ 12,
411 /* [BS3CG1DST_ST4] = */ 12,
412 /* [BS3CG1DST_ST5] = */ 12,
413 /* [BS3CG1DST_ST6] = */ 12,
414 /* [BS3CG1DST_ST7] = */ 12,
415 /* [BS3CG1DST_MM0] = */ 8,
416 /* [BS3CG1DST_MM1] = */ 8,
417 /* [BS3CG1DST_MM2] = */ 8,
418 /* [BS3CG1DST_MM3] = */ 8,
419 /* [BS3CG1DST_MM4] = */ 8,
420 /* [BS3CG1DST_MM5] = */ 8,
421 /* [BS3CG1DST_MM6] = */ 8,
422 /* [BS3CG1DST_MM7] = */ 8,
423 /* [BS3CG1DST_XMM0] = */ 16,
424 /* [BS3CG1DST_XMM1] = */ 16,
425 /* [BS3CG1DST_XMM2] = */ 16,
426 /* [BS3CG1DST_XMM3] = */ 16,
427 /* [BS3CG1DST_XMM4] = */ 16,
428 /* [BS3CG1DST_XMM5] = */ 16,
429 /* [BS3CG1DST_XMM6] = */ 16,
430 /* [BS3CG1DST_XMM7] = */ 16,
431 /* [BS3CG1DST_XMM8] = */ 16,
432 /* [BS3CG1DST_XMM9] = */ 16,
433 /* [BS3CG1DST_XMM10] = */ 16,
434 /* [BS3CG1DST_XMM11] = */ 16,
435 /* [BS3CG1DST_XMM12] = */ 16,
436 /* [BS3CG1DST_XMM13] = */ 16,
437 /* [BS3CG1DST_XMM14] = */ 16,
438 /* [BS3CG1DST_XMM15] = */ 16,
439 /* [BS3CG1DST_XMM0_LO] = */ 8,
440 /* [BS3CG1DST_XMM1_LO] = */ 8,
441 /* [BS3CG1DST_XMM2_LO] = */ 8,
442 /* [BS3CG1DST_XMM3_LO] = */ 8,
443 /* [BS3CG1DST_XMM4_LO] = */ 8,
444 /* [BS3CG1DST_XMM5_LO] = */ 8,
445 /* [BS3CG1DST_XMM6_LO] = */ 8,
446 /* [BS3CG1DST_XMM7_LO] = */ 8,
447 /* [BS3CG1DST_XMM8_LO] = */ 8,
448 /* [BS3CG1DST_XMM9_LO] = */ 8,
449 /* [BS3CG1DST_XMM10_LO] = */ 8,
450 /* [BS3CG1DST_XMM11_LO] = */ 8,
451 /* [BS3CG1DST_XMM12_LO] = */ 8,
452 /* [BS3CG1DST_XMM13_LO] = */ 8,
453 /* [BS3CG1DST_XMM14_LO] = */ 8,
454 /* [BS3CG1DST_XMM15_LO] = */ 8,
455 /* [BS3CG1DST_XMM0_HI] = */ 8,
456 /* [BS3CG1DST_XMM1_HI] = */ 8,
457 /* [BS3CG1DST_XMM2_HI] = */ 8,
458 /* [BS3CG1DST_XMM3_HI] = */ 8,
459 /* [BS3CG1DST_XMM4_HI] = */ 8,
460 /* [BS3CG1DST_XMM5_HI] = */ 8,
461 /* [BS3CG1DST_XMM6_HI] = */ 8,
462 /* [BS3CG1DST_XMM7_HI] = */ 8,
463 /* [BS3CG1DST_XMM8_HI] = */ 8,
464 /* [BS3CG1DST_XMM9_HI] = */ 8,
465 /* [BS3CG1DST_XMM10_HI] = */ 8,
466 /* [BS3CG1DST_XMM11_HI] = */ 8,
467 /* [BS3CG1DST_XMM12_HI] = */ 8,
468 /* [BS3CG1DST_XMM13_HI] = */ 8,
469 /* [BS3CG1DST_XMM14_HI] = */ 8,
470 /* [BS3CG1DST_XMM15_HI] = */ 8,
471 /* [BS3CG1DST_XMM0_LO_ZX] = */ 8,
472 /* [BS3CG1DST_XMM1_LO_ZX] = */ 8,
473 /* [BS3CG1DST_XMM2_LO_ZX] = */ 8,
474 /* [BS3CG1DST_XMM3_LO_ZX] = */ 8,
475 /* [BS3CG1DST_XMM4_LO_ZX] = */ 8,
476 /* [BS3CG1DST_XMM5_LO_ZX] = */ 8,
477 /* [BS3CG1DST_XMM6_LO_ZX] = */ 8,
478 /* [BS3CG1DST_XMM7_LO_ZX] = */ 8,
479 /* [BS3CG1DST_XMM8_LO_ZX] = */ 8,
480 /* [BS3CG1DST_XMM9_LO_ZX] = */ 8,
481 /* [BS3CG1DST_XMM10_LO_ZX] = */ 8,
482 /* [BS3CG1DST_XMM11_LO_ZX] = */ 8,
483 /* [BS3CG1DST_XMM12_LO_ZX] = */ 8,
484 /* [BS3CG1DST_XMM13_LO_ZX] = */ 8,
485 /* [BS3CG1DST_XMM14_LO_ZX] = */ 8,
486 /* [BS3CG1DST_XMM15_LO_ZX] = */ 8,
487 /* [BS3CG1DST_XMM0_DW0] = */ 4,
488 /* [BS3CG1DST_XMM1_DW0] = */ 4,
489 /* [BS3CG1DST_XMM2_DW0] = */ 4,
490 /* [BS3CG1DST_XMM3_DW0] = */ 4,
491 /* [BS3CG1DST_XMM4_DW0] = */ 4,
492 /* [BS3CG1DST_XMM5_DW0] = */ 4,
493 /* [BS3CG1DST_XMM6_DW0] = */ 4,
494 /* [BS3CG1DST_XMM7_DW0] = */ 4,
495 /* [BS3CG1DST_XMM8_DW0] = */ 4,
496 /* [BS3CG1DST_XMM9_DW0] = */ 4,
497 /* [BS3CG1DST_XMM10_DW0] = */ 4,
498 /* [BS3CG1DST_XMM11_DW0] = */ 4,
499 /* [BS3CG1DST_XMM12_DW0] = */ 4,
500 /* [BS3CG1DST_XMM13_DW0] = */ 4,
501 /* [BS3CG1DST_XMM14_DW0] = */ 4,
502 /* [BS3CG1DST_XMM15_DW0] = */ 4,
503 /* [BS3CG1DST_YMM0] = */ 32,
504 /* [BS3CG1DST_YMM1] = */ 32,
505 /* [BS3CG1DST_YMM2] = */ 32,
506 /* [BS3CG1DST_YMM3] = */ 32,
507 /* [BS3CG1DST_YMM4] = */ 32,
508 /* [BS3CG1DST_YMM5] = */ 32,
509 /* [BS3CG1DST_YMM6] = */ 32,
510 /* [BS3CG1DST_YMM7] = */ 32,
511 /* [BS3CG1DST_YMM8] = */ 32,
512 /* [BS3CG1DST_YMM9] = */ 32,
513 /* [BS3CG1DST_YMM10] = */ 32,
514 /* [BS3CG1DST_YMM11] = */ 32,
515 /* [BS3CG1DST_YMM12] = */ 32,
516 /* [BS3CG1DST_YMM13] = */ 32,
517 /* [BS3CG1DST_YMM14] = */ 32,
518 /* [BS3CG1DST_YMM15] = */ 32,
519
520 /* [BS3CG1DST_VALUE_XCPT] = */ 1,
521};
522AssertCompile(RT_ELEMENTS(g_acbBs3Cg1DstFields) == BS3CG1DST_END);
523
524/** Destination field offset indexed by bBS3CG1DST.
525 * Zero means operand size sized. */
526static const unsigned g_aoffBs3Cg1DstFields[] =
527{
528 /* [BS3CG1DST_INVALID] = */ ~0U,
529 /* [BS3CG1DST_OP1] = */ ~0U,
530 /* [BS3CG1DST_OP2] = */ ~0U,
531 /* [BS3CG1DST_OP3] = */ ~0U,
532 /* [BS3CG1DST_OP4] = */ ~0U,
533 /* [BS3CG1DST_EFL] = */ RT_OFFSETOF(BS3REGCTX, rflags),
534 /* [BS3CG1DST_EFL_UNDEF]=*/ ~0, /* special field */
535
536 /* [BS3CG1DST_AL] = */ RT_OFFSETOF(BS3REGCTX, rax.u8),
537 /* [BS3CG1DST_CL] = */ RT_OFFSETOF(BS3REGCTX, rcx.u8),
538 /* [BS3CG1DST_DL] = */ RT_OFFSETOF(BS3REGCTX, rdx.u8),
539 /* [BS3CG1DST_BL] = */ RT_OFFSETOF(BS3REGCTX, rbx.u8),
540 /* [BS3CG1DST_AH] = */ RT_OFFSETOF(BS3REGCTX, rax.b.bHi),
541 /* [BS3CG1DST_CH] = */ RT_OFFSETOF(BS3REGCTX, rcx.b.bHi),
542 /* [BS3CG1DST_DH] = */ RT_OFFSETOF(BS3REGCTX, rdx.b.bHi),
543 /* [BS3CG1DST_BH] = */ RT_OFFSETOF(BS3REGCTX, rbx.b.bHi),
544 /* [BS3CG1DST_SPL] = */ RT_OFFSETOF(BS3REGCTX, rsp.u8),
545 /* [BS3CG1DST_BPL] = */ RT_OFFSETOF(BS3REGCTX, rbp.u8),
546 /* [BS3CG1DST_SIL] = */ RT_OFFSETOF(BS3REGCTX, rsi.u8),
547 /* [BS3CG1DST_DIL] = */ RT_OFFSETOF(BS3REGCTX, rdi.u8),
548 /* [BS3CG1DST_R8L] = */ RT_OFFSETOF(BS3REGCTX, r8.u8),
549 /* [BS3CG1DST_R9L] = */ RT_OFFSETOF(BS3REGCTX, r9.u8),
550 /* [BS3CG1DST_R10L] = */ RT_OFFSETOF(BS3REGCTX, r10.u8),
551 /* [BS3CG1DST_R11L] = */ RT_OFFSETOF(BS3REGCTX, r11.u8),
552 /* [BS3CG1DST_R12L] = */ RT_OFFSETOF(BS3REGCTX, r12.u8),
553 /* [BS3CG1DST_R13L] = */ RT_OFFSETOF(BS3REGCTX, r13.u8),
554 /* [BS3CG1DST_R14L] = */ RT_OFFSETOF(BS3REGCTX, r14.u8),
555 /* [BS3CG1DST_R15L] = */ RT_OFFSETOF(BS3REGCTX, r15.u8),
556
557 /* [BS3CG1DST_AX] = */ RT_OFFSETOF(BS3REGCTX, rax.u16),
558 /* [BS3CG1DST_CX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u16),
559 /* [BS3CG1DST_DX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u16),
560 /* [BS3CG1DST_BX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u16),
561 /* [BS3CG1DST_SP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u16),
562 /* [BS3CG1DST_BP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u16),
563 /* [BS3CG1DST_SI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u16),
564 /* [BS3CG1DST_DI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u16),
565 /* [BS3CG1DST_R8W] = */ RT_OFFSETOF(BS3REGCTX, r8.u16),
566 /* [BS3CG1DST_R9W] = */ RT_OFFSETOF(BS3REGCTX, r9.u16),
567 /* [BS3CG1DST_R10W] = */ RT_OFFSETOF(BS3REGCTX, r10.u16),
568 /* [BS3CG1DST_R11W] = */ RT_OFFSETOF(BS3REGCTX, r11.u16),
569 /* [BS3CG1DST_R12W] = */ RT_OFFSETOF(BS3REGCTX, r12.u16),
570 /* [BS3CG1DST_R13W] = */ RT_OFFSETOF(BS3REGCTX, r13.u16),
571 /* [BS3CG1DST_R14W] = */ RT_OFFSETOF(BS3REGCTX, r14.u16),
572 /* [BS3CG1DST_R15W] = */ RT_OFFSETOF(BS3REGCTX, r15.u16),
573
574 /* [BS3CG1DST_EAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u32),
575 /* [BS3CG1DST_ECX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u32),
576 /* [BS3CG1DST_EDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u32),
577 /* [BS3CG1DST_EBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u32),
578 /* [BS3CG1DST_ESP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u32),
579 /* [BS3CG1DST_EBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u32),
580 /* [BS3CG1DST_ESI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u32),
581 /* [BS3CG1DST_EDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u32),
582 /* [BS3CG1DST_R8D] = */ RT_OFFSETOF(BS3REGCTX, r8.u32),
583 /* [BS3CG1DST_R9D] = */ RT_OFFSETOF(BS3REGCTX, r9.u32),
584 /* [BS3CG1DST_R10D] = */ RT_OFFSETOF(BS3REGCTX, r10.u32),
585 /* [BS3CG1DST_R11D] = */ RT_OFFSETOF(BS3REGCTX, r11.u32),
586 /* [BS3CG1DST_R12D] = */ RT_OFFSETOF(BS3REGCTX, r12.u32),
587 /* [BS3CG1DST_R13D] = */ RT_OFFSETOF(BS3REGCTX, r13.u32),
588 /* [BS3CG1DST_R14D] = */ RT_OFFSETOF(BS3REGCTX, r14.u32),
589 /* [BS3CG1DST_R15D] = */ RT_OFFSETOF(BS3REGCTX, r15.u32),
590
591 /* [BS3CG1DST_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u64),
592 /* [BS3CG1DST_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u64),
593 /* [BS3CG1DST_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u64),
594 /* [BS3CG1DST_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u64),
595 /* [BS3CG1DST_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u64),
596 /* [BS3CG1DST_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u64),
597 /* [BS3CG1DST_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u64),
598 /* [BS3CG1DST_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u64),
599 /* [BS3CG1DST_R8] = */ RT_OFFSETOF(BS3REGCTX, r8.u64),
600 /* [BS3CG1DST_R9] = */ RT_OFFSETOF(BS3REGCTX, r9.u64),
601 /* [BS3CG1DST_R10] = */ RT_OFFSETOF(BS3REGCTX, r10.u64),
602 /* [BS3CG1DST_R11] = */ RT_OFFSETOF(BS3REGCTX, r11.u64),
603 /* [BS3CG1DST_R12] = */ RT_OFFSETOF(BS3REGCTX, r12.u64),
604 /* [BS3CG1DST_R13] = */ RT_OFFSETOF(BS3REGCTX, r13.u64),
605 /* [BS3CG1DST_R14] = */ RT_OFFSETOF(BS3REGCTX, r14.u64),
606 /* [BS3CG1DST_R15] = */ RT_OFFSETOF(BS3REGCTX, r15.u64),
607
608 /* [BS3CG1DST_OZ_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax),
609 /* [BS3CG1DST_OZ_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx),
610 /* [BS3CG1DST_OZ_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx),
611 /* [BS3CG1DST_OZ_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx),
612 /* [BS3CG1DST_OZ_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp),
613 /* [BS3CG1DST_OZ_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp),
614 /* [BS3CG1DST_OZ_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi),
615 /* [BS3CG1DST_OZ_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi),
616 /* [BS3CG1DST_OZ_R8] = */ RT_OFFSETOF(BS3REGCTX, r8),
617 /* [BS3CG1DST_OZ_R9] = */ RT_OFFSETOF(BS3REGCTX, r9),
618 /* [BS3CG1DST_OZ_R10] = */ RT_OFFSETOF(BS3REGCTX, r10),
619 /* [BS3CG1DST_OZ_R11] = */ RT_OFFSETOF(BS3REGCTX, r11),
620 /* [BS3CG1DST_OZ_R12] = */ RT_OFFSETOF(BS3REGCTX, r12),
621 /* [BS3CG1DST_OZ_R13] = */ RT_OFFSETOF(BS3REGCTX, r13),
622 /* [BS3CG1DST_OZ_R14] = */ RT_OFFSETOF(BS3REGCTX, r14),
623 /* [BS3CG1DST_OZ_R15] = */ RT_OFFSETOF(BS3REGCTX, r15),
624
625 /* [BS3CG1DST_FCW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FCW),
626 /* [BS3CG1DST_FSW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FSW),
627 /* [BS3CG1DST_FTW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FTW),
628 /* [BS3CG1DST_FOP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FOP),
629 /* [BS3CG1DST_FPUIP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUIP),
630 /* [BS3CG1DST_FPUCS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.CS),
631 /* [BS3CG1DST_FPUDP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUDP),
632 /* [BS3CG1DST_FPUDS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.DS),
633 /* [BS3CG1DST_MXCSR] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.MXCSR),
634 /* [BS3CG1DST_ST0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
635 /* [BS3CG1DST_ST1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
636 /* [BS3CG1DST_ST2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
637 /* [BS3CG1DST_ST3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
638 /* [BS3CG1DST_ST4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
639 /* [BS3CG1DST_ST5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
640 /* [BS3CG1DST_ST6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
641 /* [BS3CG1DST_ST7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
642 /* [BS3CG1DST_MM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
643 /* [BS3CG1DST_MM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
644 /* [BS3CG1DST_MM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
645 /* [BS3CG1DST_MM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
646 /* [BS3CG1DST_MM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
647 /* [BS3CG1DST_MM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
648 /* [BS3CG1DST_MM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
649 /* [BS3CG1DST_MM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
650
651 /* [BS3CG1DST_XMM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
652 /* [BS3CG1DST_XMM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
653 /* [BS3CG1DST_XMM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
654 /* [BS3CG1DST_XMM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
655 /* [BS3CG1DST_XMM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
656 /* [BS3CG1DST_XMM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
657 /* [BS3CG1DST_XMM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
658 /* [BS3CG1DST_XMM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
659 /* [BS3CG1DST_XMM8] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
660 /* [BS3CG1DST_XMM9] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
661 /* [BS3CG1DST_XMM10] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
662 /* [BS3CG1DST_XMM11] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
663 /* [BS3CG1DST_XMM12] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
664 /* [BS3CG1DST_XMM13] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
665 /* [BS3CG1DST_XMM14] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
666 /* [BS3CG1DST_XMM15] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
667 /* [BS3CG1DST_XMM0_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
668 /* [BS3CG1DST_XMM1_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
669 /* [BS3CG1DST_XMM2_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
670 /* [BS3CG1DST_XMM3_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
671 /* [BS3CG1DST_XMM4_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
672 /* [BS3CG1DST_XMM5_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
673 /* [BS3CG1DST_XMM6_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
674 /* [BS3CG1DST_XMM7_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
675 /* [BS3CG1DST_XMM8_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
676 /* [BS3CG1DST_XMM9_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
677 /* [BS3CG1DST_XMM10_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
678 /* [BS3CG1DST_XMM11_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
679 /* [BS3CG1DST_XMM12_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
680 /* [BS3CG1DST_XMM13_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
681 /* [BS3CG1DST_XMM14_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
682 /* [BS3CG1DST_XMM15_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
683 /* [BS3CG1DST_XMM0_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]) + sizeof(uint64_t),
684 /* [BS3CG1DST_XMM1_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]) + sizeof(uint64_t),
685 /* [BS3CG1DST_XMM2_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]) + sizeof(uint64_t),
686 /* [BS3CG1DST_XMM3_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]) + sizeof(uint64_t),
687 /* [BS3CG1DST_XMM4_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]) + sizeof(uint64_t),
688 /* [BS3CG1DST_XMM5_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]) + sizeof(uint64_t),
689 /* [BS3CG1DST_XMM6_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]) + sizeof(uint64_t),
690 /* [BS3CG1DST_XMM7_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]) + sizeof(uint64_t),
691 /* [BS3CG1DST_XMM8_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]) + sizeof(uint64_t),
692 /* [BS3CG1DST_XMM9_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]) + sizeof(uint64_t),
693 /* [BS3CG1DST_XMM10_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]) + sizeof(uint64_t),
694 /* [BS3CG1DST_XMM11_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]) + sizeof(uint64_t),
695 /* [BS3CG1DST_XMM12_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]) + sizeof(uint64_t),
696 /* [BS3CG1DST_XMM13_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]) + sizeof(uint64_t),
697 /* [BS3CG1DST_XMM14_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]) + sizeof(uint64_t),
698 /* [BS3CG1DST_XMM15_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) + sizeof(uint64_t),
699 /* [BS3CG1DST_XMM0_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
700 /* [BS3CG1DST_XMM1_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
701 /* [BS3CG1DST_XMM2_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
702 /* [BS3CG1DST_XMM3_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
703 /* [BS3CG1DST_XMM4_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
704 /* [BS3CG1DST_XMM5_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
705 /* [BS3CG1DST_XMM6_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
706 /* [BS3CG1DST_XMM7_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
707 /* [BS3CG1DST_XMM8_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
708 /* [BS3CG1DST_XMM9_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
709 /* [BS3CG1DST_XMM10_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
710 /* [BS3CG1DST_XMM11_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
711 /* [BS3CG1DST_XMM12_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
712 /* [BS3CG1DST_XMM13_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
713 /* [BS3CG1DST_XMM14_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
714 /* [BS3CG1DST_XMM15_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
715 /* [BS3CG1DST_XMM0_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
716 /* [BS3CG1DST_XMM1_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
717 /* [BS3CG1DST_XMM2_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
718 /* [BS3CG1DST_XMM3_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
719 /* [BS3CG1DST_XMM4_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
720 /* [BS3CG1DST_XMM5_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
721 /* [BS3CG1DST_XMM6_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
722 /* [BS3CG1DST_XMM7_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
723 /* [BS3CG1DST_XMM8_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
724 /* [BS3CG1DST_XMM9_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
725 /* [BS3CG1DST_XMM10_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
726 /* [BS3CG1DST_XMM11_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
727 /* [BS3CG1DST_XMM12_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
728 /* [BS3CG1DST_XMM13_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
729 /* [BS3CG1DST_XMM14_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
730 /* [BS3CG1DST_XMM15_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
731
732 /* [BS3CG1DST_YMM0] = */ ~0U,
733 /* [BS3CG1DST_YMM1] = */ ~0U,
734 /* [BS3CG1DST_YMM2] = */ ~0U,
735 /* [BS3CG1DST_YMM3] = */ ~0U,
736 /* [BS3CG1DST_YMM4] = */ ~0U,
737 /* [BS3CG1DST_YMM5] = */ ~0U,
738 /* [BS3CG1DST_YMM6] = */ ~0U,
739 /* [BS3CG1DST_YMM7] = */ ~0U,
740 /* [BS3CG1DST_YMM8] = */ ~0U,
741 /* [BS3CG1DST_YMM9] = */ ~0U,
742 /* [BS3CG1DST_YMM10] = */ ~0U,
743 /* [BS3CG1DST_YMM11] = */ ~0U,
744 /* [BS3CG1DST_YMM12] = */ ~0U,
745 /* [BS3CG1DST_YMM13] = */ ~0U,
746 /* [BS3CG1DST_YMM14] = */ ~0U,
747 /* [BS3CG1DST_YMM15] = */ ~0U,
748
749 /* [BS3CG1DST_VALUE_XCPT] = */ ~0U,
750};
751AssertCompile(RT_ELEMENTS(g_aoffBs3Cg1DstFields) == BS3CG1DST_END);
752
753#ifdef BS3CG1_DEBUG_CTX_MOD
754/** Destination field names. */
755static const struct { char sz[12]; } g_aszBs3Cg1DstFields[] =
756{
757 { "INVALID" },
758 { "OP1" },
759 { "OP2" },
760 { "OP3" },
761 { "OP4" },
762 { "EFL" },
763 { "EFL_UND" },
764
765 { "AL" },
766 { "CL" },
767 { "DL" },
768 { "BL" },
769 { "AH" },
770 { "CH" },
771 { "DH" },
772 { "BH" },
773 { "SPL" },
774 { "BPL" },
775 { "SIL" },
776 { "DIL" },
777 { "R8L" },
778 { "R9L" },
779 { "R10L" },
780 { "R11L" },
781 { "R12L" },
782 { "R13L" },
783 { "R14L" },
784 { "R15L" },
785
786 { "AX" },
787 { "CX" },
788 { "DX" },
789 { "BX" },
790 { "SP" },
791 { "BP" },
792 { "SI" },
793 { "DI" },
794 { "R8W" },
795 { "R9W" },
796 { "R10W" },
797 { "R11W" },
798 { "R12W" },
799 { "R13W" },
800 { "R14W" },
801 { "R15W" },
802
803 { "EAX" },
804 { "ECX" },
805 { "EDX" },
806 { "EBX" },
807 { "ESP" },
808 { "EBP" },
809 { "ESI" },
810 { "EDI" },
811 { "R8D" },
812 { "R9D" },
813 { "R10D" },
814 { "R11D" },
815 { "R12D" },
816 { "R13D" },
817 { "R14D" },
818 { "R15D" },
819
820 { "RAX" },
821 { "RCX" },
822 { "RDX" },
823 { "RBX" },
824 { "RSP" },
825 { "RBP" },
826 { "RSI" },
827 { "RDI" },
828 { "R8" },
829 { "R9" },
830 { "R10" },
831 { "R11" },
832 { "R12" },
833 { "R13" },
834 { "R14" },
835 { "R15" },
836
837 { "OZ_RAX" },
838 { "OZ_RCX" },
839 { "OZ_RDX" },
840 { "OZ_RBX" },
841 { "OZ_RSP" },
842 { "OZ_RBP" },
843 { "OZ_RSI" },
844 { "OZ_RDI" },
845 { "OZ_R8" },
846 { "OZ_R9" },
847 { "OZ_R10" },
848 { "OZ_R11" },
849 { "OZ_R12" },
850 { "OZ_R13" },
851 { "OZ_R14" },
852 { "OZ_R15" },
853
854 { "FCW" },
855 { "FSW" },
856 { "FTW" },
857 { "FOP" },
858 { "FPUIP" },
859 { "FPUCS" },
860 { "FPUDP" },
861 { "FPUDS" },
862 { "MXCSR" },
863 { "MXCSR_M" },
864 { "ST0" },
865 { "ST1" },
866 { "ST2" },
867 { "ST3" },
868 { "ST4" },
869 { "ST5" },
870 { "ST6" },
871 { "ST7" },
872 { "MM0" },
873 { "MM1" },
874 { "MM2" },
875 { "MM3" },
876 { "MM4" },
877 { "MM5" },
878 { "MM6" },
879 { "MM7" },
880 { "XMM0" },
881 { "XMM1" },
882 { "XMM2" },
883 { "XMM3" },
884 { "XMM4" },
885 { "XMM5" },
886 { "XMM6" },
887 { "XMM7" },
888 { "XMM8" },
889 { "XMM9" },
890 { "XMM10" },
891 { "XMM11" },
892 { "XMM12" },
893 { "XMM13" },
894 { "XMM14" },
895 { "XMM15" },
896 { "XMM0_LO" },
897 { "XMM1_LO" },
898 { "XMM2_LO" },
899 { "XMM3_LO" },
900 { "XMM4_LO" },
901 { "XMM5_LO" },
902 { "XMM6_LO" },
903 { "XMM7_LO" },
904 { "XMM8_LO" },
905 { "XMM9_LO" },
906 { "XMM10_LO" },
907 { "XMM11_LO" },
908 { "XMM12_LO" },
909 { "XMM13_LO" },
910 { "XMM14_LO" },
911 { "XMM15_LO" },
912 { "XMM0_HI" },
913 { "XMM1_HI" },
914 { "XMM2_HI" },
915 { "XMM3_HI" },
916 { "XMM4_HI" },
917 { "XMM5_HI" },
918 { "XMM6_HI" },
919 { "XMM7_HI" },
920 { "XMM8_HI" },
921 { "XMM9_HI" },
922 { "XMM10_HI" },
923 { "XMM11_HI" },
924 { "XMM12_HI" },
925 { "XMM13_HI" },
926 { "XMM14_HI" },
927 { "XMM15_HI" },
928 { "XMM0_LO_ZX" },
929 { "XMM1_LO_ZX" },
930 { "XMM2_LO_ZX" },
931 { "XMM3_LO_ZX" },
932 { "XMM4_LO_ZX" },
933 { "XMM5_LO_ZX" },
934 { "XMM6_LO_ZX" },
935 { "XMM7_LO_ZX" },
936 { "XMM8_LO_ZX" },
937 { "XMM9_LO_ZX" },
938 { "XMM10_LO_ZX" },
939 { "XMM11_LO_ZX" },
940 { "XMM12_LO_ZX" },
941 { "XMM13_LO_ZX" },
942 { "XMM14_LO_ZX" },
943 { "XMM15_LO_ZX" },
944 { "XMM0_DW0" },
945 { "XMM1_DW0" },
946 { "XMM2_DW0" },
947 { "XMM3_DW0" },
948 { "XMM4_DW0" },
949 { "XMM5_DW0" },
950 { "XMM6_DW0" },
951 { "XMM7_DW0" },
952 { "XMM8_DW0" },
953 { "XMM9_DW0" },
954 { "XMM10_DW0" },
955 { "XMM11_DW0" },
956 { "XMM12_DW0" },
957 { "XMM13_DW0" },
958 { "XMM14_DW0" },
959 { "XMM15_DW0" },
960 { "YMM0" },
961 { "YMM1" },
962 { "YMM2" },
963 { "YMM3" },
964 { "YMM4" },
965 { "YMM5" },
966 { "YMM6" },
967 { "YMM7" },
968 { "YMM8" },
969 { "YMM9" },
970 { "YMM10" },
971 { "YMM11" },
972 { "YMM12" },
973 { "YMM13" },
974 { "YMM14" },
975 { "YMM15" },
976
977 { "VALXCPT" },
978};
979AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) == BS3CG1DST_END);
980
981#endif
982
983#if 0
984static const struct
985{
986 uint8_t cbPrefixes;
987 uint8_t abPrefixes[14];
988 uint16_t fEffective;
989} g_aPrefixVariations[] =
990{
991 { 0, { 0x00 }, BS3CG1_PF_NONE },
992
993 { 1, { P_OZ }, BS3CG1_PF_OZ },
994 { 1, { P_CS }, BS3CG1_PF_CS },
995 { 1, { P_DS }, BS3CG1_PF_DS },
996 { 1, { P_ES }, BS3CG1_PF_ES },
997 { 1, { P_FS }, BS3CG1_PF_FS },
998 { 1, { P_GS }, BS3CG1_PF_GS },
999 { 1, { P_SS }, BS3CG1_PF_SS },
1000 { 1, { P_LK }, BS3CG1_PF_LK },
1001
1002 { 2, { P_CS, P_OZ, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
1003 { 2, { P_DS, P_OZ, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
1004 { 2, { P_ES, P_OZ, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
1005 { 2, { P_FS, P_OZ, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
1006 { 2, { P_GS, P_OZ, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
1007 { 2, { P_GS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1008 { 2, { P_SS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1009
1010 { 2, { P_OZ, P_CS, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
1011 { 2, { P_OZ, P_DS, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
1012 { 2, { P_OZ, P_ES, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
1013 { 2, { P_OZ, P_FS, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
1014 { 2, { P_OZ, P_GS, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
1015 { 2, { P_OZ, P_GS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1016 { 2, { P_OZ, P_SS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1017};
1018
1019static const uint16_t g_afPfxKindToIgnoredFlags[BS3CG1PFXKIND_END] =
1020{
1021 /* [BS3CG1PFXKIND_INVALID] = */ UINT16_MAX,
1022 /* [BS3CG1PFXKIND_MODRM] = */ 0,
1023 /* [BS3CG1PFXKIND_MODRM_NO_OP_SIZES] = */ BS3CG1_PF_OZ | BS3CG1_PF_W,
1024};
1025
1026#endif
1027
1028
1029/**
1030 * Checks if >= 16 byte SSE/AVX alignment are exempted for the exception type.
1031 *
1032 * @returns true / false.
1033 * @param enmXcptType The type to check.
1034 */
1035static bool Bs3Cg1XcptTypeIsUnaligned(BS3CG1XCPTTYPE enmXcptType)
1036{
1037 switch (enmXcptType)
1038 {
1039 case BS3CG1XCPTTYPE_4UA:
1040 case BS3CG1XCPTTYPE_5:
1041 return true;
1042 default:
1043 return false;
1044 }
1045}
1046
1047
1048DECLINLINE(unsigned) Bs3Cg1InsertReqPrefix(PBS3CG1STATE pThis, unsigned offDst)
1049{
1050 switch (pThis->enmPrefixKind)
1051 {
1052 case BS3CG1PFXKIND_REQ_66:
1053 pThis->abCurInstr[offDst] = 0x66;
1054 break;
1055 case BS3CG1PFXKIND_REQ_F2:
1056 pThis->abCurInstr[offDst] = 0xf2;
1057 break;
1058 case BS3CG1PFXKIND_REQ_F3:
1059 pThis->abCurInstr[offDst] = 0xf3;
1060 break;
1061 default:
1062 return offDst;
1063 }
1064 return offDst + 1;
1065}
1066
1067
1068DECLINLINE(unsigned) Bs3Cg1InsertOpcodes(PBS3CG1STATE pThis, unsigned offDst)
1069{
1070 switch (pThis->cbOpcodes)
1071 {
1072 case 4: pThis->abCurInstr[offDst + 3] = pThis->abOpcodes[3];
1073 case 3: pThis->abCurInstr[offDst + 2] = pThis->abOpcodes[2];
1074 case 2: pThis->abCurInstr[offDst + 1] = pThis->abOpcodes[1];
1075 case 1: pThis->abCurInstr[offDst] = pThis->abOpcodes[0];
1076 return offDst + pThis->cbOpcodes;
1077
1078 default:
1079 BS3_ASSERT(0);
1080 return 0;
1081 }
1082}
1083
1084
1085/**
1086 * Cleans up state and context changes made by the encoder.
1087 *
1088 * @param pThis The state.
1089 */
1090static void Bs3Cg1EncodeCleanup(PBS3CG1STATE pThis)
1091{
1092 /* Restore the DS registers in the contexts. */
1093 unsigned iRing = 4;
1094 while (iRing-- > 0)
1095 pThis->aInitialCtxs[iRing].ds = pThis->aSavedSegRegs[iRing].ds;
1096
1097 switch (pThis->enmEncoding)
1098 {
1099 /* Most encodings currently doesn't need any special cleaning up. */
1100 default:
1101 return;
1102 }
1103}
1104
1105
1106static unsigned Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
1107 uint8_t cbOp, uint8_t cbMissalign, BS3CG1OPLOC enmLocation)
1108{
1109 pThis->aOperands[pThis->iRmOp].idxField = BS3CG1DST_INVALID;
1110 pThis->aOperands[pThis->iRmOp].enmLocation = enmLocation;
1111 pThis->aOperands[pThis->iRmOp].cbOp = cbOp;
1112 pThis->aOperands[pThis->iRmOp].off = cbOp + cbMissalign;
1113
1114 if ( BS3_MODE_IS_16BIT_CODE(pThis->bMode)
1115 || (fAddrOverride && BS3_MODE_IS_32BIT_CODE(pThis->bMode)) )
1116 {
1117 /*
1118 * 16-bit code doing 16-bit or 32-bit addressing,
1119 * or 32-bit code doing 16-bit addressing.
1120 */
1121 unsigned iRing = 4;
1122 if (BS3_MODE_IS_RM_OR_V86(pThis->bMode))
1123 while (iRing-- > 0)
1124 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel;
1125 else
1126 while (iRing-- > 0)
1127 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel | iRing;
1128 if (!fAddrOverride || BS3_MODE_IS_32BIT_CODE(pThis->bMode))
1129 {
1130 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 6 /*disp16*/);
1131 *(uint16_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
1132 off += 2;
1133 }
1134 else
1135 {
1136 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1137 *(uint32_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMissalign;
1138 off += 4;
1139 }
1140 }
1141 else
1142 {
1143 /*
1144 * 32-bit code doing 32-bit addressing,
1145 * or 64-bit code doing either 64-bit or 32-bit addressing.
1146 */
1147 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1148 *(uint32_t *)&pThis->abCurInstr[off] = BS3_FP_OFF(pThis->pbDataPg) + X86_PAGE_SIZE - cbOp - cbMissalign;
1149
1150 /* In 64-bit mode we always have a rip relative encoding regardless of fAddrOverride. */
1151 if (BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1152 *(uint32_t *)&pThis->abCurInstr[off] -= BS3_FP_OFF(&pThis->pbCodePg[X86_PAGE_SIZE]);
1153 off += 4;
1154 }
1155
1156 /*
1157 * Fill the memory with 0xcc.
1158 */
1159 switch (cbOp + cbMissalign)
1160 {
1161 case 8: pThis->pbDataPg[X86_PAGE_SIZE - 8] = 0xcc; /* fall thru */
1162 case 7: pThis->pbDataPg[X86_PAGE_SIZE - 7] = 0xcc; /* fall thru */
1163 case 6: pThis->pbDataPg[X86_PAGE_SIZE - 6] = 0xcc; /* fall thru */
1164 case 5: pThis->pbDataPg[X86_PAGE_SIZE - 5] = 0xcc; /* fall thru */
1165 case 4: pThis->pbDataPg[X86_PAGE_SIZE - 4] = 0xcc; /* fall thru */
1166 case 3: pThis->pbDataPg[X86_PAGE_SIZE - 3] = 0xcc; /* fall thru */
1167 case 2: pThis->pbDataPg[X86_PAGE_SIZE - 2] = 0xcc; /* fall thru */
1168 case 1: pThis->pbDataPg[X86_PAGE_SIZE - 1] = 0xcc; /* fall thru */
1169 case 0: break;
1170 default:
1171 Bs3MemSet(&pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMissalign], 0xcc, cbOp - cbMissalign);
1172 break;
1173 }
1174
1175 return off;
1176}
1177
1178
1179/**
1180 * Encodes the next instruction.
1181 *
1182 * @returns Next iEncoding value. Returns @a iEncoding unchanged to indicate
1183 * that there are no more encodings to test.
1184 * @param pThis The state.
1185 * @param iEncoding The encoding to produce. Meaning is specific to each
1186 * BS3CG1ENC_XXX value and should be considered internal.
1187 */
1188static unsigned Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEncoding)
1189{
1190 unsigned off;
1191 unsigned cbOp;
1192
1193 pThis->bAlignmentXcpt = UINT8_MAX;
1194
1195 switch (pThis->enmEncoding)
1196 {
1197 case BS3CG1ENC_MODRM_Eb_Gb:
1198 /* Start by reg,reg encoding. */
1199 if (iEncoding == 0)
1200 {
1201 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1202 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xAX, X86_GREG_xCX);
1203 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_AL;
1204 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_CL;
1205 }
1206 else if (iEncoding == 1)
1207 {
1208 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_CH;
1209 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1210 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, 1, 0, BS3CG1OPLOC_MEM_RW);
1211 }
1212 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1213 {
1214 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_BH;
1215 pThis->abCurInstr[0] = P_AZ;
1216 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1217 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, 1, 0, BS3CG1OPLOC_MEM_RW);
1218 }
1219 else
1220 break;
1221 pThis->cbCurInstr = off;
1222 iEncoding++;
1223 break;
1224
1225 case BS3CG1ENC_MODRM_Gb_Eb:
1226 /* Start by reg,reg encoding. */
1227 if (iEncoding == 0)
1228 {
1229 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1230 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xAX, X86_GREG_xCX);
1231 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_AL;
1232 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_CL;
1233 }
1234 else if (iEncoding == 1)
1235 {
1236 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_CH;
1237 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1238 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, 1, 0, BS3CG1OPLOC_MEM);
1239 }
1240 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1241 {
1242 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_BH;
1243 pThis->abCurInstr[0] = P_AZ;
1244 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1245 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, 1, 0, BS3CG1OPLOC_MEM);
1246 }
1247 else
1248 break;
1249 pThis->cbCurInstr = off;
1250 iEncoding++;
1251 break;
1252
1253 case BS3CG1ENC_MODRM_Gv_Ev:
1254 case BS3CG1ENC_MODRM_Ev_Gv:
1255 if (iEncoding == 0)
1256 {
1257 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1258 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1259 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1260 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBX;
1261 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_OZ_RDX;
1262 }
1263 else if (iEncoding == 1)
1264 {
1265 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1266 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1267 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1268 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp, 0,
1269 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1270 }
1271 else if (iEncoding == 2 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1272 {
1273 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1274 pThis->abCurInstr[0] = P_OZ;
1275 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1276 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1277 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBX;
1278 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_OZ_RDX;
1279 pThis->aOperands[pThis->iRmOp ].enmLocation = BS3CG1OPLOC_CTX;
1280 }
1281 else if (iEncoding == 3)
1282 {
1283 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1284 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RSI;
1285 pThis->abCurInstr[0] = P_OZ;
1286 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1287 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xSI, cbOp, 0,
1288 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1289 }
1290 else if (iEncoding == 4)
1291 {
1292 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1293 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RDI;
1294 pThis->abCurInstr[0] = P_AZ;
1295 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1296 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xDI, cbOp, 0,
1297 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1298 }
1299 else if (iEncoding == 5)
1300 {
1301 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 4 : 2;
1302 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RSI;
1303 pThis->abCurInstr[0] = P_OZ;
1304 pThis->abCurInstr[1] = P_AZ;
1305 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
1306 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xSI, cbOp, 0,
1307 pThis->enmEncoding == BS3CG1ENC_MODRM_Gv_Ev ? BS3CG1OPLOC_MEM : BS3CG1OPLOC_MEM_RW);
1308 }
1309 else if (iEncoding == 6 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1310 {
1311 cbOp = 8;
1312 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1313 pThis->abCurInstr[off++] = REX_W___;
1314 off = Bs3Cg1InsertOpcodes(pThis, off);
1315 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, X86_GREG_xBX, X86_GREG_xDX);
1316 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_RBX;
1317 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_RDX;
1318 pThis->aOperands[pThis->iRmOp ].enmLocation = BS3CG1OPLOC_CTX;
1319 }
1320 else
1321 break;
1322 pThis->aOperands[0].cbOp = cbOp;
1323 pThis->aOperands[1].cbOp = cbOp;
1324 pThis->cbOperand = cbOp;
1325 pThis->cbCurInstr = off;
1326 iEncoding++;
1327 break;
1328
1329 case BS3CG1ENC_MODRM_Wss_Vss:
1330 if (iEncoding == 0)
1331 {
1332 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1333 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1334 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_DW0;
1335 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_DW0;
1336 }
1337 else if (iEncoding == 1)
1338 {
1339 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_DW0;
1340 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1341 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 4, 0, BS3CG1OPLOC_MEM_RW);
1342 }
1343 else if (iEncoding == 2)
1344 {
1345 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_DW0;
1346 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1347 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 4, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1348 }
1349 else
1350 break;
1351 pThis->cbCurInstr = off;
1352 iEncoding++;
1353 break;
1354
1355 case BS3CG1ENC_MODRM_Wsd_Vsd:
1356 if (iEncoding == 0)
1357 {
1358 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1359 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1360 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO;
1361 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO;
1362 }
1363 else if (iEncoding == 1)
1364 {
1365 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
1366 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1367 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_RW);
1368 }
1369 else if (iEncoding == 2)
1370 {
1371 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
1372 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1373 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1374 }
1375 else
1376 break;
1377 pThis->cbCurInstr = off;
1378 iEncoding++;
1379 break;
1380
1381 case BS3CG1ENC_MODRM_Wps_Vps:
1382 case BS3CG1ENC_MODRM_Wpd_Vpd:
1383 if (iEncoding == 0)
1384 {
1385 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1386 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1387 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
1388 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
1389 }
1390 else if (iEncoding == 1)
1391 {
1392 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
1393 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1394 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM_RW);
1395 }
1396 else if (iEncoding == 2)
1397 {
1398 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
1399 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1400 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1401 if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
1402 pThis->bAlignmentXcpt = X86_XCPT_GP;
1403 }
1404 else
1405 break;
1406 pThis->cbCurInstr = off;
1407 iEncoding++;
1408 break;
1409
1410 case BS3CG1ENC_MODRM_WqZxReg_Vq:
1411 if (iEncoding == 0)
1412 {
1413 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1414 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1415 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_LO_ZX;
1416 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO;
1417 }
1418 else if (iEncoding == 1)
1419 {
1420 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
1421 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1422 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM_RW);
1423 }
1424 else if (iEncoding == 2)
1425 {
1426 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
1427 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1428 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM_RW);
1429 }
1430 else
1431 break;
1432 pThis->cbCurInstr = off;
1433 iEncoding++;
1434 break;
1435
1436 case BS3CG1ENC_MODRM_Vq_UqHi:
1437 if (iEncoding == 0)
1438 {
1439 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1440 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1441 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0_HI;
1442 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1_LO;
1443 }
1444 else if (iEncoding == 1)
1445 {
1446 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1447 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 2, 2);
1448 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM2_HI;
1449 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
1450 }
1451 else
1452 break;
1453 pThis->cbCurInstr = off;
1454 iEncoding++;
1455 break;
1456
1457 case BS3CG1ENC_MODRM_Vq_Mq:
1458 if (iEncoding == 0)
1459 {
1460 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2_LO;
1461 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1462 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 8, 0, BS3CG1OPLOC_MEM);
1463 }
1464 else if (iEncoding == 1)
1465 {
1466 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3_LO;
1467 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1468 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 8, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM);
1469 }
1470 else
1471 break;
1472 pThis->cbCurInstr = off;
1473 iEncoding++;
1474 break;
1475
1476 case BS3CG1ENC_MODRM_Vdq_Wdq:
1477 if (iEncoding == 0)
1478 {
1479 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1480 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 1, 0);
1481 pThis->aOperands[pThis->iRmOp ].idxField = BS3CG1DST_XMM0;
1482 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM1;
1483 }
1484 else if (iEncoding == 1)
1485 {
1486 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM2;
1487 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1488 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 2 /*iReg*/, 16, 0, BS3CG1OPLOC_MEM);
1489 }
1490 else if (iEncoding == 2)
1491 {
1492 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_XMM3;
1493 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1494 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, 3 /*iReg*/, 16, 1 /*cbMissalign*/, BS3CG1OPLOC_MEM);
1495 if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
1496 pThis->bAlignmentXcpt = X86_XCPT_GP;
1497 }
1498 else
1499 break;
1500 pThis->cbCurInstr = off;
1501 iEncoding++;
1502 break;
1503
1504 case BS3CG1ENC_MODRM_Gv_Ma:
1505 cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
1506 if (iEncoding == 0)
1507 {
1508 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1509 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1510 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1511 }
1512 else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1513 {
1514 cbOp = cbOp == 2 ? 4 : 2;
1515 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1516 pThis->abCurInstr[0] = P_OZ;
1517 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1518 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1519 }
1520 else if (iEncoding == 2)
1521 {
1522 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1523 pThis->abCurInstr[0] = P_AZ;
1524 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1525 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1526 }
1527 else if (iEncoding == 3)
1528 {
1529 cbOp = cbOp == 2 ? 4 : 2;
1530 pThis->aOperands[pThis->iRegOp].idxField = BS3CG1DST_OZ_RBP;
1531 pThis->abCurInstr[0] = P_AZ;
1532 pThis->abCurInstr[1] = P_OZ;
1533 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
1534 off = Bs3Cfg1EncodeMemMod0Disp(pThis, true, off, X86_GREG_xBP, cbOp * 2, 0, BS3CG1OPLOC_MEM);
1535 }
1536 else
1537 break;
1538 pThis->aOperands[pThis->iRegOp].cbOp = cbOp;
1539 pThis->cbOperand = cbOp;
1540 pThis->cbCurInstr = off;
1541 iEncoding++;
1542 break;
1543
1544 case BS3CG1ENC_MODRM_MbRO:
1545 if (iEncoding == 0)
1546 {
1547 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)) - 1;
1548 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
1549 (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
1550 1, 0, BS3CG1OPLOC_MEM);
1551 }
1552 else
1553 break;
1554 pThis->cbCurInstr = off;
1555 iEncoding++;
1556 break;
1557
1558 case BS3CG1ENC_MODRM_MdWO:
1559 if (iEncoding == 0)
1560 {
1561 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)) - 1;
1562 off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
1563 (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
1564 4, 0, BS3CG1OPLOC_MEM_RW);
1565 }
1566 else
1567 break;
1568 pThis->cbCurInstr = off;
1569 iEncoding++;
1570 break;
1571
1572 case BS3CG1ENC_FIXED:
1573 if (iEncoding == 0)
1574 {
1575 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1576 pThis->cbCurInstr = off;
1577 iEncoding++;
1578 }
1579 break;
1580
1581 case BS3CG1ENC_FIXED_AL_Ib:
1582 if (iEncoding == 0)
1583 {
1584 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1585 pThis->aOperands[1].off = (uint8_t)off;
1586 pThis->abCurInstr[off++] = 0xff;
1587 pThis->cbCurInstr = off;
1588 iEncoding++;
1589 }
1590 break;
1591
1592 case BS3CG1ENC_FIXED_rAX_Iz:
1593 if (iEncoding == 0)
1594 {
1595 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1596 pThis->aOperands[1].off = (uint8_t)off;
1597 if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
1598 {
1599 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
1600 off += 2;
1601 pThis->aOperands[0].cbOp = 2;
1602 pThis->aOperands[1].cbOp = 2;
1603 pThis->cbOperand = 2;
1604 }
1605 else
1606 {
1607 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1608 off += 4;
1609 pThis->aOperands[0].cbOp = 4;
1610 pThis->aOperands[1].cbOp = 4;
1611 pThis->cbOperand = 4;
1612 }
1613 }
1614 else if (iEncoding == 1 && (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
1615 {
1616 pThis->abCurInstr[0] = P_OZ;
1617 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1618 pThis->aOperands[1].off = (uint8_t)off;
1619 if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
1620 {
1621 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
1622 off += 2;
1623 pThis->aOperands[0].cbOp = 2;
1624 pThis->aOperands[1].cbOp = 2;
1625 pThis->cbOperand = 2;
1626 }
1627 else
1628 {
1629 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1630 off += 4;
1631 pThis->aOperands[0].cbOp = 4;
1632 pThis->aOperands[1].cbOp = 4;
1633 pThis->cbOperand = 4;
1634 }
1635 }
1636 else if (iEncoding == 2 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1637 {
1638 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1639 pThis->abCurInstr[off++] = REX_W___;
1640 off = Bs3Cg1InsertOpcodes(pThis, off);
1641 pThis->aOperands[1].off = (uint8_t)off;
1642 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
1643 off += 4;
1644 pThis->aOperands[0].cbOp = 8;
1645 pThis->aOperands[1].cbOp = 4;
1646 pThis->cbOperand = 8;
1647 }
1648 else
1649 break;
1650 pThis->cbCurInstr = off;
1651 iEncoding++;
1652 break;
1653
1654 case BS3CG1ENC_MODRM_MOD_EQ_3:
1655 if (iEncoding < 8)
1656 {
1657 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1658 off = Bs3Cg1InsertOpcodes(pThis, off);
1659 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding, 1);
1660 }
1661 else if (iEncoding < 16)
1662 {
1663 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1664 off = Bs3Cg1InsertOpcodes(pThis, off);
1665 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding);
1666 }
1667 else
1668 break;
1669 pThis->cbCurInstr = off;
1670 iEncoding++;
1671 break;
1672
1673 case BS3CG1ENC_MODRM_MOD_NE_3:
1674 if (iEncoding < 3)
1675 {
1676 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1677 off = Bs3Cg1InsertOpcodes(pThis, off);
1678 pThis->abCurInstr[off++] = X86_MODRM_MAKE(iEncoding, 0, 1);
1679 if (iEncoding >= 1)
1680 pThis->abCurInstr[off++] = 0x7f;
1681 if (iEncoding == 2)
1682 {
1683 pThis->abCurInstr[off++] = 0x5f;
1684 if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
1685 {
1686 pThis->abCurInstr[off++] = 0x3f;
1687 pThis->abCurInstr[off++] = 0x1f;
1688 }
1689 }
1690 }
1691 else
1692 break;
1693 pThis->cbCurInstr = off;
1694 iEncoding++;
1695 break;
1696
1697 default:
1698 Bs3TestFailedF("Internal error! BS3CG1ENC_XXX = %u not implemented", pThis->enmEncoding);
1699 break;
1700 }
1701
1702
1703 return iEncoding;
1704}
1705
1706
1707/**
1708 * Prepares doing instruction encodings.
1709 *
1710 * This is in part specific to how the instruction is encoded, but generally it
1711 * sets up basic operand values that doesn't change (much) when Bs3Cg1EncodeNext
1712 * is called from within the loop.
1713 *
1714 * @returns Success indicator (true/false).
1715 * @param pThis The state.
1716 */
1717static bool Bs3Cg1EncodePrep(PBS3CG1STATE pThis)
1718{
1719 unsigned iRing = 4;
1720 while (iRing-- > 0)
1721 pThis->aSavedSegRegs[iRing].ds = pThis->aInitialCtxs[iRing].ds;
1722
1723 pThis->iRmOp = RT_ELEMENTS(pThis->aOperands) - 1;
1724 pThis->iRegOp = RT_ELEMENTS(pThis->aOperands) - 1;
1725 pThis->fSameRingNotOkay = false;
1726 pThis->cbOperand = 0;
1727
1728 switch (pThis->enmEncoding)
1729 {
1730 case BS3CG1ENC_MODRM_Eb_Gb:
1731 pThis->iRmOp = 0;
1732 pThis->iRegOp = 1;
1733 pThis->aOperands[0].cbOp = 1;
1734 pThis->aOperands[1].cbOp = 1;
1735 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1736 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1737 break;
1738
1739 case BS3CG1ENC_MODRM_Ev_Gv:
1740 pThis->iRmOp = 0;
1741 pThis->iRegOp = 1;
1742 pThis->cbOperand = 2;
1743 pThis->aOperands[0].cbOp = 2;
1744 pThis->aOperands[1].cbOp = 2;
1745 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1746 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1747 break;
1748
1749 case BS3CG1ENC_MODRM_Gb_Eb:
1750 pThis->iRmOp = 1;
1751 pThis->iRegOp = 0;
1752 pThis->aOperands[0].cbOp = 1;
1753 pThis->aOperands[1].cbOp = 1;
1754 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1755 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1756 break;
1757
1758 case BS3CG1ENC_MODRM_Gv_Ev:
1759 pThis->iRmOp = 1;
1760 pThis->iRegOp = 0;
1761 pThis->cbOperand = 2;
1762 pThis->aOperands[0].cbOp = 2;
1763 pThis->aOperands[1].cbOp = 2;
1764 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1765 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1766 break;
1767
1768 case BS3CG1ENC_MODRM_Gv_Ma:
1769 pThis->iRmOp = 1;
1770 pThis->iRegOp = 0;
1771 pThis->cbOperand = 2;
1772 pThis->aOperands[0].cbOp = 2;
1773 pThis->aOperands[1].cbOp = 4;
1774 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1775 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
1776 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1777 break;
1778
1779 case BS3CG1ENC_MODRM_Wss_Vss:
1780 pThis->iRmOp = 0;
1781 pThis->iRegOp = 1;
1782 pThis->aOperands[0].cbOp = 4;
1783 pThis->aOperands[1].cbOp = 4;
1784 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1785 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1786 break;
1787
1788 case BS3CG1ENC_MODRM_Wsd_Vsd:
1789 case BS3CG1ENC_MODRM_WqZxReg_Vq:
1790 pThis->iRmOp = 0;
1791 pThis->iRegOp = 1;
1792 pThis->aOperands[0].cbOp = 8;
1793 pThis->aOperands[1].cbOp = 8;
1794 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1795 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1796 break;
1797
1798 case BS3CG1ENC_MODRM_Wps_Vps:
1799 case BS3CG1ENC_MODRM_Wpd_Vpd:
1800 pThis->iRmOp = 0;
1801 pThis->iRegOp = 1;
1802 pThis->aOperands[0].cbOp = 16;
1803 pThis->aOperands[1].cbOp = 16;
1804 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1805 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1806 break;
1807
1808 case BS3CG1ENC_MODRM_Vdq_Wdq:
1809 pThis->iRmOp = 1;
1810 pThis->iRegOp = 0;
1811 pThis->aOperands[0].cbOp = 16;
1812 pThis->aOperands[1].cbOp = 16;
1813 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1814 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1815 break;
1816
1817 case BS3CG1ENC_MODRM_Vq_UqHi:
1818 pThis->iRmOp = 1;
1819 pThis->iRegOp = 0;
1820 pThis->aOperands[0].cbOp = 8;
1821 pThis->aOperands[1].cbOp = 8;
1822 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1823 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
1824 break;
1825
1826 case BS3CG1ENC_MODRM_Vq_Mq:
1827 pThis->iRmOp = 1;
1828 pThis->iRegOp = 0;
1829 pThis->aOperands[0].cbOp = 8;
1830 pThis->aOperands[1].cbOp = 8;
1831 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1832 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
1833 break;
1834
1835 case BS3CG1ENC_MODRM_MbRO:
1836 pThis->iRmOp = 0;
1837 pThis->aOperands[0].cbOp = 1;
1838 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
1839 break;
1840
1841 case BS3CG1ENC_MODRM_MdWO:
1842 pThis->iRmOp = 0;
1843 pThis->aOperands[0].cbOp = 4;
1844 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_RW;
1845 break;
1846
1847 case BS3CG1ENC_FIXED:
1848 /* nothing to do here */
1849 break;
1850
1851 case BS3CG1ENC_FIXED_AL_Ib:
1852 pThis->aOperands[0].cbOp = 1;
1853 pThis->aOperands[1].cbOp = 1;
1854 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1855 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
1856 pThis->aOperands[0].idxField = BS3CG1DST_AL;
1857 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1858 break;
1859
1860 case BS3CG1ENC_FIXED_rAX_Iz:
1861 pThis->aOperands[0].cbOp = 2;
1862 pThis->aOperands[1].cbOp = 2;
1863 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
1864 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
1865 pThis->aOperands[0].idxField = BS3CG1DST_OZ_RAX;
1866 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
1867 break;
1868
1869 case BS3CG1ENC_MODRM_MOD_EQ_3:
1870 case BS3CG1ENC_MODRM_MOD_NE_3:
1871 /* Unused or invalid instructions mostly. */
1872 break;
1873
1874 default:
1875 return Bs3TestFailedF("Invalid/unimplemented enmEncoding for instruction #%RU32 (%.*s): %d",
1876 pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic, pThis->enmEncoding);
1877 }
1878 return true;
1879}
1880
1881
1882/**
1883 * Sets up SSE and maybe AVX.
1884 *
1885 * @returns true (if successful, false if not and the SSE instructions ends up
1886 * being invalid).
1887 * @param pThis The state.
1888 */
1889static bool Bs3Cg3SetupSseAndAvx(PBS3CG1STATE pThis)
1890{
1891 if (!pThis->fWorkExtCtx)
1892 {
1893 unsigned i;
1894 uint32_t cr0 = ASMGetCR0();
1895 uint32_t cr4 = ASMGetCR4();
1896
1897 cr0 &= ~(X86_CR0_TS | X86_CR0_MP | X86_CR0_EM);
1898 cr0 |= X86_CR0_NE;
1899 ASMSetCR0(cr0);
1900 if (pThis->pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
1901 {
1902 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE;
1903 ASMSetCR4(cr4);
1904 ASMSetXcr0(pThis->pExtCtx->fXcr0);
1905 }
1906 else
1907 {
1908 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT;
1909 ASMSetCR4(cr4);
1910 }
1911
1912 for (i = 0; i < RT_ELEMENTS(pThis->aInitialCtxs); i++)
1913 {
1914 pThis->aInitialCtxs[i].cr0.u32 = cr0;
1915 pThis->aInitialCtxs[i].cr4.u32 = cr4;
1916 }
1917 pThis->fWorkExtCtx = true;
1918 }
1919
1920 return true;
1921}
1922
1923
1924/**
1925 * Next CPU configuration to test the current instruction in.
1926 *
1927 * This is for testing FPU, SSE and AVX instructions with the various lazy state
1928 * load and enable bits in different configurations to ensure we're getting the
1929 * right response.
1930 *
1931 * This also cleans up the CPU and test driver state.
1932 *
1933 * @returns true if we're to do another round, false if we're done.
1934 * @param pThis The state.
1935 * @param iCpuSetup The current CPU setup number.
1936 * @param pfInvalidInstr Where to indicate whether the setup causes an
1937 * invalid instruction or not. This is also used as
1938 * input to avoid unnecessary CPUID work.
1939 */
1940static bool Bs3Cg1CpuSetupNext(PBS3CG1STATE pThis, unsigned iCpuSetup, bool *pfInvalidInstr)
1941{
1942 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
1943 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1944 return false;
1945
1946 switch (pThis->enmCpuTest)
1947 {
1948 case BS3CG1CPU_ANY:
1949 case BS3CG1CPU_GE_80186:
1950 case BS3CG1CPU_GE_80286:
1951 case BS3CG1CPU_GE_80386:
1952 case BS3CG1CPU_GE_80486:
1953 case BS3CG1CPU_GE_Pentium:
1954 case BS3CG1CPU_CLFSH:
1955 case BS3CG1CPU_CLFLUSHOPT:
1956 return false;
1957
1958 case BS3CG1CPU_SSE:
1959 case BS3CG1CPU_SSE2:
1960 case BS3CG1CPU_SSE3:
1961 case BS3CG1CPU_AVX:
1962 case BS3CG1CPU_AVX2:
1963 if (iCpuSetup > 0 || *pfInvalidInstr)
1964 {
1965 /** @todo do more configs here. */
1966 pThis->fWorkExtCtx = false;
1967 ASMSetCR0(ASMGetCR0() | X86_CR0_EM | X86_CR0_MP);
1968 ASMSetCR4(ASMGetCR4() & ~(X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE));
1969 return false;
1970 }
1971 return false;
1972
1973 default:
1974 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
1975 return false;
1976 }
1977}
1978
1979
1980/**
1981 * Check if the instruction is supported by the CPU, possibly making state
1982 * adjustments to enable support for it.
1983 *
1984 * @returns true if supported, false if not.
1985 * @param pThis The state.
1986 */
1987static bool Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
1988{
1989 uint32_t fEax;
1990 uint32_t fEbx;
1991 uint32_t fEcx;
1992 uint32_t fEdx;
1993
1994 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
1995 && BS3_MODE_IS_64BIT_CODE(pThis->bMode))
1996 return false;
1997
1998 switch (pThis->enmCpuTest)
1999 {
2000 case BS3CG1CPU_ANY:
2001 return true;
2002
2003 case BS3CG1CPU_GE_80186:
2004 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80186)
2005 return true;
2006 return false;
2007
2008 case BS3CG1CPU_GE_80286:
2009 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80286)
2010 return true;
2011 return false;
2012
2013 case BS3CG1CPU_GE_80386:
2014 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
2015 return true;
2016 return false;
2017
2018 case BS3CG1CPU_GE_80486:
2019 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486)
2020 return true;
2021 return false;
2022
2023 case BS3CG1CPU_GE_Pentium:
2024 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_Pentium)
2025 return true;
2026 return false;
2027
2028 case BS3CG1CPU_SSE:
2029 case BS3CG1CPU_SSE2:
2030 case BS3CG1CPU_SSE3:
2031 case BS3CG1CPU_AVX:
2032 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2033 {
2034 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, &fEdx);
2035 switch (pThis->enmCpuTest)
2036 {
2037 case BS3CG1CPU_SSE:
2038 if (fEdx & X86_CPUID_FEATURE_EDX_SSE)
2039 return Bs3Cg3SetupSseAndAvx(pThis);
2040 return false;
2041 case BS3CG1CPU_SSE2:
2042 if (fEdx & X86_CPUID_FEATURE_EDX_SSE2)
2043 return Bs3Cg3SetupSseAndAvx(pThis);
2044 return false;
2045 case BS3CG1CPU_SSE3:
2046 if (fEcx & X86_CPUID_FEATURE_ECX_SSE3)
2047 return Bs3Cg3SetupSseAndAvx(pThis);
2048 return false;
2049 case BS3CG1CPU_AVX:
2050 if (fEcx & X86_CPUID_FEATURE_ECX_AVX)
2051 return Bs3Cg3SetupSseAndAvx(pThis);
2052 return false;
2053 default: BS3_ASSERT(0); /* impossible */
2054 }
2055 }
2056 return false;
2057
2058 case BS3CG1CPU_AVX2:
2059 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2060 {
2061 ASMCpuIdExSlow(7, 0, 0/*leaf*/, 0, &fEax, &fEbx, &fEcx, &fEdx);
2062 switch (pThis->enmCpuTest)
2063 {
2064 case BS3CG1CPU_AVX2:
2065 if (fEbx & X86_CPUID_STEXT_FEATURE_EBX_AVX2)
2066 return Bs3Cg3SetupSseAndAvx(pThis);
2067 return false;
2068 default: BS3_ASSERT(0); return false; /* impossible */
2069 }
2070 }
2071 return false;
2072
2073 case BS3CG1CPU_CLFSH:
2074 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2075 {
2076 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, NULL, &fEdx);
2077 if (fEdx & X86_CPUID_FEATURE_EDX_CLFSH)
2078 return true;
2079 }
2080 return false;
2081
2082 case BS3CG1CPU_CLFLUSHOPT:
2083 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2084 {
2085 ASMCpuIdExSlow(7, 0, 0/*leaf*/, 0, NULL, &fEbx, NULL, NULL);
2086 if (fEbx & X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT)
2087 return true;
2088 }
2089 return false;
2090
2091 default:
2092 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
2093 return false;
2094 }
2095}
2096
2097
2098
2099/**
2100 * Checks the preconditions for a test.
2101 *
2102 * @returns true if the test be executed, false if not.
2103 * @param pThis The state.
2104 * @param pHdr The test header.
2105 */
2106static bool Bs3Cg1RunSelector(PBS3CG1STATE pThis, PCBS3CG1TESTHDR pHdr)
2107{
2108
2109 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1);
2110 unsigned cbLeft = pHdr->cbSelector;
2111 while (cbLeft-- > 0)
2112 {
2113 switch (*pbCode++)
2114 {
2115#define CASE_PRED(a_Pred, a_Expr) \
2116 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_TRUE: \
2117 if (!(a_Expr)) return false; \
2118 break; \
2119 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_FALSE: \
2120 if (a_Expr) return false; \
2121 break
2122 CASE_PRED(BS3CG1PRED_SIZE_O16, pThis->cbOperand == 2);
2123 CASE_PRED(BS3CG1PRED_SIZE_O32, pThis->cbOperand == 4);
2124 CASE_PRED(BS3CG1PRED_SIZE_O64, pThis->cbOperand == 8);
2125 CASE_PRED(BS3CG1PRED_RING_0, pThis->uCpl == 0);
2126 CASE_PRED(BS3CG1PRED_RING_1, pThis->uCpl == 1);
2127 CASE_PRED(BS3CG1PRED_RING_2, pThis->uCpl == 2);
2128 CASE_PRED(BS3CG1PRED_RING_3, pThis->uCpl == 3);
2129 CASE_PRED(BS3CG1PRED_RING_0_THRU_2, pThis->uCpl <= 2);
2130 CASE_PRED(BS3CG1PRED_RING_1_THRU_3, pThis->uCpl >= 1);
2131 CASE_PRED(BS3CG1PRED_CODE_64BIT, BS3_MODE_IS_64BIT_CODE(pThis->bMode));
2132 CASE_PRED(BS3CG1PRED_CODE_32BIT, BS3_MODE_IS_32BIT_CODE(pThis->bMode));
2133 CASE_PRED(BS3CG1PRED_CODE_16BIT, BS3_MODE_IS_16BIT_CODE(pThis->bMode));
2134 CASE_PRED(BS3CG1PRED_MODE_REAL, BS3_MODE_IS_RM_SYS(pThis->bMode));
2135 CASE_PRED(BS3CG1PRED_MODE_PROT, BS3_MODE_IS_PM_SYS(pThis->bMode));
2136 CASE_PRED(BS3CG1PRED_MODE_LONG, BS3_MODE_IS_64BIT_SYS(pThis->bMode));
2137 CASE_PRED(BS3CG1PRED_MODE_SMM, false);
2138 CASE_PRED(BS3CG1PRED_MODE_VMX, false);
2139 CASE_PRED(BS3CG1PRED_MODE_SVM, false);
2140 CASE_PRED(BS3CG1PRED_PAGING_ON, BS3_MODE_IS_PAGED(pThis->bMode));
2141 CASE_PRED(BS3CG1PRED_PAGING_OFF, !BS3_MODE_IS_PAGED(pThis->bMode));
2142
2143#undef CASE_PRED
2144 default:
2145 return Bs3TestFailedF("Invalid selector opcode %#x!", pbCode[-1]);
2146 }
2147 }
2148
2149 return true;
2150}
2151
2152
2153#ifdef BS3CG1_DEBUG_CTX_MOD
2154/**
2155 * Translates the operator into a string.
2156 *
2157 * @returns Read-only string pointer.
2158 * @param bOpcode The context modifier program opcode.
2159 */
2160static const char BS3_FAR *Bs3Cg1CtxOpToString(uint8_t bOpcode)
2161{
2162 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2163 {
2164 case BS3CG1_CTXOP_ASSIGN: return "=";
2165 case BS3CG1_CTXOP_OR: return "|=";
2166 case BS3CG1_CTXOP_AND: return "&=";
2167 case BS3CG1_CTXOP_AND_INV: return "&~=";
2168 }
2169}
2170#endif
2171
2172
2173/**
2174 * Runs a context modifier program.
2175 *
2176 * @returns Success indicator (true/false).
2177 * @param pThis The state.
2178 * @param pCtx The context.
2179 * @param pHdr The program header.
2180 * @param off The program offset relative to the end of the header.
2181 * @param cb The program size.
2182 * @param pEflCtx The context to take undefined EFLAGS from. (This is NULL
2183 * if we're processing a input context modifier program.)
2184 * @param pbInstr Points to the first instruction byte. For storing
2185 * immediate operands during input context modification.
2186 * NULL for output contexts.
2187 */
2188static bool Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCTX pCtx, PCBS3CG1TESTHDR pHdr, unsigned off, unsigned cb,
2189 PCBS3REGCTX pEflCtx, uint8_t BS3_FAR *pbInstr)
2190{
2191 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1) + off;
2192 int cbLeft = cb;
2193 while (cbLeft-- > 0)
2194 {
2195 /*
2196 * Decode the instruction.
2197 */
2198 uint8_t const bOpcode = *pbCode++;
2199 unsigned cbValue;
2200 unsigned cbDst;
2201 BS3CG1DST idxField;
2202 BS3PTRUNION PtrField;
2203
2204 /* Expand the destiation field (can be escaped). */
2205 switch (bOpcode & BS3CG1_CTXOP_DST_MASK)
2206 {
2207 case BS3CG1_CTXOP_OP1:
2208 idxField = pThis->aOperands[0].idxField;
2209 if (idxField == BS3CG1DST_INVALID)
2210 idxField = BS3CG1DST_OP1;
2211 break;
2212
2213 case BS3CG1_CTXOP_OP2:
2214 idxField = pThis->aOperands[1].idxField;
2215 if (idxField == BS3CG1DST_INVALID)
2216 idxField = BS3CG1DST_OP2;
2217 break;
2218
2219 case BS3CG1_CTXOP_EFL:
2220 idxField = BS3CG1DST_EFL;
2221 break;
2222
2223 case BS3CG1_CTXOP_DST_ESC:
2224 if (cbLeft-- > 0)
2225 {
2226 idxField = (BS3CG1DST)*pbCode++;
2227 if (idxField <= BS3CG1DST_OP4)
2228 {
2229 if (idxField > BS3CG1DST_INVALID)
2230 {
2231 uint8_t idxField2 = pThis->aOperands[idxField - BS3CG1DST_OP1].idxField;
2232 if (idxField2 != BS3CG1DST_INVALID)
2233 idxField = idxField2;
2234 break;
2235 }
2236 }
2237 else if (idxField < BS3CG1DST_END)
2238 break;
2239 return Bs3TestFailedF("Malformed context instruction: idxField=%d", idxField);
2240 }
2241 /* fall thru */
2242 default:
2243 return Bs3TestFailed("Malformed context instruction: Destination");
2244 }
2245
2246
2247 /* Expand value size (can be escaped). */
2248 switch (bOpcode & BS3CG1_CTXOP_SIZE_MASK)
2249 {
2250 case BS3CG1_CTXOP_1_BYTE: cbValue = 1; break;
2251 case BS3CG1_CTXOP_2_BYTES: cbValue = 2; break;
2252 case BS3CG1_CTXOP_4_BYTES: cbValue = 4; break;
2253 case BS3CG1_CTXOP_8_BYTES: cbValue = 8; break;
2254 case BS3CG1_CTXOP_16_BYTES: cbValue = 16; break;
2255 case BS3CG1_CTXOP_32_BYTES: cbValue = 32; break;
2256 case BS3CG1_CTXOP_12_BYTES: cbValue = 12; break;
2257 case BS3CG1_CTXOP_SIZE_ESC:
2258 if (cbLeft-- > 0)
2259 {
2260 cbValue = *pbCode++;
2261 if (cbValue)
2262 break;
2263 }
2264 /* fall thru */
2265 default:
2266 return Bs3TestFailed("Malformed context instruction: size");
2267 }
2268
2269 /* Make sure there is enough instruction bytes for the value. */
2270 if (cbValue <= cbLeft)
2271 { /* likely */ }
2272 else
2273 return Bs3TestFailedF("Malformed context instruction: %u bytes value, %u bytes left", cbValue, cbLeft);
2274
2275 /*
2276 * Do value processing specific to the target field size.
2277 */
2278 cbDst = g_acbBs3Cg1DstFields[idxField];
2279 if (cbDst == BS3CG1DSTSIZE_OPERAND)
2280 cbDst = pThis->aOperands[idxField - BS3CG1DST_OP1].cbOp;
2281 else if (cbDst == BS3CG1DSTSIZE_OPERAND_SIZE_GRP)
2282 cbDst = pThis->cbOperand;
2283 if (cbDst <= 8)
2284 {
2285 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
2286
2287 /*
2288 * Deal with fields up to 8-byte wide.
2289 */
2290 /* Get the value. */
2291 uint64_t uValue;
2292 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT))
2293 switch (cbValue)
2294 {
2295 case 1: uValue = *(int8_t const BS3_FAR *)pbCode; break;
2296 case 2: uValue = *(int16_t const BS3_FAR *)pbCode; break;
2297 case 4: uValue = *(int32_t const BS3_FAR *)pbCode; break;
2298 default:
2299 if (cbValue >= 8)
2300 {
2301 uValue = *(uint64_t const BS3_FAR *)pbCode;
2302 break;
2303 }
2304 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
2305 }
2306 else
2307 switch (cbValue)
2308 {
2309 case 1: uValue = *(uint8_t const BS3_FAR *)pbCode; break;
2310 case 2: uValue = *(uint16_t const BS3_FAR *)pbCode; break;
2311 case 4: uValue = *(uint32_t const BS3_FAR *)pbCode; break;
2312 default:
2313 if (cbValue >= 8)
2314 {
2315 uValue = *(uint64_t const BS3_FAR *)pbCode;
2316 break;
2317 }
2318 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
2319 }
2320
2321 /* Find the field. */
2322 if (offField < sizeof(BS3REGCTX))
2323 PtrField.pu8 = (uint8_t BS3_FAR *)pCtx + offField;
2324 /* Non-register operands: */
2325 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
2326 {
2327 unsigned const idxOp = idxField - BS3CG1DST_OP1;
2328
2329 switch (pThis->aOperands[idxOp].enmLocation)
2330 {
2331 case BS3CG1OPLOC_IMM:
2332 if (pbInstr)
2333 PtrField.pu8 = &pbInstr[pThis->aOperands[idxOp].off];
2334 else
2335 return Bs3TestFailedF("Immediate operand referenced in output context!");
2336 break;
2337
2338 case BS3CG1OPLOC_MEM:
2339 if (!pbInstr)
2340 return Bs3TestFailedF("Read only operand specified in output!");
2341 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2342 break;
2343
2344 case BS3CG1OPLOC_MEM_RW:
2345 if (pbInstr)
2346 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2347 else
2348 PtrField.pu8 = pThis->MemOp.ab;
2349 break;
2350
2351 default:
2352 return Bs3TestFailedF("Internal error: cbDst=%u idxField=%d (%d) offField=%#x: enmLocation=%u off=%#x idxField=%u",
2353 cbDst, idxField, idxOp, offField, pThis->aOperands[idxOp].enmLocation,
2354 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
2355 }
2356 }
2357 /* Special field: Copying in undefined EFLAGS from the result context. */
2358 else if (idxField == BS3CG1DST_EFL_UNDEF)
2359 {
2360 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN)
2361 return Bs3TestFailed("Invalid BS3CG1DST_EFL_UNDEF usage");
2362 PtrField.pu32 = &pCtx->rflags.u32;
2363 uValue = (*PtrField.pu32 & ~(uint32_t)uValue) | (pEflCtx->rflags.u32 & (uint32_t)uValue);
2364 }
2365 /* Special field: Expected value (in/result) exception. */
2366 else if (idxField == BS3CG1DST_VALUE_XCPT)
2367 {
2368 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN || cbDst != 1)
2369 return Bs3TestFailed("Invalid BS3CG1DST_VALUE_XCPT usage");
2370 PtrField.pu8 = &pThis->bValueXcpt;
2371 }
2372 /* FPU and FXSAVE format. */
2373 else if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
2374 && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
2375 {
2376 if (!pThis->fWorkExtCtx)
2377 return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
2378 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
2379 }
2380 /** @todo other FPU fields and FPU state formats. */
2381 else
2382 return Bs3TestFailedF("Todo implement me: cbDst=%u idxField=%d offField=%#x", cbDst, idxField, offField);
2383
2384#ifdef BS3CG1_DEBUG_CTX_MOD
2385 switch (cbDst)
2386 {
2387 case 1:
2388 BS3CG1_DPRINTF(("dbg: modify %s: %#04RX8 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2389 *PtrField.pu8, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2390 break;
2391 case 2:
2392 BS3CG1_DPRINTF(("dbg: modify %s: %#06RX16 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2393 *PtrField.pu16, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2394 break;
2395 case 4:
2396 BS3CG1_DPRINTF(("dbg: modify %s: %#010RX32 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2397 *PtrField.pu32, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2398 break;
2399 default:
2400 BS3CG1_DPRINTF(("dbg: modify %s: %#018RX64 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2401 *PtrField.pu64, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
2402 break;
2403 }
2404#endif
2405
2406 /* Modify the field. */
2407 switch (cbDst)
2408 {
2409 case 1:
2410 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2411 {
2412 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu8 = (uint8_t)uValue; break;
2413 case BS3CG1_CTXOP_OR: *PtrField.pu8 |= (uint8_t)uValue; break;
2414 case BS3CG1_CTXOP_AND: *PtrField.pu8 &= (uint8_t)uValue; break;
2415 case BS3CG1_CTXOP_AND_INV: *PtrField.pu8 &= ~(uint8_t)uValue; break;
2416 }
2417 break;
2418
2419 case 2:
2420 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2421 {
2422 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu16 = (uint16_t)uValue; break;
2423 case BS3CG1_CTXOP_OR: *PtrField.pu16 |= (uint16_t)uValue; break;
2424 case BS3CG1_CTXOP_AND: *PtrField.pu16 &= (uint16_t)uValue; break;
2425 case BS3CG1_CTXOP_AND_INV: *PtrField.pu16 &= ~(uint16_t)uValue; break;
2426 }
2427 break;
2428
2429 case 4:
2430 if (offField <= RT_OFFSETOF(BS3REGCTX, r15)) /* Clear the top dword. */
2431 PtrField.pu32[1] = 0;
2432 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2433 {
2434 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu32 = (uint32_t)uValue; break;
2435 case BS3CG1_CTXOP_OR: *PtrField.pu32 |= (uint32_t)uValue; break;
2436 case BS3CG1_CTXOP_AND: *PtrField.pu32 &= (uint32_t)uValue; break;
2437 case BS3CG1_CTXOP_AND_INV: *PtrField.pu32 &= ~(uint32_t)uValue; break;
2438 }
2439 break;
2440
2441 case 8:
2442 if ((unsigned)(idxField - BS3CG1DST_XMM0_LO_ZX) <= (unsigned)(BS3CG1DST_XMM15_LO_ZX - BS3CG1DST_XMM0_LO_ZX))
2443 PtrField.pu64[1] = 0;
2444 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2445 {
2446 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu64 = (uint64_t)uValue; break;
2447 case BS3CG1_CTXOP_OR: *PtrField.pu64 |= (uint64_t)uValue; break;
2448 case BS3CG1_CTXOP_AND: *PtrField.pu64 &= (uint64_t)uValue; break;
2449 case BS3CG1_CTXOP_AND_INV: *PtrField.pu64 &= ~(uint64_t)uValue; break;
2450 }
2451 break;
2452
2453 default:
2454 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, expected 1, 2, 4, or 8", cbDst);
2455 }
2456
2457#ifdef BS3CG1_DEBUG_CTX_MOD
2458 switch (cbDst)
2459 {
2460 case 1: BS3CG1_DPRINTF(("dbg: --> %s: %#04RX8\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu8)); break;
2461 case 2: BS3CG1_DPRINTF(("dbg: --> %s: %#06RX16\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu16)); break;
2462 case 4: BS3CG1_DPRINTF(("dbg: --> %s: %#010RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu32)); break;
2463 default: BS3CG1_DPRINTF(("dbg: --> %s: %#018RX64\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64)); break;
2464 }
2465#endif
2466
2467 }
2468 /*
2469 * Deal with larger field (FPU, SSE, AVX, ...).
2470 */
2471 else
2472 {
2473 union
2474 {
2475 X86FPUREG FpuReg;
2476 X86XMMREG XmmReg;
2477 X86YMMREG YmmReg;
2478 X86ZMMREG ZmmReg;
2479 uint8_t ab[sizeof(X86ZMMREG)];
2480 uint32_t au32[sizeof(X86ZMMREG) / sizeof(uint32_t)];
2481 } Value;
2482 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
2483
2484 if (!pThis->fWorkExtCtx)
2485 return Bs3TestFailedF("Extended context disabled: Field %d @ %#x LB %u\n", idxField, offField, cbDst);
2486
2487 /* Copy the value into the union, doing the zero padding / extending. */
2488 Bs3MemCpy(&Value, pbCode, cbValue);
2489 if (cbValue < sizeof(Value))
2490 {
2491 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT) && (Value.ab[cbValue - 1] & 0x80))
2492 Bs3MemSet(&Value.ab[cbValue], 0xff, sizeof(Value) - cbValue);
2493 else
2494 Bs3MemSet(&Value.ab[cbValue], 0x00, sizeof(Value) - cbValue);
2495 }
2496
2497 /* Optimized access to XMM and STx registers. */
2498 if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
2499 && offField - sizeof(BS3REGCTX) <= RT_UOFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) )
2500 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
2501 /* Non-register operands: */
2502 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
2503 {
2504 unsigned const idxOp = idxField - BS3CG1DST_OP1;
2505 switch (pThis->aOperands[idxOp].enmLocation)
2506 {
2507 case BS3CG1OPLOC_MEM:
2508 if (!pbInstr)
2509 return Bs3TestFailedF("Read only operand specified in output!");
2510 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2511 break;
2512
2513 case BS3CG1OPLOC_MEM_RW:
2514 if (pbInstr)
2515 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
2516 else
2517 PtrField.pu8 = pThis->MemOp.ab;
2518 break;
2519
2520 default:
2521 return Bs3TestFailedF("Internal error: Field %d (%d) @ %#x LB %u: enmLocation=%u off=%#x idxField=%u",
2522 idxField, idxOp, offField, cbDst, pThis->aOperands[idxOp].enmLocation,
2523 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
2524 }
2525 }
2526 /* The YMM (AVX) and the first 16 ZMM (AVX512) registers have split storage in
2527 the state, so they need special handling. */
2528 else
2529 {
2530 return Bs3TestFailedF("TODO: implement me: cbDst=%d idxField=%d (AVX and other weird state)", cbDst, idxField);
2531 }
2532
2533 if (PtrField.pb)
2534 {
2535 /* Modify the field / memory. */
2536 unsigned i;
2537 if (cbDst & 3)
2538 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, multiple of 4", cbDst);
2539
2540#ifdef BS3CG1_DEBUG_CTX_MOD
2541 BS3CG1_DPRINTF(("dbg: modify %s: %.*Rhxs (LB %u) %s %.*Rhxs (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
2542 cbDst, PtrField.pb, cbDst, Bs3Cg1CtxOpToString(bOpcode), cbValue, Value.ab, cbValue));
2543#endif
2544
2545 i = cbDst / 4;
2546 while (i-- > 0)
2547 {
2548 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
2549 {
2550 case BS3CG1_CTXOP_ASSIGN: PtrField.pu32[i] = Value.au32[i]; break;
2551 case BS3CG1_CTXOP_OR: PtrField.pu32[i] |= Value.au32[i]; break;
2552 case BS3CG1_CTXOP_AND: PtrField.pu32[i] &= Value.au32[i]; break;
2553 case BS3CG1_CTXOP_AND_INV: PtrField.pu32[i] &= ~Value.au32[i]; break;
2554 }
2555 }
2556
2557#ifdef BS3CG1_DEBUG_CTX_MOD
2558 BS3CG1_DPRINTF(("dbg: --> %s: %.*Rhxs\n", g_aszBs3Cg1DstFields[idxField].sz, cbDst, PtrField.pb));
2559#endif
2560 }
2561 }
2562
2563 /*
2564 * Advance to the next instruction.
2565 */
2566 pbCode += cbValue;
2567 cbLeft -= cbValue;
2568 }
2569
2570 return true;
2571}
2572
2573
2574/**
2575 * Checks the result of a run.
2576 *
2577 * @returns true if successful, false if not.
2578 * @param pThis The state.
2579 * @param fInvalidInstr Whether this is an invalid instruction.
2580 * @param bTestXcptExpected The exception causing the test code to stop
2581 * executing.
2582 * @param iEncoding For error reporting.
2583 */
2584static bool Bs3Cg1CheckResult(PBS3CG1STATE pThis, bool fInvalidInstr, uint8_t bTestXcptExpected, unsigned iEncoding)
2585{
2586 unsigned iOperand;
2587
2588 /*
2589 * Check the exception state first.
2590 */
2591 uint8_t bExpectedXcpt;
2592 uint8_t cbAdjustPc;
2593 if (!fInvalidInstr)
2594 {
2595 bExpectedXcpt = pThis->bAlignmentXcpt;
2596 if (bExpectedXcpt == UINT8_MAX)
2597 bExpectedXcpt = pThis->bValueXcpt;
2598 if (bExpectedXcpt == UINT8_MAX)
2599 {
2600 cbAdjustPc = pThis->cbCurInstr;
2601 bExpectedXcpt = bTestXcptExpected;
2602 if (bTestXcptExpected == X86_XCPT_PF)
2603 pThis->Ctx.cr2.u = pThis->uCodePgFlat + X86_PAGE_SIZE;
2604 }
2605 else
2606 cbAdjustPc = 0;
2607 }
2608 else
2609 {
2610 cbAdjustPc = 0;
2611 bExpectedXcpt = bTestXcptExpected;
2612 }
2613 if (RT_LIKELY( pThis->TrapFrame.bXcpt == bExpectedXcpt
2614 && pThis->TrapFrame.Ctx.rip.u == pThis->Ctx.rip.u + cbAdjustPc))
2615 {
2616 /*
2617 * Check the register content.
2618 */
2619 bool fOkay = Bs3TestCheckRegCtxEx(&pThis->TrapFrame.Ctx, &pThis->Ctx,
2620 cbAdjustPc, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/,
2621 pThis->pszMode, iEncoding);
2622
2623 /*
2624 * Check memory output operands.
2625 */
2626 iOperand = pThis->cOperands;
2627 while (iOperand-- > 0)
2628 if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
2629 {
2630 BS3PTRUNION PtrUnion;
2631 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
2632 switch (pThis->aOperands[iOperand].cbOp)
2633 {
2634 case 1:
2635 if (*PtrUnion.pu8 == pThis->MemOp.ab[0])
2636 continue;
2637 Bs3TestFailedF("op%u: Wrote %#04RX8, expected %#04RX8", iOperand, *PtrUnion.pu8, pThis->MemOp.ab[0]);
2638 break;
2639 case 2:
2640 if (*PtrUnion.pu16 == pThis->MemOp.au16[0])
2641 continue;
2642 Bs3TestFailedF("op%u: Wrote %#06RX16, expected %#06RX16",
2643 iOperand, *PtrUnion.pu16, pThis->MemOp.au16[0]);
2644 break;
2645 case 4:
2646 if (*PtrUnion.pu32 == pThis->MemOp.au32[0])
2647 continue;
2648 Bs3TestFailedF("op%u: Wrote %#010RX32, expected %#010RX32",
2649 iOperand, *PtrUnion.pu32, pThis->MemOp.au32[0]);
2650 break;
2651 case 8:
2652 if (*PtrUnion.pu64 == pThis->MemOp.au64[0])
2653 continue;
2654 Bs3TestFailedF("op%u: Wrote %#018RX64, expected %#018RX64",
2655 iOperand, *PtrUnion.pu64, pThis->MemOp.au64[0]);
2656 break;
2657 default:
2658 if (Bs3MemCmp(PtrUnion.pb, pThis->MemOp.ab, pThis->aOperands[iOperand].cbOp) == 0)
2659 continue;
2660 Bs3TestFailedF("op%u: Wrote %.*Rhxs, expected %.*Rhxs",
2661 iOperand,
2662 pThis->aOperands[iOperand].cbOp, PtrUnion.pb,
2663 pThis->aOperands[iOperand].cbOp, pThis->MemOp.ab);
2664 break;
2665 }
2666 fOkay = false;
2667 }
2668
2669 /*
2670 * Check extended context if enabled.
2671 */
2672 if (pThis->fWorkExtCtx)
2673 {
2674 PBS3EXTCTX pExpect = pThis->pExtCtx;
2675 PBS3EXTCTX pResult = pThis->pResultExtCtx;
2676 unsigned i;
2677 if ( pExpect->enmMethod == BS3EXTCTXMETHOD_XSAVE
2678 || pExpect->enmMethod == BS3EXTCTXMETHOD_FXSAVE)
2679 {
2680 /* Compare the x87 state, ASSUMING XCR0 bit 1 is set. */
2681#define CHECK_FIELD(a_Field, a_szFmt) \
2682 if (pResult->Ctx.a_Field != pExpect->Ctx.a_Field) fOkay = Bs3TestFailedF(a_szFmt, pResult->Ctx.a_Field, pExpect->Ctx.a_Field)
2683 CHECK_FIELD(x87.FCW, "FCW: %#06x, expected %#06x");
2684 CHECK_FIELD(x87.FSW, "FSW: %#06x, expected %#06x");
2685 CHECK_FIELD(x87.FTW, "FTW: %#06x, expected %#06x");
2686 //CHECK_FIELD(x87.FOP, "FOP: %#06x, expected %#06x");
2687 //CHECK_FIELD(x87.FPUIP, "FPUIP: %#010x, expected %#010x");
2688 //CHECK_FIELD(x87.CS, "FPUCS: %#06x, expected %#06x");
2689 //CHECK_FIELD(x87.Rsrvd1, "Rsrvd1: %#06x, expected %#06x");
2690 //CHECK_FIELD(x87.DP, "FPUDP: %#010x, expected %#010x");
2691 //CHECK_FIELD(x87.DS, "FPUDS: %#06x, expected %#06x");
2692 //CHECK_FIELD(x87.Rsrvd2, "Rsrvd2: %#06x, expected %#06x");
2693 CHECK_FIELD(x87.MXCSR, "MXCSR: %#010x, expected %#010x");
2694#undef CHECK_FIELD
2695 for (i = 0; i < RT_ELEMENTS(pExpect->Ctx.x87.aRegs); i++)
2696 if ( pResult->Ctx.x87.aRegs[i].au64[0] != pExpect->Ctx.x87.aRegs[i].au64[0]
2697 || pResult->Ctx.x87.aRegs[i].au16[4] != pExpect->Ctx.x87.aRegs[i].au16[4])
2698 fOkay = Bs3TestFailedF("ST[%u]: %c m=%#RX64 e=%d, expected %c m=%#RX64 e=%d", i,
2699 pResult->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
2700 pResult->Ctx.x87.aRegs[i].r80Ex.s.u64Mantissa,
2701 pResult->Ctx.x87.aRegs[i].r80Ex.s.uExponent,
2702 pExpect->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
2703 pExpect->Ctx.x87.aRegs[i].r80Ex.s.u64Mantissa,
2704 pExpect->Ctx.x87.aRegs[i].r80Ex.s.uExponent);
2705 for (i = 0; i < (ARCH_BITS == 64 ? 16 : 8); i++)
2706 if ( pResult->Ctx.x87.aXMM[i].au64[0] != pExpect->Ctx.x87.aXMM[i].au64[0]
2707 || pResult->Ctx.x87.aXMM[i].au64[1] != pExpect->Ctx.x87.aXMM[i].au64[1])
2708 fOkay = Bs3TestFailedF("XMM%u: %#010RX64'%08RX64, expected %#010RX64'%08RX64", i,
2709 pResult->Ctx.x87.aXMM[i].au64[0],
2710 pResult->Ctx.x87.aXMM[i].au64[1],
2711 pExpect->Ctx.x87.aXMM[i].au64[0],
2712 pExpect->Ctx.x87.aXMM[i].au64[1]);
2713 }
2714 else
2715 fOkay = Bs3TestFailedF("Unsupported extended CPU context method: %d", pExpect->enmMethod);
2716 }
2717
2718 /*
2719 * Done.
2720 */
2721 if (fOkay)
2722 return true;
2723
2724 /*
2725 * Report failure.
2726 */
2727 Bs3TestFailedF("%RU32[%u]: encoding#%u: %.*Rhxs",
2728 pThis->iInstr, pThis->iTest, iEncoding, pThis->cbCurInstr, pThis->abCurInstr);
2729 }
2730 else
2731 Bs3TestFailedF("%RU32[%u]: bXcpt=%#x expected %#x; rip=%RX64 expected %RX64; encoding#%u: %.*Rhxs",
2732 pThis->iInstr, pThis->iTest,
2733 pThis->TrapFrame.bXcpt, bExpectedXcpt,
2734 pThis->TrapFrame.Ctx.rip.u, pThis->Ctx.rip.u + cbAdjustPc,
2735 iEncoding, pThis->cbCurInstr, pThis->abCurInstr);
2736 Bs3TestPrintf("cpl=%u cbOperands=%u\n", pThis->uCpl, pThis->cbOperand);
2737
2738 /*
2739 * Display memory operands.
2740 */
2741 for (iOperand = 0; iOperand < pThis->cOperands; iOperand++)
2742 {
2743 BS3PTRUNION PtrUnion;
2744 switch (pThis->aOperands[iOperand].enmLocation)
2745 {
2746 case BS3CG1OPLOC_CTX:
2747 {
2748 uint8_t idxField = pThis->aOperands[iOperand].idxField;
2749 unsigned offField = g_aoffBs3Cg1DstFields[idxField];
2750 if (offField <= sizeof(BS3REGCTX))
2751 PtrUnion.pb = (uint8_t BS3_FAR *)&pThis->Ctx + offField;
2752 else
2753 {
2754 Bs3TestPrintf("op%u: ctx%u: xxxx\n", iOperand, pThis->aOperands[iOperand].cbOp * 8);
2755 break;
2756 }
2757 switch (pThis->aOperands[iOperand].cbOp)
2758 {
2759 case 1: Bs3TestPrintf("op%u: ctx08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2760 case 2: Bs3TestPrintf("op%u: ctx16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2761 case 4: Bs3TestPrintf("op%u: ctx32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2762 case 8: Bs3TestPrintf("op%u: ctx64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2763 default:
2764 Bs3TestPrintf("op%u: ctx%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2765 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2766 break;
2767 }
2768 break;
2769 }
2770
2771 case BS3CG1OPLOC_IMM:
2772 PtrUnion.pb = &pThis->pbCodePg[pThis->aOperands[iOperand].off];
2773 switch (pThis->aOperands[iOperand].cbOp)
2774 {
2775 case 1: Bs3TestPrintf("op%u: imm08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2776 case 2: Bs3TestPrintf("op%u: imm16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2777 case 4: Bs3TestPrintf("op%u: imm32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2778 case 8: Bs3TestPrintf("op%u: imm64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2779 default:
2780 Bs3TestPrintf("op%u: imm%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2781 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2782 break;
2783 }
2784 break;
2785
2786 case BS3CG1OPLOC_MEM:
2787 case BS3CG1OPLOC_MEM_RW:
2788 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
2789 switch (pThis->aOperands[iOperand].cbOp)
2790 {
2791 case 1: Bs3TestPrintf("op%u: result mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2792 case 2: Bs3TestPrintf("op%u: result mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2793 case 4: Bs3TestPrintf("op%u: result mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2794 case 8: Bs3TestPrintf("op%u: result mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2795 default:
2796 Bs3TestPrintf("op%u: result mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2797 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2798 break;
2799 }
2800 if (pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
2801 {
2802 PtrUnion.pb = pThis->MemOp.ab;
2803 switch (pThis->aOperands[iOperand].cbOp)
2804 {
2805 case 1: Bs3TestPrintf("op%u: expect mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
2806 case 2: Bs3TestPrintf("op%u: expect mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
2807 case 4: Bs3TestPrintf("op%u: expect mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
2808 case 8: Bs3TestPrintf("op%u: expect mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
2809 default:
2810 Bs3TestPrintf("op%u: expect mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
2811 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
2812 break;
2813 }
2814 }
2815 break;
2816 }
2817 }
2818
2819 /*
2820 * Display contexts.
2821 */
2822 Bs3TestPrintf("-- Expected context:\n");
2823 Bs3RegCtxPrint(&pThis->Ctx);
2824 Bs3TestPrintf("-- Actual context:\n");
2825 Bs3TrapPrintFrame(&pThis->TrapFrame);
2826 Bs3TestPrintf("\n");
2827 return false;
2828}
2829
2830
2831/**
2832 * Destroys the state, freeing all allocations and such.
2833 *
2834 * @param pThis The state.
2835 */
2836static void Bs3Cg1Destroy(PBS3CG1STATE pThis)
2837{
2838 if (BS3_MODE_IS_PAGED(pThis->bMode))
2839 {
2840#if ARCH_BITS != 16
2841 Bs3MemGuardedTestPageFree(pThis->pbCodePg);
2842 Bs3MemGuardedTestPageFree(pThis->pbDataPg);
2843#endif
2844 }
2845 else
2846 {
2847 Bs3MemFree(pThis->pbCodePg, X86_PAGE_SIZE);
2848 Bs3MemFree(pThis->pbDataPg, X86_PAGE_SIZE);
2849 }
2850
2851 if (pThis->pExtCtx)
2852 Bs3MemFree(pThis->pExtCtx, pThis->pExtCtx->cb * 3);
2853
2854 pThis->pbCodePg = NULL;
2855 pThis->pbDataPg = NULL;
2856 pThis->pExtCtx = NULL;
2857 pThis->pResultExtCtx = NULL;
2858 pThis->pInitialExtCtx = NULL;
2859}
2860
2861
2862/**
2863 * Initializes the state.
2864 *
2865 * @returns Success indicator (true/false)
2866 * @param pThis The state.
2867 * @param bMode The mode being tested.
2868 */
2869bool BS3_CMN_NM(Bs3Cg1Init)(PBS3CG1STATE pThis, uint8_t bMode)
2870{
2871 BS3MEMKIND const enmMemKind = BS3_MODE_IS_RM_OR_V86(bMode) ? BS3MEMKIND_REAL
2872 : !BS3_MODE_IS_64BIT_CODE(bMode) ? BS3MEMKIND_TILED : BS3MEMKIND_FLAT32;
2873 unsigned iRing;
2874 unsigned cb;
2875 unsigned i;
2876 uint64_t fFlags;
2877 PBS3EXTCTX pExtCtx;
2878
2879 Bs3MemSet(pThis, 0, sizeof(*pThis));
2880
2881 pThis->iFirstRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
2882 pThis->iEndRing = BS3_MODE_IS_RM_SYS(bMode) ? 1 : 4;
2883 pThis->bMode = bMode;
2884 pThis->pszMode = Bs3GetModeName(bMode);
2885 pThis->pszModeShort = Bs3GetModeNameShortLower(bMode);
2886 pThis->pchMnemonic = g_achBs3Cg1Mnemonics;
2887 pThis->pabOperands = g_abBs3Cg1Operands;
2888 pThis->pabOpcodes = g_abBs3Cg1Opcodes;
2889 pThis->fAdvanceMnemonic = 1;
2890
2891 /* Allocate extended context structures. */
2892 cb = Bs3ExtCtxGetSize(&fFlags);
2893 pExtCtx = Bs3MemAlloc(BS3MEMKIND_TILED, cb * 3);
2894 if (!pExtCtx)
2895 return Bs3TestFailedF("Bs3MemAlloc(tiled,%#x)", cb * 3);
2896 pThis->pExtCtx = pExtCtx;
2897 pThis->pResultExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb);
2898 pThis->pInitialExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb + cb);
2899
2900 Bs3ExtCtxInit(pThis->pExtCtx, cb, fFlags);
2901 Bs3ExtCtxInit(pThis->pResultExtCtx, cb, fFlags);
2902 Bs3ExtCtxInit(pThis->pInitialExtCtx, cb, fFlags);
2903 //Bs3TestPrintf("fCR0=%RX64 cbExtCtx=%#x method=%d\n", fFlags, cb, pExtCtx->enmMethod);
2904
2905 /* Allocate guarded exectuable and data memory. */
2906 if (BS3_MODE_IS_PAGED(bMode))
2907 {
2908#if ARCH_BITS != 16
2909 pThis->pbCodePg = Bs3MemGuardedTestPageAlloc(enmMemKind);
2910 pThis->pbDataPg = Bs3MemGuardedTestPageAlloc(enmMemKind);
2911 if (!pThis->pbCodePg || !pThis->pbDataPg)
2912 {
2913 Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
2914 Bs3MemPrintInfo();
2915 Bs3Shutdown();
2916 return Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
2917 }
2918 if ( BS3_MODE_IS_64BIT_CODE(bMode)
2919 && (uintptr_t)pThis->pbDataPg >= _2G)
2920 return Bs3TestFailedF("pbDataPg=%p is above 2GB and not simple to address from 64-bit code", pThis->pbDataPg);
2921#else
2922 return Bs3TestFailed("WTF?! #1");
2923#endif
2924 }
2925 else
2926 {
2927 pThis->pbCodePg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
2928 pThis->pbDataPg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
2929 if (!pThis->pbCodePg || !pThis->pbDataPg)
2930 {
2931 Bs3MemPrintInfo();
2932 return Bs3TestFailedF("Bs3MemAlloc(%d,Pg) failed", enmMemKind);
2933 }
2934 }
2935 pThis->uCodePgFlat = Bs3SelPtrToFlat(pThis->pbCodePg);
2936 pThis->uDataPgFlat = Bs3SelPtrToFlat(pThis->pbDataPg);
2937#if ARCH_BITS == 16
2938 pThis->CodePgFar.sel = BS3_FP_SEG(pThis->pbCodePg);
2939 pThis->CodePgFar.off = BS3_FP_OFF(pThis->pbCodePg);
2940 pThis->CodePgRip = BS3_FP_OFF(pThis->pbCodePg);
2941 pThis->DataPgFar.sel = BS3_FP_SEG(pThis->pbDataPg);
2942 pThis->DataPgFar.off = BS3_FP_OFF(pThis->pbDataPg);
2943#else
2944 if (BS3_MODE_IS_RM_OR_V86(bMode))
2945 {
2946 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToRealMode(pThis->uDataPgFlat);
2947 ASMCompilerBarrier();
2948 pThis->CodePgFar.off = 0;
2949 pThis->CodePgFar.sel = pThis->uCodePgFlat >> 4;
2950 pThis->CodePgRip = pThis->CodePgFar.off;
2951 }
2952 else if (BS3_MODE_IS_16BIT_CODE(bMode))
2953 {
2954 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
2955 ASMCompilerBarrier();
2956 pThis->CodePgFar.sel = BS3_SEL_SPARE_00;
2957 pThis->CodePgFar.off = 0;
2958 pThis->CodePgRip = 0;
2959 }
2960 else if (BS3_MODE_IS_32BIT_CODE(bMode))
2961 {
2962 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
2963 ASMCompilerBarrier();
2964 pThis->CodePgFar.sel = 0;
2965 pThis->CodePgFar.off = 0;
2966 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
2967 }
2968 else
2969 {
2970 pThis->DataPgFar.off = 0;
2971 pThis->DataPgFar.sel = 0;
2972 pThis->CodePgFar.off = 0;
2973 pThis->CodePgFar.sel = 0;
2974 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
2975 }
2976#endif
2977
2978 /*
2979 * Create basic context for each target ring.
2980 *
2981 * In protected 16-bit code we need set up code selectors that can access
2982 * pbCodePg.
2983 *
2984 * In long mode we make sure the high 32-bits of GPRs (sans RSP) have some
2985 * bits set so we can check that the implicit clearing is tested.
2986 */
2987 Bs3RegCtxSaveEx(&pThis->aInitialCtxs[pThis->iFirstRing], bMode, 1024 * 3);
2988#if ARCH_BITS == 64
2989 pThis->aInitialCtxs[pThis->iFirstRing].rax.u |= UINT64_C(0x0101010100000000);
2990 pThis->aInitialCtxs[pThis->iFirstRing].rbx.u |= UINT64_C(0x0202020200000000);
2991 pThis->aInitialCtxs[pThis->iFirstRing].rcx.u |= UINT64_C(0x0303030300000000);
2992 pThis->aInitialCtxs[pThis->iFirstRing].rdx.u |= UINT64_C(0x0404040400000000);
2993 pThis->aInitialCtxs[pThis->iFirstRing].rbp.u |= UINT64_C(0x0505050500000000);
2994 pThis->aInitialCtxs[pThis->iFirstRing].rdi.u |= UINT64_C(0x0606060600000000);
2995 pThis->aInitialCtxs[pThis->iFirstRing].rsi.u |= UINT64_C(0x0707070700000000);
2996 pThis->aInitialCtxs[pThis->iFirstRing].r8.u |= UINT64_C(0x0808080800000000);
2997 pThis->aInitialCtxs[pThis->iFirstRing].r9.u |= UINT64_C(0x0909090900000000);
2998 pThis->aInitialCtxs[pThis->iFirstRing].r10.u |= UINT64_C(0x1010101000000000);
2999 pThis->aInitialCtxs[pThis->iFirstRing].r11.u |= UINT64_C(0x1111111100000000);
3000 pThis->aInitialCtxs[pThis->iFirstRing].r12.u |= UINT64_C(0x1212121200000000);
3001 pThis->aInitialCtxs[pThis->iFirstRing].r13.u |= UINT64_C(0x1313131300000000);
3002 pThis->aInitialCtxs[pThis->iFirstRing].r14.u |= UINT64_C(0x1414141400000000);
3003 pThis->aInitialCtxs[pThis->iFirstRing].r15.u |= UINT64_C(0x1515151500000000);
3004#endif
3005
3006 if (BS3_MODE_IS_RM_OR_V86(bMode))
3007 {
3008 pThis->aInitialCtxs[pThis->iFirstRing].cs = pThis->CodePgFar.sel;
3009 BS3_ASSERT(pThis->iFirstRing + 1 == pThis->iEndRing);
3010 }
3011 else if (BS3_MODE_IS_16BIT_CODE(bMode))
3012 {
3013#if ARCH_BITS == 16
3014 uintptr_t const uFlatCodePgSeg = Bs3SelPtrToFlat(BS3_FP_MAKE(BS3_FP_SEG(pThis->pbCodePg), 0));
3015#else
3016 uintptr_t const uFlatCodePgSeg = (uintptr_t)pThis->pbCodePg;
3017#endif
3018 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
3019 {
3020 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
3021 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
3022 }
3023 for (iRing = pThis->iFirstRing; iRing < pThis->iEndRing; iRing++)
3024 {
3025 pThis->aInitialCtxs[iRing].cs = BS3_SEL_SPARE_00 + iRing * 8 + iRing;
3026 Bs3SelSetup16BitCode(&Bs3GdteSpare00 + iRing, uFlatCodePgSeg, iRing);
3027 }
3028 }
3029 else
3030 {
3031 Bs3RegCtxSetRipCsFromCurPtr(&pThis->aInitialCtxs[pThis->iFirstRing], (FPFNBS3FAR)pThis->pbCodePg);
3032 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
3033 {
3034 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
3035 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
3036 }
3037 }
3038
3039 /*
3040 * Create an initial extended CPU context.
3041 */
3042 pExtCtx = pThis->pInitialExtCtx;
3043 if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE
3044 || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
3045 {
3046 pExtCtx->Ctx.x87.FCW = X86_FCW_MASK_ALL | X86_FCW_PC_64 | X86_FCW_RC_NEAREST;
3047 pExtCtx->Ctx.x87.FSW = 0;
3048 pExtCtx->Ctx.x87.MXCSR = X86_MXCSR_IM | X86_MXCSR_DM | X86_MXCSR_RC_NEAREST;
3049 pExtCtx->Ctx.x87.MXCSR_MASK = 0;
3050 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aRegs); i++)
3051 {
3052 pExtCtx->Ctx.x87.aRegs[i].au16[0] = i << 4;
3053 pExtCtx->Ctx.x87.aRegs[i].au16[1] = i << 4;
3054 pExtCtx->Ctx.x87.aRegs[i].au16[2] = i << 4;
3055 pExtCtx->Ctx.x87.aRegs[i].au16[3] = i << 4;
3056 }
3057 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM); i++)
3058 {
3059 pExtCtx->Ctx.x87.aXMM[i].au16[0] = i;
3060 pExtCtx->Ctx.x87.aXMM[i].au16[1] = i;
3061 pExtCtx->Ctx.x87.aXMM[i].au16[2] = i;
3062 pExtCtx->Ctx.x87.aXMM[i].au16[3] = i;
3063 pExtCtx->Ctx.x87.aXMM[i].au16[4] = i;
3064 pExtCtx->Ctx.x87.aXMM[i].au16[5] = i;
3065 pExtCtx->Ctx.x87.aXMM[i].au16[6] = i;
3066 pExtCtx->Ctx.x87.aXMM[i].au16[7] = i;
3067 }
3068 if (pExtCtx->fXcr0 & XSAVE_C_YMM)
3069 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi); i++)
3070 {
3071 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[0] = i << 8;
3072 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[1] = i << 8;
3073 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[2] = i << 8;
3074 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[3] = i << 8;
3075 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[4] = i << 8;
3076 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[5] = i << 8;
3077 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[6] = i << 8;
3078 pExtCtx->Ctx.x.u.Intel.YmmHi.aYmmHi[i].au16[7] = i << 8;
3079 }
3080
3081 }
3082 //else if (pExtCtx->enmMethod == BS3EXTCTXMETHOD_ANCIENT)
3083 else
3084 return Bs3TestFailedF("Unsupported extended CPU context method: %d", pExtCtx->enmMethod);
3085
3086 return true;
3087}
3088
3089
3090static uint8_t BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
3091{
3092 uint8_t iRing;
3093 unsigned iInstr;
3094
3095 /*
3096 * Test the instructions.
3097 */
3098 for (iInstr = 0; iInstr < g_cBs3Cg1Instructions;
3099 iInstr++,
3100 pThis->pchMnemonic += pThis->fAdvanceMnemonic * pThis->cchMnemonic,
3101 pThis->pabOperands += pThis->cOperands,
3102 pThis->pabOpcodes += pThis->cbOpcodes)
3103 {
3104 bool fInvalidInstr = false;
3105 unsigned iCpuSetup;
3106 uint8_t bTestXcptExpected = BS3_MODE_IS_PAGED(pThis->bMode) ? X86_XCPT_PF : X86_XCPT_UD;
3107
3108 /*
3109 * Expand the instruction information into the state.
3110 * Note! 16-bit will switch to a two level test header lookup once we exceed 64KB.
3111 */
3112 PCBS3CG1INSTR pInstr = &g_aBs3Cg1Instructions[iInstr];
3113 pThis->iInstr = iInstr;
3114 pThis->pTestHdr = (PCBS3CG1TESTHDR)&g_abBs3Cg1Tests[pInstr->offTests];
3115 pThis->fFlags = pInstr->fFlags;
3116 pThis->enmEncoding = (BS3CG1ENC)pInstr->enmEncoding;
3117 pThis->enmCpuTest = (BS3CG1CPU)pInstr->enmCpuTest;
3118 pThis->enmPrefixKind = (BS3CG1PFXKIND)pInstr->enmPrefixKind;
3119 pThis->enmXcptType = (BS3CG1XCPTTYPE)pInstr->enmXcptType;
3120 pThis->cchMnemonic = pInstr->cchMnemonic;
3121 if (pThis->fAdvanceMnemonic)
3122 Bs3TestSubF("%s / %.*s", pThis->pszModeShort, pThis->cchMnemonic, pThis->pchMnemonic);
3123 pThis->fAdvanceMnemonic = pInstr->fAdvanceMnemonic;
3124 pThis->cOperands = pInstr->cOperands;
3125 pThis->cbOpcodes = pInstr->cbOpcodes;
3126 switch (pThis->cOperands)
3127 {
3128 case 3: pThis->aenmOperands[3] = (BS3CG1OP)pThis->pabOperands[3];
3129 case 2: pThis->aenmOperands[2] = (BS3CG1OP)pThis->pabOperands[2];
3130 case 1: pThis->aenmOperands[1] = (BS3CG1OP)pThis->pabOperands[1];
3131 case 0: pThis->aenmOperands[0] = (BS3CG1OP)pThis->pabOperands[0];
3132 }
3133
3134 switch (pThis->cbOpcodes)
3135 {
3136 case 3: pThis->abOpcodes[3] = pThis->pabOpcodes[3];
3137 case 2: pThis->abOpcodes[2] = pThis->pabOpcodes[2];
3138 case 1: pThis->abOpcodes[1] = pThis->pabOpcodes[1];
3139 case 0: pThis->abOpcodes[0] = pThis->pabOpcodes[0];
3140 }
3141
3142 /*
3143 * Check if the CPU supports the instruction.
3144 */
3145 if ( !Bs3Cg1CpuSetupFirst(pThis)
3146 || (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID)))
3147 {
3148 fInvalidInstr = true;
3149 bTestXcptExpected = X86_XCPT_UD;
3150 }
3151
3152 for (iCpuSetup = 0;; iCpuSetup++)
3153 {
3154 unsigned iEncoding;
3155 unsigned iEncodingNext;
3156
3157 /*
3158 * Prep the operands and encoding handling.
3159 */
3160 if (!Bs3Cg1EncodePrep(pThis))
3161 break;
3162
3163 /*
3164 * Encode the instruction in various ways and check out the test values.
3165 */
3166 for (iEncoding = 0;; iEncoding = iEncodingNext)
3167 {
3168 /*
3169 * Encode the next instruction variation.
3170 */
3171 iEncodingNext = Bs3Cg1EncodeNext(pThis, iEncoding);
3172 if (iEncodingNext <= iEncoding)
3173 break;
3174 BS3CG1_DPRINTF(("\ndbg: Encoding #%u: cbCurInst=%u: %.*Rhxs\n",
3175 iEncoding, pThis->cbCurInstr, pThis->cbCurInstr, pThis->abCurInstr));
3176
3177 /*
3178 * Do the rings.
3179 */
3180 for (iRing = pThis->iFirstRing + pThis->fSameRingNotOkay; iRing < pThis->iEndRing; iRing++)
3181 {
3182 PCBS3CG1TESTHDR pHdr;
3183
3184 pThis->uCpl = iRing;
3185 BS3CG1_DPRINTF(("dbg: Ring %u\n", iRing));
3186
3187 /*
3188 * Do the tests one by one.
3189 */
3190 pHdr = pThis->pTestHdr;
3191 for (pThis->iTest = 0;; pThis->iTest++)
3192 {
3193 if (Bs3Cg1RunSelector(pThis, pHdr))
3194 {
3195 /* Okay, set up the execution context. */
3196 unsigned offCode;
3197 uint8_t BS3_FAR *pbCode;
3198
3199 Bs3MemCpy(&pThis->Ctx, &pThis->aInitialCtxs[iRing], sizeof(pThis->Ctx));
3200 if (pThis->fWorkExtCtx)
3201 Bs3ExtCtxCopy(pThis->pExtCtx, pThis->pInitialExtCtx);
3202 if (BS3_MODE_IS_PAGED(pThis->bMode))
3203 {
3204 offCode = X86_PAGE_SIZE - pThis->cbCurInstr;
3205 pbCode = &pThis->pbCodePg[offCode];
3206 //if (iEncoding > 0) { pbCode[-1] = 0xf4; offCode--; }
3207 }
3208 else
3209 {
3210 pbCode = pThis->pbCodePg;
3211 pbCode[pThis->cbCurInstr] = 0x0f; /* UD2 */
3212 pbCode[pThis->cbCurInstr + 1] = 0x0b;
3213 offCode = 0;
3214 }
3215 pThis->Ctx.rip.u = pThis->CodePgRip + offCode;
3216 Bs3MemCpy(pbCode, pThis->abCurInstr, pThis->cbCurInstr);
3217
3218 if (Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr, pHdr->cbSelector, pHdr->cbInput, NULL, pbCode))
3219 {
3220 /* Run the instruction. */
3221 BS3CG1_DPRINTF(("dbg: Running test #%u\n", pThis->iTest));
3222 //Bs3RegCtxPrint(&pThis->Ctx);
3223 if (pThis->fWorkExtCtx)
3224 Bs3ExtCtxRestore(pThis->pExtCtx);
3225 Bs3TrapSetJmpAndRestore(&pThis->Ctx, &pThis->TrapFrame);
3226 if (pThis->fWorkExtCtx)
3227 Bs3ExtCtxSave(pThis->pResultExtCtx);
3228 BS3CG1_DPRINTF(("dbg: bXcpt=%#x rip=%RX64 -> %RX64\n",
3229 pThis->TrapFrame.bXcpt, pThis->Ctx.rip.u, pThis->TrapFrame.Ctx.rip.u));
3230
3231 /*
3232 * Apply the output modification program to the context.
3233 */
3234 pThis->Ctx.rflags.u32 &= ~X86_EFL_RF;
3235 pThis->Ctx.rflags.u32 |= pThis->TrapFrame.Ctx.rflags.u32 & X86_EFL_RF;
3236 pThis->bValueXcpt = UINT8_MAX;
3237 if ( fInvalidInstr
3238 || pThis->bAlignmentXcpt != UINT8_MAX
3239 || pThis->bValueXcpt != UINT8_MAX
3240 || Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr,
3241 pHdr->cbSelector + pHdr->cbInput, pHdr->cbOutput,
3242 &pThis->TrapFrame.Ctx, NULL /*pbCode*/))
3243 {
3244 Bs3Cg1CheckResult(pThis, fInvalidInstr, bTestXcptExpected, iEncoding);
3245 }
3246 }
3247 }
3248 else
3249 BS3CG1_DPRINTF(("dbg: Skipping #%u\n", pThis->iTest));
3250
3251 /* advance */
3252 if (pHdr->fLast)
3253 {
3254 BS3CG1_DPRINTF(("dbg: Last\n\n"));
3255 break;
3256 }
3257 pHdr = (PCBS3CG1TESTHDR)((uint8_t BS3_FAR *)(pHdr + 1) + pHdr->cbInput + pHdr->cbOutput + pHdr->cbSelector);
3258 }
3259 }
3260 }
3261
3262 /*
3263 * Clean up (segment registers, etc) and get the next CPU config.
3264 */
3265 Bs3Cg1EncodeCleanup(pThis);
3266 if (!Bs3Cg1CpuSetupNext(pThis, iCpuSetup, &fInvalidInstr))
3267 break;
3268 if (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID))
3269 fInvalidInstr = true;
3270 if (fInvalidInstr)
3271 bTestXcptExpected = X86_XCPT_UD;
3272 }
3273 }
3274
3275 return 0;
3276}
3277
3278
3279BS3_DECL_FAR(uint8_t) BS3_CMN_NM(Bs3Cg1Worker)(uint8_t bMode)
3280{
3281 uint8_t bRet = 1;
3282 BS3CG1STATE This;
3283
3284#if 0
3285 /* (for debugging) */
3286 if (!BS3_MODE_IS_RM_OR_V86(bMode))
3287 return BS3TESTDOMODE_SKIPPED;
3288#endif
3289
3290 if (BS3_CMN_NM(Bs3Cg1Init)(&This, bMode))
3291 {
3292 bRet = BS3_CMN_NM(Bs3Cg1WorkerInner)(&This);
3293 Bs3TestSubDone();
3294 }
3295 Bs3Cg1Destroy(&This);
3296
3297#if 0
3298 /* (for debugging) */
3299 if (bMode >= BS3_MODE_RM)
3300 {
3301 Bs3TestTerm();
3302 Bs3Shutdown();
3303 }
3304#endif
3305 return bRet;
3306}
3307
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