VirtualBox

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

Last change on this file since 105862 was 103262, checked in by vboxsync, 10 months ago

IPRT,VMMDev,Bs3Kit: Added support for sub-sub-tests to better deal with bs3-cpu-generated-1 and others with too many sub-tests for the test manager.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 266.1 KB
Line 
1/* $Id: bs3-cpu-generated-1-template.c 103262 2024-02-08 00:00:32Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-generated-1, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37#ifndef BS3_INSTANTIATING_CMN
38# error "BS3_INSTANTIATING_CMN not defined"
39#endif
40
41
42/*********************************************************************************************************************************
43* Header Files *
44*********************************************************************************************************************************/
45#include <iprt/asm.h>
46#include <iprt/asm-amd64-x86.h>
47
48#include "bs3-cpu-generated-1.h"
49
50
51/*********************************************************************************************************************************
52* Defined Constants And Macros *
53*********************************************************************************************************************************/
54#define BS3CG1_WITH_VEX
55
56#define P_CS X86_OP_PRF_CS
57#define P_SS X86_OP_PRF_SS
58#define P_DS X86_OP_PRF_DS
59#define P_ES X86_OP_PRF_ES
60#define P_FS X86_OP_PRF_FS
61#define P_GS X86_OP_PRF_GS
62#define P_OZ X86_OP_PRF_SIZE_OP
63#define P_AZ X86_OP_PRF_SIZE_ADDR
64#define P_LK X86_OP_PRF_LOCK
65#define P_RN X86_OP_PRF_REPNZ
66#define P_RZ X86_OP_PRF_REPZ
67
68#define REX_WRBX (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_B | X86_OP_REX_X)
69#define REX_W___ (X86_OP_REX_W)
70#define REX_WR__ (X86_OP_REX_W | X86_OP_REX_R)
71#define REX_W_B_ (X86_OP_REX_W | X86_OP_REX_B)
72#define REX_W__X (X86_OP_REX_W | X86_OP_REX_X)
73#define REX_WRB_ (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_B)
74#define REX_WR_X (X86_OP_REX_W | X86_OP_REX_R | X86_OP_REX_X)
75#define REX_W_BX (X86_OP_REX_W | X86_OP_REX_B | X86_OP_REX_X)
76#define REX__R__ (X86_OP_REX_R)
77#define REX__RB_ (X86_OP_REX_R | X86_OP_REX_B)
78#define REX__R_X (X86_OP_REX_R | X86_OP_REX_X)
79#define REX__RBX (X86_OP_REX_R | X86_OP_REX_B | X86_OP_REX_X)
80#define REX___B_ (X86_OP_REX_B)
81#define REX___BX (X86_OP_REX_B | X86_OP_REX_X)
82#define REX____X (X86_OP_REX_X)
83#define REX_____ (0x40)
84
85
86/** @def BS3CG1_DPRINTF
87 * Debug print macro.
88 */
89#if 0
90# define BS3CG1_DPRINTF(a_ArgList) Bs3TestPrintf a_ArgList
91# define BS3CG1_DEBUG_CTX_MOD
92#else
93# define BS3CG1_DPRINTF(a_ArgList) do { } while (0)
94#endif
95
96/**
97 * Checks if this is a 64-bit test target or not.
98 * Helps avoid ifdefs or code bloat.
99 */
100#if ARCH_BITS == 64
101# define BS3CG1_IS_64BIT_TARGET(a_pThis) BS3_MODE_IS_64BIT_CODE((a_pThis)->bMode)
102#else
103# define BS3CG1_IS_64BIT_TARGET(a_pThis) (false)
104#endif
105
106
107/*********************************************************************************************************************************
108* Structures and Typedefs *
109*********************************************************************************************************************************/
110/** Operand value location. */
111typedef enum BS3CG1OPLOC
112{
113 BS3CG1OPLOC_INVALID = 0,
114 BS3CG1OPLOC_CTX,
115 BS3CG1OPLOC_CTX_ZX_VLMAX,
116 BS3CG1OPLOC_IMM,
117 BS3CG1OPLOC_MEM,
118 BS3CG1OPLOC_MEM_RW,
119 BS3CG1OPLOC_MEM_WO,
120 BS3CG1OPLOC_END
121} BS3CG1OPLOC;
122AssertCompile(BS3CG1OPLOC_END <= 16);
123
124
125/** Pointer to the generated test state. */
126typedef struct BS3CG1STATE *PBS3CG1STATE;
127
128/**
129 * Encoder callback.
130 * @returns Next encoding. If equal or less to @a iEncoding, no
131 * further encodings are available for testing.
132 * @param pThis The state.
133 * @param iEncoding The encoding.
134 */
135typedef unsigned BS3_NEAR_CODE FNBS3CG1ENCODER(PBS3CG1STATE pThis, unsigned iEncoding);
136/** Pointer to a encoder callback. */
137typedef FNBS3CG1ENCODER *PFNBS3CG1ENCODER;
138
139
140/**
141 * The state.
142 */
143typedef struct BS3CG1STATE
144{
145 /** @name Instruction details (expanded from BS3CG1INSTR).
146 * @{ */
147 /** Pointer to the mnemonic string (not terminated) (g_achBs3Cg1Mnemonics). */
148 const char BS3_FAR *pchMnemonic;
149 /** Pointer to the test header. */
150 PCBS3CG1TESTHDR pTestHdr;
151 /** Pointer to the per operand flags (g_abBs3Cg1Operands). */
152 const uint8_t BS3_FAR *pabOperands;
153 /** Opcode bytes (g_abBs3Cg1Opcodes). */
154 const uint8_t BS3_FAR *pabOpcodes;
155 /** The current instruction number in the input array (for error reporting). */
156 uint32_t iInstr;
157
158 /** The instruction flags. */
159 uint32_t fFlags;
160 /** The encoding. */
161 BS3CG1ENC enmEncoding;
162 /** The non-invalid encoding. This may differ from enmEncoding when
163 * Bs3Cg1CalcNoneIntelInvalidEncoding has been called. */
164 BS3CG1ENC enmEncodingNonInvalid;
165 /** The CPU test / CPU ID. */
166 BS3CG1CPU enmCpuTest;
167 /** Prefix sensitivity and requirements. */
168 BS3CG1PFXKIND enmPrefixKind;
169 /** Exception type (SSE, AVX). */
170 BS3CG1XCPTTYPE enmXcptType;
171 /** Per operand flags. */
172 BS3CG1OP aenmOperands[4];
173 /** Opcode bytes. */
174 uint8_t abOpcodes[4];
175 /** The instruction encoder. */
176 PFNBS3CG1ENCODER pfnEncoder;
177
178 /** The length of the mnemonic. */
179 uint8_t cchMnemonic;
180 /** Whether to advance the mnemonic pointer or not. */
181 uint8_t fAdvanceMnemonic;
182 /** The opcode map number. */
183 uint8_t uOpcodeMap;
184 /** The number of opcode bytes. */
185 uint8_t cbOpcodes;
186 /** Number of operands. */
187 uint8_t cOperands;
188 /** @} */
189
190 /** Default operand size. */
191 uint8_t cbOpDefault;
192 /** Operand size when overridden by 066h. */
193 uint8_t cbOpOvrd66;
194 /** Operand size when overridden by REX.W. */
195 uint8_t cbOpOvrdRexW;
196
197 /** Operand size in bytes (0 if not applicable). */
198 uint8_t cbOperand;
199 /** Current VEX.L value (UINT8_MAX if not applicable). */
200 uint8_t uVexL;
201 /** Current target ring (0..3). */
202 uint8_t uCpl;
203
204 /** The current test number. */
205 uint8_t iTest;
206
207 /** Target mode (g_bBs3CurrentMode). */
208 uint8_t bMode;
209 /** The CPU vendor (BS3CPUVENDOR). */
210 uint8_t bCpuVendor;
211 /** First ring being tested. */
212 uint8_t iFirstRing;
213 /** End of rings being tested. */
214 uint8_t iEndRing;
215
216 /** @name Current encoded instruction.
217 * @{ */
218 /** The size of the current instruction that we're testing. */
219 uint8_t cbCurInstr;
220 /** The size the prefixes. */
221 uint8_t cbCurPrefix;
222 /** The offset into abCurInstr of the immediate. */
223 uint8_t offCurImm;
224 /** Buffer for assembling the current instruction. */
225 uint8_t abCurInstr[23];
226
227 /** Set if the encoding can't be tested in the same ring as this test code.
228 * This is used to deal with encodings modifying SP/ESP/RSP. */
229 bool fSameRingNotOkay;
230 /** Whether to work the extended context too. */
231 bool fWorkExtCtx;
232 /** The aOperands index of the modrm.reg operand (if applicable). */
233 uint8_t iRegOp;
234 /** The aOperands index of the modrm.rm operand (if applicable). */
235 uint8_t iRmOp;
236
237 /** Operands details. */
238 struct
239 {
240 uint8_t cbOp;
241 /** BS3CG1OPLOC_XXX. */
242 uint8_t enmLocation;
243 /** BS3CG1OPLOC_XXX for memory encodings (MODRM.rm field). */
244 uint8_t enmLocationMem : 4;
245 /** BS3CG1OPLOC_XXX for register encodings (MODRM.rm field). */
246 uint8_t enmLocationReg : 4;
247 /** The BS3CG1DST value for this field.
248 * Set to BS3CG1DST_INVALID if memory or immediate. */
249 uint8_t idxField;
250 /** The base BS3CG1DST value for this field.
251 * Used only by some generalized encoders when dealing with registers. */
252 uint8_t idxFieldBase;
253 /** Depends on enmLocation.
254 * - BS3CG1OPLOC_IMM: offset relative to start of the instruction.
255 * - BS3CG1OPLOC_MEM: offset should be subtracted from &pbDataPg[_4K].
256 * - BS3CG1OPLOC_MEM_RW: offset should be subtracted from &pbDataPg[_4K].
257 * - BS3CG1OPLOC_MEM_RO: offset should be subtracted from &pbDataPg[_4K].
258 * - BS3CG1OPLOC_CTX: not used (use idxField instead).
259 */
260 uint8_t off;
261 } aOperands[4];
262 /** @} */
263
264 /** Page to put code in. When paging is enabled, the page before and after
265 * are marked not-present. */
266 uint8_t BS3_FAR *pbCodePg;
267 /** The flat address corresponding to pbCodePg. */
268 uintptr_t uCodePgFlat;
269 /** The 16-bit address corresponding to pbCodePg if relevant for bMode. */
270 RTFAR16 CodePgFar;
271 /** The IP/EIP/RIP value for pbCodePg[0] relative to CS (bMode). */
272 uintptr_t CodePgRip;
273
274 /** Page for placing data operands in. When paging is enabled, the page before
275 * and after are marked not-present. */
276 uint8_t BS3_FAR *pbDataPg;
277 /** The flat address corresponding to pbDataPg. */
278 uintptr_t uDataPgFlat;
279 /** The 16-bit address corresponding to pbDataPg. */
280 RTFAR16 DataPgFar;
281
282 /** The name corresponding to bMode. */
283 const char BS3_FAR *pszMode;
284 /** The short name corresponding to bMode. */
285 const char BS3_FAR *pszModeShort;
286
287 /** @name Expected result (modifiable by output program).
288 * @{ */
289 /** The expected exception based on operand values or result.
290 * UINT8_MAX if no special exception expected. */
291 uint8_t bValueXcpt;
292 /** @} */
293 /** Alignment exception expected by the encoder.
294 * UINT8_MAX if no special exception expected. */
295 uint8_t bAlignmentXcpt;
296 /** Set by the encoding method to indicating invalid encoding. */
297 bool fInvalidEncoding;
298 /** The result of Bs3Cg1CpuSetupFirst(). */
299 bool fCpuSetupFirstResult;
300
301 /** The context we're working on. */
302 BS3REGCTX Ctx;
303 /** The trap context and frame. */
304 BS3TRAPFRAME TrapFrame;
305 /** Initial contexts, one for each ring. */
306 BS3REGCTX aInitialCtxs[4];
307
308 /** The extended context we're working on (input, expected output). */
309 PBS3EXTCTX pExtCtx;
310 /** The extended result context (analoguous to TrapFrame). */
311 PBS3EXTCTX pResultExtCtx;
312 /** The initial extended context. */
313 PBS3EXTCTX pInitialExtCtx;
314
315 /** Memory operand scratch space. */
316 union
317 {
318 uint8_t ab[128];
319 uint16_t au16[128 / sizeof(uint16_t)];
320 uint32_t au32[128 / sizeof(uint32_t)];
321 uint64_t au64[128 / sizeof(uint64_t)];
322 } MemOp;
323
324 /** Array parallel to aInitialCtxs for saving segment registers. */
325 struct
326 {
327 RTSEL ds;
328 } aSavedSegRegs[4];
329
330} BS3CG1STATE;
331
332
333#define BS3CG1_PF_OZ UINT16_C(0x0001)
334#define BS3CG1_PF_AZ UINT16_C(0x0002)
335#define BS3CG1_PF_CS UINT16_C(0x0004)
336#define BS3CG1_PF_DS UINT16_C(0x0008)
337#define BS3CG1_PF_ES UINT16_C(0x0010)
338#define BS3CG1_PF_FS UINT16_C(0x0020)
339#define BS3CG1_PF_GS UINT16_C(0x0040)
340#define BS3CG1_PF_SS UINT16_C(0x0080)
341#define BS3CG1_PF_SEGS (BS3CG1_PF_CS | BS3CG1_PF_DS | BS3CG1_PF_ES | BS3CG1_PF_FS | BS3CG1_PF_GS | BS3CG1_PF_SS)
342#define BS3CG1_PF_MEM (BS3CG1_PF_SEGS | BS3CG1_PF_AZ)
343#define BS3CG1_PF_LK UINT16_C(0x0100)
344#define BS3CG1_PF_RN UINT16_C(0x0200)
345#define BS3CG1_PF_RZ UINT16_C(0x0400)
346#define BS3CG1_PF_W UINT16_C(0x0800) /**< REX.W */
347#define BS3CG1_PF_R UINT16_C(0x1000) /**< REX.R */
348#define BS3CG1_PF_B UINT16_C(0x2000) /**< REX.B */
349#define BS3CG1_PF_X UINT16_C(0x4000) /**< REX.X */
350
351
352/** Used in g_cbBs3Cg1DstFields to indicate that it's one of the 4 operands. */
353#define BS3CG1DSTSIZE_OPERAND UINT8_C(255)
354/** Used in g_cbBs3Cg1DstFields to indicate that the operand size determins
355 * the field size (2, 4, or 8). */
356#define BS3CG1DSTSIZE_OPERAND_SIZE_GRP UINT8_C(254)
357
358
359
360/*********************************************************************************************************************************
361* Global Variables *
362*********************************************************************************************************************************/
363/** Destination field sizes indexed by bBS3CG1DST.
364 * Zero means operand size sized. */
365static const uint8_t g_acbBs3Cg1DstFields[] =
366{
367 /* [BS3CG1DST_INVALID] = */ BS3CG1DSTSIZE_OPERAND,
368
369 /* [BS3CG1DST_OP1] = */ BS3CG1DSTSIZE_OPERAND,
370 /* [BS3CG1DST_OP2] = */ BS3CG1DSTSIZE_OPERAND,
371 /* [BS3CG1DST_OP3] = */ BS3CG1DSTSIZE_OPERAND,
372 /* [BS3CG1DST_OP4] = */ BS3CG1DSTSIZE_OPERAND,
373 /* [BS3CG1DST_EFL] = */ 4,
374 /* [BS3CG1DST_EFL_UNDEF]=*/ 4,
375
376 /* [BS3CG1DST_AL] = */ 1,
377 /* [BS3CG1DST_CL] = */ 1,
378 /* [BS3CG1DST_DL] = */ 1,
379 /* [BS3CG1DST_BL] = */ 1,
380 /* [BS3CG1DST_AH] = */ 1,
381 /* [BS3CG1DST_CH] = */ 1,
382 /* [BS3CG1DST_DH] = */ 1,
383 /* [BS3CG1DST_BH] = */ 1,
384 /* [BS3CG1DST_SPL] = */ 1,
385 /* [BS3CG1DST_BPL] = */ 1,
386 /* [BS3CG1DST_SIL] = */ 1,
387 /* [BS3CG1DST_DIL] = */ 1,
388 /* [BS3CG1DST_R8L] = */ 1,
389 /* [BS3CG1DST_R9L] = */ 1,
390 /* [BS3CG1DST_R10L] = */ 1,
391 /* [BS3CG1DST_R11L] = */ 1,
392 /* [BS3CG1DST_R12L] = */ 1,
393 /* [BS3CG1DST_R13L] = */ 1,
394 /* [BS3CG1DST_R14L] = */ 1,
395 /* [BS3CG1DST_R15L] = */ 1,
396
397 /* [BS3CG1DST_AX] = */ 2,
398 /* [BS3CG1DST_CX] = */ 2,
399 /* [BS3CG1DST_DX] = */ 2,
400 /* [BS3CG1DST_BX] = */ 2,
401 /* [BS3CG1DST_SP] = */ 2,
402 /* [BS3CG1DST_BP] = */ 2,
403 /* [BS3CG1DST_SI] = */ 2,
404 /* [BS3CG1DST_DI] = */ 2,
405 /* [BS3CG1DST_R8W] = */ 2,
406 /* [BS3CG1DST_R9W] = */ 2,
407 /* [BS3CG1DST_R10W] = */ 2,
408 /* [BS3CG1DST_R11W] = */ 2,
409 /* [BS3CG1DST_R12W] = */ 2,
410 /* [BS3CG1DST_R13W] = */ 2,
411 /* [BS3CG1DST_R14W] = */ 2,
412 /* [BS3CG1DST_R15W] = */ 2,
413
414 /* [BS3CG1DST_EAX] = */ 4,
415 /* [BS3CG1DST_ECX] = */ 4,
416 /* [BS3CG1DST_EDX] = */ 4,
417 /* [BS3CG1DST_EBX] = */ 4,
418 /* [BS3CG1DST_ESP] = */ 4,
419 /* [BS3CG1DST_EBP] = */ 4,
420 /* [BS3CG1DST_ESI] = */ 4,
421 /* [BS3CG1DST_EDI] = */ 4,
422 /* [BS3CG1DST_R8D] = */ 4,
423 /* [BS3CG1DST_R9D] = */ 4,
424 /* [BS3CG1DST_R10D] = */ 4,
425 /* [BS3CG1DST_R11D] = */ 4,
426 /* [BS3CG1DST_R12D] = */ 4,
427 /* [BS3CG1DST_R13D] = */ 4,
428 /* [BS3CG1DST_R14D] = */ 4,
429 /* [BS3CG1DST_R15D] = */ 4,
430
431 /* [BS3CG1DST_RAX] = */ 8,
432 /* [BS3CG1DST_RCX] = */ 8,
433 /* [BS3CG1DST_RDX] = */ 8,
434 /* [BS3CG1DST_RBX] = */ 8,
435 /* [BS3CG1DST_RSP] = */ 8,
436 /* [BS3CG1DST_RBP] = */ 8,
437 /* [BS3CG1DST_RSI] = */ 8,
438 /* [BS3CG1DST_RDI] = */ 8,
439 /* [BS3CG1DST_R8] = */ 8,
440 /* [BS3CG1DST_R9] = */ 8,
441 /* [BS3CG1DST_R10] = */ 8,
442 /* [BS3CG1DST_R11] = */ 8,
443 /* [BS3CG1DST_R12] = */ 8,
444 /* [BS3CG1DST_R13] = */ 8,
445 /* [BS3CG1DST_R14] = */ 8,
446 /* [BS3CG1DST_R15] = */ 8,
447
448 /* [BS3CG1DST_OZ_RAX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
449 /* [BS3CG1DST_OZ_RCX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
450 /* [BS3CG1DST_OZ_RDX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
451 /* [BS3CG1DST_OZ_RBX] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
452 /* [BS3CG1DST_OZ_RSP] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
453 /* [BS3CG1DST_OZ_RBP] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
454 /* [BS3CG1DST_OZ_RSI] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
455 /* [BS3CG1DST_OZ_RDI] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
456 /* [BS3CG1DST_OZ_R8] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
457 /* [BS3CG1DST_OZ_R9] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
458 /* [BS3CG1DST_OZ_R10] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
459 /* [BS3CG1DST_OZ_R11] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
460 /* [BS3CG1DST_OZ_R12] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
461 /* [BS3CG1DST_OZ_R13] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
462 /* [BS3CG1DST_OZ_R14] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
463 /* [BS3CG1DST_OZ_R15] = */ BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
464
465 /* [BS3CG1DST_CR0] = */ 4,
466 /* [BS3CG1DST_CR4] = */ 4,
467 /* [BS3CG1DST_XCR0] = */ 8,
468
469 /* [BS3CG1DST_FCW] = */ 2,
470 /* [BS3CG1DST_FSW] = */ 2,
471 /* [BS3CG1DST_FTW] = */ 2,
472 /* [BS3CG1DST_FOP] = */ 2,
473 /* [BS3CG1DST_FPUIP] = */ 2,
474 /* [BS3CG1DST_FPUCS] = */ 2,
475 /* [BS3CG1DST_FPUDP] = */ 2,
476 /* [BS3CG1DST_FPUDS] = */ 2,
477 /* [BS3CG1DST_MXCSR] = */ 4,
478 /* [BS3CG1DST_ST0] = */ 12,
479 /* [BS3CG1DST_ST1] = */ 12,
480 /* [BS3CG1DST_ST2] = */ 12,
481 /* [BS3CG1DST_ST3] = */ 12,
482 /* [BS3CG1DST_ST4] = */ 12,
483 /* [BS3CG1DST_ST5] = */ 12,
484 /* [BS3CG1DST_ST6] = */ 12,
485 /* [BS3CG1DST_ST7] = */ 12,
486 /* [BS3CG1DST_MM0] = */ 8,
487 /* [BS3CG1DST_MM1] = */ 8,
488 /* [BS3CG1DST_MM2] = */ 8,
489 /* [BS3CG1DST_MM3] = */ 8,
490 /* [BS3CG1DST_MM4] = */ 8,
491 /* [BS3CG1DST_MM5] = */ 8,
492 /* [BS3CG1DST_MM6] = */ 8,
493 /* [BS3CG1DST_MM7] = */ 8,
494 /* [BS3CG1DST_MM0_LO_ZX] = */ 4,
495 /* [BS3CG1DST_MM1_LO_ZX] = */ 4,
496 /* [BS3CG1DST_MM2_LO_ZX] = */ 4,
497 /* [BS3CG1DST_MM3_LO_ZX] = */ 4,
498 /* [BS3CG1DST_MM4_LO_ZX] = */ 4,
499 /* [BS3CG1DST_MM5_LO_ZX] = */ 4,
500 /* [BS3CG1DST_MM6_LO_ZX] = */ 4,
501 /* [BS3CG1DST_MM7_LO_ZX] = */ 4,
502 /* [BS3CG1DST_XMM0] = */ 16,
503 /* [BS3CG1DST_XMM1] = */ 16,
504 /* [BS3CG1DST_XMM2] = */ 16,
505 /* [BS3CG1DST_XMM3] = */ 16,
506 /* [BS3CG1DST_XMM4] = */ 16,
507 /* [BS3CG1DST_XMM5] = */ 16,
508 /* [BS3CG1DST_XMM6] = */ 16,
509 /* [BS3CG1DST_XMM7] = */ 16,
510 /* [BS3CG1DST_XMM8] = */ 16,
511 /* [BS3CG1DST_XMM9] = */ 16,
512 /* [BS3CG1DST_XMM10] = */ 16,
513 /* [BS3CG1DST_XMM11] = */ 16,
514 /* [BS3CG1DST_XMM12] = */ 16,
515 /* [BS3CG1DST_XMM13] = */ 16,
516 /* [BS3CG1DST_XMM14] = */ 16,
517 /* [BS3CG1DST_XMM15] = */ 16,
518 /* [BS3CG1DST_XMM0_LO] = */ 8,
519 /* [BS3CG1DST_XMM1_LO] = */ 8,
520 /* [BS3CG1DST_XMM2_LO] = */ 8,
521 /* [BS3CG1DST_XMM3_LO] = */ 8,
522 /* [BS3CG1DST_XMM4_LO] = */ 8,
523 /* [BS3CG1DST_XMM5_LO] = */ 8,
524 /* [BS3CG1DST_XMM6_LO] = */ 8,
525 /* [BS3CG1DST_XMM7_LO] = */ 8,
526 /* [BS3CG1DST_XMM8_LO] = */ 8,
527 /* [BS3CG1DST_XMM9_LO] = */ 8,
528 /* [BS3CG1DST_XMM10_LO] = */ 8,
529 /* [BS3CG1DST_XMM11_LO] = */ 8,
530 /* [BS3CG1DST_XMM12_LO] = */ 8,
531 /* [BS3CG1DST_XMM13_LO] = */ 8,
532 /* [BS3CG1DST_XMM14_LO] = */ 8,
533 /* [BS3CG1DST_XMM15_LO] = */ 8,
534 /* [BS3CG1DST_XMM0_HI] = */ 8,
535 /* [BS3CG1DST_XMM1_HI] = */ 8,
536 /* [BS3CG1DST_XMM2_HI] = */ 8,
537 /* [BS3CG1DST_XMM3_HI] = */ 8,
538 /* [BS3CG1DST_XMM4_HI] = */ 8,
539 /* [BS3CG1DST_XMM5_HI] = */ 8,
540 /* [BS3CG1DST_XMM6_HI] = */ 8,
541 /* [BS3CG1DST_XMM7_HI] = */ 8,
542 /* [BS3CG1DST_XMM8_HI] = */ 8,
543 /* [BS3CG1DST_XMM9_HI] = */ 8,
544 /* [BS3CG1DST_XMM10_HI] = */ 8,
545 /* [BS3CG1DST_XMM11_HI] = */ 8,
546 /* [BS3CG1DST_XMM12_HI] = */ 8,
547 /* [BS3CG1DST_XMM13_HI] = */ 8,
548 /* [BS3CG1DST_XMM14_HI] = */ 8,
549 /* [BS3CG1DST_XMM15_HI] = */ 8,
550 /* [BS3CG1DST_XMM0_LO_ZX] = */ 8,
551 /* [BS3CG1DST_XMM1_LO_ZX] = */ 8,
552 /* [BS3CG1DST_XMM2_LO_ZX] = */ 8,
553 /* [BS3CG1DST_XMM3_LO_ZX] = */ 8,
554 /* [BS3CG1DST_XMM4_LO_ZX] = */ 8,
555 /* [BS3CG1DST_XMM5_LO_ZX] = */ 8,
556 /* [BS3CG1DST_XMM6_LO_ZX] = */ 8,
557 /* [BS3CG1DST_XMM7_LO_ZX] = */ 8,
558 /* [BS3CG1DST_XMM8_LO_ZX] = */ 8,
559 /* [BS3CG1DST_XMM9_LO_ZX] = */ 8,
560 /* [BS3CG1DST_XMM10_LO_ZX] = */ 8,
561 /* [BS3CG1DST_XMM11_LO_ZX] = */ 8,
562 /* [BS3CG1DST_XMM12_LO_ZX] = */ 8,
563 /* [BS3CG1DST_XMM13_LO_ZX] = */ 8,
564 /* [BS3CG1DST_XMM14_LO_ZX] = */ 8,
565 /* [BS3CG1DST_XMM15_LO_ZX] = */ 8,
566 /* [BS3CG1DST_XMM0_DW0] = */ 4,
567 /* [BS3CG1DST_XMM1_DW0] = */ 4,
568 /* [BS3CG1DST_XMM2_DW0] = */ 4,
569 /* [BS3CG1DST_XMM3_DW0] = */ 4,
570 /* [BS3CG1DST_XMM4_DW0] = */ 4,
571 /* [BS3CG1DST_XMM5_DW0] = */ 4,
572 /* [BS3CG1DST_XMM6_DW0] = */ 4,
573 /* [BS3CG1DST_XMM7_DW0] = */ 4,
574 /* [BS3CG1DST_XMM8_DW0] = */ 4,
575 /* [BS3CG1DST_XMM9_DW0] = */ 4,
576 /* [BS3CG1DST_XMM10_DW0] = */ 4,
577 /* [BS3CG1DST_XMM11_DW0] = */ 4,
578 /* [BS3CG1DST_XMM12_DW0] = */ 4,
579 /* [BS3CG1DST_XMM13_DW0] = */ 4,
580 /* [BS3CG1DST_XMM14_DW0] = */ 4,
581 /* [BS3CG1DST_XMM15_DW0] = */ 4,
582 /* [BS3CG1DST_XMM0_DW0_ZX] = */ 4,
583 /* [BS3CG1DST_XMM1_DW0_ZX] = */ 4,
584 /* [BS3CG1DST_XMM2_DW0_ZX] = */ 4,
585 /* [BS3CG1DST_XMM3_DW0_ZX] = */ 4,
586 /* [BS3CG1DST_XMM4_DW0_ZX] = */ 4,
587 /* [BS3CG1DST_XMM5_DW0_ZX] = */ 4,
588 /* [BS3CG1DST_XMM6_DW0_ZX] = */ 4,
589 /* [BS3CG1DST_XMM7_DW0_ZX] = */ 4,
590 /* [BS3CG1DST_XMM8_DW0_ZX] = */ 4,
591 /* [BS3CG1DST_XMM9_DW0_ZX] = */ 4,
592 /* [BS3CG1DST_XMM10_DW0_ZX] =*/ 4,
593 /* [BS3CG1DST_XMM11_DW0_ZX] =*/ 4,
594 /* [BS3CG1DST_XMM12_DW0_ZX] =*/ 4,
595 /* [BS3CG1DST_XMM13_DW0_ZX] =*/ 4,
596 /* [BS3CG1DST_XMM14_DW0_ZX] =*/ 4,
597 /* [BS3CG1DST_XMM15_DW0_ZX] =*/ 4,
598 /* [BS3CG1DST_XMM0_HI96] = */ 12,
599 /* [BS3CG1DST_XMM1_HI96] = */ 12,
600 /* [BS3CG1DST_XMM2_HI96] = */ 12,
601 /* [BS3CG1DST_XMM3_HI96] = */ 12,
602 /* [BS3CG1DST_XMM4_HI96] = */ 12,
603 /* [BS3CG1DST_XMM5_HI96] = */ 12,
604 /* [BS3CG1DST_XMM6_HI96] = */ 12,
605 /* [BS3CG1DST_XMM7_HI96] = */ 12,
606 /* [BS3CG1DST_XMM8_HI96] = */ 12,
607 /* [BS3CG1DST_XMM9_HI96] = */ 12,
608 /* [BS3CG1DST_XMM10_HI96] =*/ 12,
609 /* [BS3CG1DST_XMM11_HI96] =*/ 12,
610 /* [BS3CG1DST_XMM12_HI96] =*/ 12,
611 /* [BS3CG1DST_XMM13_HI96] =*/ 12,
612 /* [BS3CG1DST_XMM14_HI96] =*/ 12,
613 /* [BS3CG1DST_XMM15_HI96] =*/ 12,
614 /* [BS3CG1DST_YMM0] = */ 32,
615 /* [BS3CG1DST_YMM1] = */ 32,
616 /* [BS3CG1DST_YMM2] = */ 32,
617 /* [BS3CG1DST_YMM3] = */ 32,
618 /* [BS3CG1DST_YMM4] = */ 32,
619 /* [BS3CG1DST_YMM5] = */ 32,
620 /* [BS3CG1DST_YMM6] = */ 32,
621 /* [BS3CG1DST_YMM7] = */ 32,
622 /* [BS3CG1DST_YMM8] = */ 32,
623 /* [BS3CG1DST_YMM9] = */ 32,
624 /* [BS3CG1DST_YMM10] = */ 32,
625 /* [BS3CG1DST_YMM11] = */ 32,
626 /* [BS3CG1DST_YMM12] = */ 32,
627 /* [BS3CG1DST_YMM13] = */ 32,
628 /* [BS3CG1DST_YMM14] = */ 32,
629 /* [BS3CG1DST_YMM15] = */ 32,
630
631 /* [BS3CG1DST_VALUE_XCPT] = */ 1,
632};
633AssertCompile(RT_ELEMENTS(g_acbBs3Cg1DstFields) == BS3CG1DST_END);
634
635/** Destination field offset indexed by bBS3CG1DST.
636 * Zero means operand size sized. */
637static const unsigned g_aoffBs3Cg1DstFields[] =
638{
639 /* [BS3CG1DST_INVALID] = */ ~0U,
640 /* [BS3CG1DST_OP1] = */ ~0U,
641 /* [BS3CG1DST_OP2] = */ ~0U,
642 /* [BS3CG1DST_OP3] = */ ~0U,
643 /* [BS3CG1DST_OP4] = */ ~0U,
644 /* [BS3CG1DST_EFL] = */ RT_OFFSETOF(BS3REGCTX, rflags),
645 /* [BS3CG1DST_EFL_UNDEF]=*/ ~0, /* special field */
646
647 /* [BS3CG1DST_AL] = */ RT_OFFSETOF(BS3REGCTX, rax.u8),
648 /* [BS3CG1DST_CL] = */ RT_OFFSETOF(BS3REGCTX, rcx.u8),
649 /* [BS3CG1DST_DL] = */ RT_OFFSETOF(BS3REGCTX, rdx.u8),
650 /* [BS3CG1DST_BL] = */ RT_OFFSETOF(BS3REGCTX, rbx.u8),
651 /* [BS3CG1DST_AH] = */ RT_OFFSETOF(BS3REGCTX, rax.b.bHi),
652 /* [BS3CG1DST_CH] = */ RT_OFFSETOF(BS3REGCTX, rcx.b.bHi),
653 /* [BS3CG1DST_DH] = */ RT_OFFSETOF(BS3REGCTX, rdx.b.bHi),
654 /* [BS3CG1DST_BH] = */ RT_OFFSETOF(BS3REGCTX, rbx.b.bHi),
655 /* [BS3CG1DST_SPL] = */ RT_OFFSETOF(BS3REGCTX, rsp.u8),
656 /* [BS3CG1DST_BPL] = */ RT_OFFSETOF(BS3REGCTX, rbp.u8),
657 /* [BS3CG1DST_SIL] = */ RT_OFFSETOF(BS3REGCTX, rsi.u8),
658 /* [BS3CG1DST_DIL] = */ RT_OFFSETOF(BS3REGCTX, rdi.u8),
659 /* [BS3CG1DST_R8L] = */ RT_OFFSETOF(BS3REGCTX, r8.u8),
660 /* [BS3CG1DST_R9L] = */ RT_OFFSETOF(BS3REGCTX, r9.u8),
661 /* [BS3CG1DST_R10L] = */ RT_OFFSETOF(BS3REGCTX, r10.u8),
662 /* [BS3CG1DST_R11L] = */ RT_OFFSETOF(BS3REGCTX, r11.u8),
663 /* [BS3CG1DST_R12L] = */ RT_OFFSETOF(BS3REGCTX, r12.u8),
664 /* [BS3CG1DST_R13L] = */ RT_OFFSETOF(BS3REGCTX, r13.u8),
665 /* [BS3CG1DST_R14L] = */ RT_OFFSETOF(BS3REGCTX, r14.u8),
666 /* [BS3CG1DST_R15L] = */ RT_OFFSETOF(BS3REGCTX, r15.u8),
667
668 /* [BS3CG1DST_AX] = */ RT_OFFSETOF(BS3REGCTX, rax.u16),
669 /* [BS3CG1DST_CX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u16),
670 /* [BS3CG1DST_DX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u16),
671 /* [BS3CG1DST_BX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u16),
672 /* [BS3CG1DST_SP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u16),
673 /* [BS3CG1DST_BP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u16),
674 /* [BS3CG1DST_SI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u16),
675 /* [BS3CG1DST_DI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u16),
676 /* [BS3CG1DST_R8W] = */ RT_OFFSETOF(BS3REGCTX, r8.u16),
677 /* [BS3CG1DST_R9W] = */ RT_OFFSETOF(BS3REGCTX, r9.u16),
678 /* [BS3CG1DST_R10W] = */ RT_OFFSETOF(BS3REGCTX, r10.u16),
679 /* [BS3CG1DST_R11W] = */ RT_OFFSETOF(BS3REGCTX, r11.u16),
680 /* [BS3CG1DST_R12W] = */ RT_OFFSETOF(BS3REGCTX, r12.u16),
681 /* [BS3CG1DST_R13W] = */ RT_OFFSETOF(BS3REGCTX, r13.u16),
682 /* [BS3CG1DST_R14W] = */ RT_OFFSETOF(BS3REGCTX, r14.u16),
683 /* [BS3CG1DST_R15W] = */ RT_OFFSETOF(BS3REGCTX, r15.u16),
684
685 /* [BS3CG1DST_EAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u32),
686 /* [BS3CG1DST_ECX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u32),
687 /* [BS3CG1DST_EDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u32),
688 /* [BS3CG1DST_EBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u32),
689 /* [BS3CG1DST_ESP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u32),
690 /* [BS3CG1DST_EBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u32),
691 /* [BS3CG1DST_ESI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u32),
692 /* [BS3CG1DST_EDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u32),
693 /* [BS3CG1DST_R8D] = */ RT_OFFSETOF(BS3REGCTX, r8.u32),
694 /* [BS3CG1DST_R9D] = */ RT_OFFSETOF(BS3REGCTX, r9.u32),
695 /* [BS3CG1DST_R10D] = */ RT_OFFSETOF(BS3REGCTX, r10.u32),
696 /* [BS3CG1DST_R11D] = */ RT_OFFSETOF(BS3REGCTX, r11.u32),
697 /* [BS3CG1DST_R12D] = */ RT_OFFSETOF(BS3REGCTX, r12.u32),
698 /* [BS3CG1DST_R13D] = */ RT_OFFSETOF(BS3REGCTX, r13.u32),
699 /* [BS3CG1DST_R14D] = */ RT_OFFSETOF(BS3REGCTX, r14.u32),
700 /* [BS3CG1DST_R15D] = */ RT_OFFSETOF(BS3REGCTX, r15.u32),
701
702 /* [BS3CG1DST_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax.u64),
703 /* [BS3CG1DST_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx.u64),
704 /* [BS3CG1DST_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx.u64),
705 /* [BS3CG1DST_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx.u64),
706 /* [BS3CG1DST_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp.u64),
707 /* [BS3CG1DST_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp.u64),
708 /* [BS3CG1DST_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi.u64),
709 /* [BS3CG1DST_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi.u64),
710 /* [BS3CG1DST_R8] = */ RT_OFFSETOF(BS3REGCTX, r8.u64),
711 /* [BS3CG1DST_R9] = */ RT_OFFSETOF(BS3REGCTX, r9.u64),
712 /* [BS3CG1DST_R10] = */ RT_OFFSETOF(BS3REGCTX, r10.u64),
713 /* [BS3CG1DST_R11] = */ RT_OFFSETOF(BS3REGCTX, r11.u64),
714 /* [BS3CG1DST_R12] = */ RT_OFFSETOF(BS3REGCTX, r12.u64),
715 /* [BS3CG1DST_R13] = */ RT_OFFSETOF(BS3REGCTX, r13.u64),
716 /* [BS3CG1DST_R14] = */ RT_OFFSETOF(BS3REGCTX, r14.u64),
717 /* [BS3CG1DST_R15] = */ RT_OFFSETOF(BS3REGCTX, r15.u64),
718
719 /* [BS3CG1DST_OZ_RAX] = */ RT_OFFSETOF(BS3REGCTX, rax),
720 /* [BS3CG1DST_OZ_RCX] = */ RT_OFFSETOF(BS3REGCTX, rcx),
721 /* [BS3CG1DST_OZ_RDX] = */ RT_OFFSETOF(BS3REGCTX, rdx),
722 /* [BS3CG1DST_OZ_RBX] = */ RT_OFFSETOF(BS3REGCTX, rbx),
723 /* [BS3CG1DST_OZ_RSP] = */ RT_OFFSETOF(BS3REGCTX, rsp),
724 /* [BS3CG1DST_OZ_RBP] = */ RT_OFFSETOF(BS3REGCTX, rbp),
725 /* [BS3CG1DST_OZ_RSI] = */ RT_OFFSETOF(BS3REGCTX, rsi),
726 /* [BS3CG1DST_OZ_RDI] = */ RT_OFFSETOF(BS3REGCTX, rdi),
727 /* [BS3CG1DST_OZ_R8] = */ RT_OFFSETOF(BS3REGCTX, r8),
728 /* [BS3CG1DST_OZ_R9] = */ RT_OFFSETOF(BS3REGCTX, r9),
729 /* [BS3CG1DST_OZ_R10] = */ RT_OFFSETOF(BS3REGCTX, r10),
730 /* [BS3CG1DST_OZ_R11] = */ RT_OFFSETOF(BS3REGCTX, r11),
731 /* [BS3CG1DST_OZ_R12] = */ RT_OFFSETOF(BS3REGCTX, r12),
732 /* [BS3CG1DST_OZ_R13] = */ RT_OFFSETOF(BS3REGCTX, r13),
733 /* [BS3CG1DST_OZ_R14] = */ RT_OFFSETOF(BS3REGCTX, r14),
734 /* [BS3CG1DST_OZ_R15] = */ RT_OFFSETOF(BS3REGCTX, r15),
735
736 /* [BS3CG1DST_CR0] = */ RT_OFFSETOF(BS3REGCTX, cr0),
737 /* [BS3CG1DST_CR4] = */ RT_OFFSETOF(BS3REGCTX, cr4),
738 /* [BS3CG1DST_XCR0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, fXcr0Saved),
739
740 /* [BS3CG1DST_FCW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FCW),
741 /* [BS3CG1DST_FSW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FSW),
742 /* [BS3CG1DST_FTW] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FTW),
743 /* [BS3CG1DST_FOP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FOP),
744 /* [BS3CG1DST_FPUIP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUIP),
745 /* [BS3CG1DST_FPUCS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.CS),
746 /* [BS3CG1DST_FPUDP] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FPUDP),
747 /* [BS3CG1DST_FPUDS] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.DS),
748 /* [BS3CG1DST_MXCSR] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.MXCSR),
749 /* [BS3CG1DST_ST0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
750 /* [BS3CG1DST_ST1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
751 /* [BS3CG1DST_ST2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
752 /* [BS3CG1DST_ST3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
753 /* [BS3CG1DST_ST4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
754 /* [BS3CG1DST_ST5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
755 /* [BS3CG1DST_ST6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
756 /* [BS3CG1DST_ST7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
757 /* [BS3CG1DST_MM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
758 /* [BS3CG1DST_MM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
759 /* [BS3CG1DST_MM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
760 /* [BS3CG1DST_MM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
761 /* [BS3CG1DST_MM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
762 /* [BS3CG1DST_MM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
763 /* [BS3CG1DST_MM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
764 /* [BS3CG1DST_MM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
765 /* [BS3CG1DST_MM0_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[0]),
766 /* [BS3CG1DST_MM1_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[1]),
767 /* [BS3CG1DST_MM2_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[2]),
768 /* [BS3CG1DST_MM3_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[3]),
769 /* [BS3CG1DST_MM4_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[4]),
770 /* [BS3CG1DST_MM5_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[5]),
771 /* [BS3CG1DST_MM6_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[6]),
772 /* [BS3CG1DST_MM7_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aRegs[7]),
773
774 /* [BS3CG1DST_XMM0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
775 /* [BS3CG1DST_XMM1] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
776 /* [BS3CG1DST_XMM2] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
777 /* [BS3CG1DST_XMM3] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
778 /* [BS3CG1DST_XMM4] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
779 /* [BS3CG1DST_XMM5] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
780 /* [BS3CG1DST_XMM6] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
781 /* [BS3CG1DST_XMM7] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
782 /* [BS3CG1DST_XMM8] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
783 /* [BS3CG1DST_XMM9] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
784 /* [BS3CG1DST_XMM10] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
785 /* [BS3CG1DST_XMM11] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
786 /* [BS3CG1DST_XMM12] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
787 /* [BS3CG1DST_XMM13] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
788 /* [BS3CG1DST_XMM14] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
789 /* [BS3CG1DST_XMM15] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
790 /* [BS3CG1DST_XMM0_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
791 /* [BS3CG1DST_XMM1_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
792 /* [BS3CG1DST_XMM2_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
793 /* [BS3CG1DST_XMM3_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
794 /* [BS3CG1DST_XMM4_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
795 /* [BS3CG1DST_XMM5_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
796 /* [BS3CG1DST_XMM6_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
797 /* [BS3CG1DST_XMM7_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
798 /* [BS3CG1DST_XMM8_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
799 /* [BS3CG1DST_XMM9_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
800 /* [BS3CG1DST_XMM10_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
801 /* [BS3CG1DST_XMM11_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
802 /* [BS3CG1DST_XMM12_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
803 /* [BS3CG1DST_XMM13_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
804 /* [BS3CG1DST_XMM14_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
805 /* [BS3CG1DST_XMM15_LO] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
806 /* [BS3CG1DST_XMM0_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]) + sizeof(uint64_t),
807 /* [BS3CG1DST_XMM1_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]) + sizeof(uint64_t),
808 /* [BS3CG1DST_XMM2_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]) + sizeof(uint64_t),
809 /* [BS3CG1DST_XMM3_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]) + sizeof(uint64_t),
810 /* [BS3CG1DST_XMM4_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]) + sizeof(uint64_t),
811 /* [BS3CG1DST_XMM5_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]) + sizeof(uint64_t),
812 /* [BS3CG1DST_XMM6_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]) + sizeof(uint64_t),
813 /* [BS3CG1DST_XMM7_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]) + sizeof(uint64_t),
814 /* [BS3CG1DST_XMM8_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]) + sizeof(uint64_t),
815 /* [BS3CG1DST_XMM9_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]) + sizeof(uint64_t),
816 /* [BS3CG1DST_XMM10_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]) + sizeof(uint64_t),
817 /* [BS3CG1DST_XMM11_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]) + sizeof(uint64_t),
818 /* [BS3CG1DST_XMM12_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]) + sizeof(uint64_t),
819 /* [BS3CG1DST_XMM13_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]) + sizeof(uint64_t),
820 /* [BS3CG1DST_XMM14_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]) + sizeof(uint64_t),
821 /* [BS3CG1DST_XMM15_HI] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]) + sizeof(uint64_t),
822 /* [BS3CG1DST_XMM0_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
823 /* [BS3CG1DST_XMM1_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
824 /* [BS3CG1DST_XMM2_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
825 /* [BS3CG1DST_XMM3_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
826 /* [BS3CG1DST_XMM4_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
827 /* [BS3CG1DST_XMM5_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
828 /* [BS3CG1DST_XMM6_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
829 /* [BS3CG1DST_XMM7_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
830 /* [BS3CG1DST_XMM8_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
831 /* [BS3CG1DST_XMM9_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
832 /* [BS3CG1DST_XMM10_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
833 /* [BS3CG1DST_XMM11_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
834 /* [BS3CG1DST_XMM12_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
835 /* [BS3CG1DST_XMM13_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
836 /* [BS3CG1DST_XMM14_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
837 /* [BS3CG1DST_XMM15_LO_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
838 /* [BS3CG1DST_XMM0_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
839 /* [BS3CG1DST_XMM1_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
840 /* [BS3CG1DST_XMM2_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
841 /* [BS3CG1DST_XMM3_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
842 /* [BS3CG1DST_XMM4_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
843 /* [BS3CG1DST_XMM5_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
844 /* [BS3CG1DST_XMM6_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
845 /* [BS3CG1DST_XMM7_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
846 /* [BS3CG1DST_XMM8_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
847 /* [BS3CG1DST_XMM9_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
848 /* [BS3CG1DST_XMM10_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
849 /* [BS3CG1DST_XMM11_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
850 /* [BS3CG1DST_XMM12_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
851 /* [BS3CG1DST_XMM13_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
852 /* [BS3CG1DST_XMM14_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
853 /* [BS3CG1DST_XMM15_DW0] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
854 /* [BS3CG1DST_XMM0_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0]),
855 /* [BS3CG1DST_XMM1_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1]),
856 /* [BS3CG1DST_XMM2_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2]),
857 /* [BS3CG1DST_XMM3_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3]),
858 /* [BS3CG1DST_XMM4_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4]),
859 /* [BS3CG1DST_XMM5_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5]),
860 /* [BS3CG1DST_XMM6_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6]),
861 /* [BS3CG1DST_XMM7_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7]),
862 /* [BS3CG1DST_XMM8_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8]),
863 /* [BS3CG1DST_XMM9_DW0_ZX] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9]),
864 /* [BS3CG1DST_XMM10_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10]),
865 /* [BS3CG1DST_XMM11_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11]),
866 /* [BS3CG1DST_XMM12_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12]),
867 /* [BS3CG1DST_XMM13_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13]),
868 /* [BS3CG1DST_XMM14_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14]),
869 /* [BS3CG1DST_XMM15_DW0_ZX] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15]),
870 /* [BS3CG1DST_XMM0_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[0].au32[1]),
871 /* [BS3CG1DST_XMM1_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[1].au32[1]),
872 /* [BS3CG1DST_XMM2_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[2].au32[1]),
873 /* [BS3CG1DST_XMM3_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[3].au32[1]),
874 /* [BS3CG1DST_XMM4_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[4].au32[1]),
875 /* [BS3CG1DST_XMM5_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[5].au32[1]),
876 /* [BS3CG1DST_XMM6_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[6].au32[1]),
877 /* [BS3CG1DST_XMM7_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[7].au32[1]),
878 /* [BS3CG1DST_XMM8_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[8].au32[1]),
879 /* [BS3CG1DST_XMM9_HI96] = */ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[9].au32[1]),
880 /* [BS3CG1DST_XMM10_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[10].au32[1]),
881 /* [BS3CG1DST_XMM11_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[11].au32[1]),
882 /* [BS3CG1DST_XMM12_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[12].au32[1]),
883 /* [BS3CG1DST_XMM13_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[13].au32[1]),
884 /* [BS3CG1DST_XMM14_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[14].au32[1]),
885 /* [BS3CG1DST_XMM15_HI96] =*/ sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.aXMM[15].au32[1]),
886
887 /* [BS3CG1DST_YMM0] = */ ~0U,
888 /* [BS3CG1DST_YMM1] = */ ~0U,
889 /* [BS3CG1DST_YMM2] = */ ~0U,
890 /* [BS3CG1DST_YMM3] = */ ~0U,
891 /* [BS3CG1DST_YMM4] = */ ~0U,
892 /* [BS3CG1DST_YMM5] = */ ~0U,
893 /* [BS3CG1DST_YMM6] = */ ~0U,
894 /* [BS3CG1DST_YMM7] = */ ~0U,
895 /* [BS3CG1DST_YMM8] = */ ~0U,
896 /* [BS3CG1DST_YMM9] = */ ~0U,
897 /* [BS3CG1DST_YMM10] = */ ~0U,
898 /* [BS3CG1DST_YMM11] = */ ~0U,
899 /* [BS3CG1DST_YMM12] = */ ~0U,
900 /* [BS3CG1DST_YMM13] = */ ~0U,
901 /* [BS3CG1DST_YMM14] = */ ~0U,
902 /* [BS3CG1DST_YMM15] = */ ~0U,
903
904 /* [BS3CG1DST_VALUE_XCPT] = */ ~0U,
905};
906AssertCompile(RT_ELEMENTS(g_aoffBs3Cg1DstFields) == BS3CG1DST_END);
907
908/** Destination field names. */
909static const struct { char sz[12]; } g_aszBs3Cg1DstFields[] =
910{
911 { "INVALID" },
912 { "OP1" },
913 { "OP2" },
914 { "OP3" },
915 { "OP4" },
916 { "EFL" },
917 { "EFL_UND" },
918
919 { "AL" },
920 { "CL" },
921 { "DL" },
922 { "BL" },
923 { "AH" },
924 { "CH" },
925 { "DH" },
926 { "BH" },
927 { "SPL" },
928 { "BPL" },
929 { "SIL" },
930 { "DIL" },
931 { "R8L" },
932 { "R9L" },
933 { "R10L" },
934 { "R11L" },
935 { "R12L" },
936 { "R13L" },
937 { "R14L" },
938 { "R15L" },
939
940 { "AX" },
941 { "CX" },
942 { "DX" },
943 { "BX" },
944 { "SP" },
945 { "BP" },
946 { "SI" },
947 { "DI" },
948 { "R8W" },
949 { "R9W" },
950 { "R10W" },
951 { "R11W" },
952 { "R12W" },
953 { "R13W" },
954 { "R14W" },
955 { "R15W" },
956
957 { "EAX" },
958 { "ECX" },
959 { "EDX" },
960 { "EBX" },
961 { "ESP" },
962 { "EBP" },
963 { "ESI" },
964 { "EDI" },
965 { "R8D" },
966 { "R9D" },
967 { "R10D" },
968 { "R11D" },
969 { "R12D" },
970 { "R13D" },
971 { "R14D" },
972 { "R15D" },
973
974 { "RAX" },
975 { "RCX" },
976 { "RDX" },
977 { "RBX" },
978 { "RSP" },
979 { "RBP" },
980 { "RSI" },
981 { "RDI" },
982 { "R8" },
983 { "R9" },
984 { "R10" },
985 { "R11" },
986 { "R12" },
987 { "R13" },
988 { "R14" },
989 { "R15" },
990
991 { "OZ_RAX" },
992 { "OZ_RCX" },
993 { "OZ_RDX" },
994 { "OZ_RBX" },
995 { "OZ_RSP" },
996 { "OZ_RBP" },
997 { "OZ_RSI" },
998 { "OZ_RDI" },
999 { "OZ_R8" },
1000 { "OZ_R9" },
1001 { "OZ_R10" },
1002 { "OZ_R11" },
1003 { "OZ_R12" },
1004 { "OZ_R13" },
1005 { "OZ_R14" },
1006 { "OZ_R15" },
1007
1008 { "CR0" },
1009 { "CR4" },
1010 { "XCR0" },
1011
1012 { "FCW" },
1013 { "FSW" },
1014 { "FTW" },
1015 { "FOP" },
1016 { "FPUIP" },
1017 { "FPUCS" },
1018 { "FPUDP" },
1019 { "FPUDS" },
1020 { "MXCSR" },
1021 { "ST0" },
1022 { "ST1" },
1023 { "ST2" },
1024 { "ST3" },
1025 { "ST4" },
1026 { "ST5" },
1027 { "ST6" },
1028 { "ST7" },
1029 { "MM0" },
1030 { "MM1" },
1031 { "MM2" },
1032 { "MM3" },
1033 { "MM4" },
1034 { "MM5" },
1035 { "MM6" },
1036 { "MM7" },
1037 { "MM0_LO_ZX" },
1038 { "MM1_LO_ZX" },
1039 { "MM2_LO_ZX" },
1040 { "MM3_LO_ZX" },
1041 { "MM4_LO_ZX" },
1042 { "MM5_LO_ZX" },
1043 { "MM6_LO_ZX" },
1044 { "MM7_LO_ZX" },
1045 { "XMM0" },
1046 { "XMM1" },
1047 { "XMM2" },
1048 { "XMM3" },
1049 { "XMM4" },
1050 { "XMM5" },
1051 { "XMM6" },
1052 { "XMM7" },
1053 { "XMM8" },
1054 { "XMM9" },
1055 { "XMM10" },
1056 { "XMM11" },
1057 { "XMM12" },
1058 { "XMM13" },
1059 { "XMM14" },
1060 { "XMM15" },
1061 { "XMM0_LO" },
1062 { "XMM1_LO" },
1063 { "XMM2_LO" },
1064 { "XMM3_LO" },
1065 { "XMM4_LO" },
1066 { "XMM5_LO" },
1067 { "XMM6_LO" },
1068 { "XMM7_LO" },
1069 { "XMM8_LO" },
1070 { "XMM9_LO" },
1071 { "XMM10_LO" },
1072 { "XMM11_LO" },
1073 { "XMM12_LO" },
1074 { "XMM13_LO" },
1075 { "XMM14_LO" },
1076 { "XMM15_LO" },
1077 { "XMM0_HI" },
1078 { "XMM1_HI" },
1079 { "XMM2_HI" },
1080 { "XMM3_HI" },
1081 { "XMM4_HI" },
1082 { "XMM5_HI" },
1083 { "XMM6_HI" },
1084 { "XMM7_HI" },
1085 { "XMM8_HI" },
1086 { "XMM9_HI" },
1087 { "XMM10_HI" },
1088 { "XMM11_HI" },
1089 { "XMM12_HI" },
1090 { "XMM13_HI" },
1091 { "XMM14_HI" },
1092 { "XMM15_HI" },
1093 { "XMM0_LO_ZX" },
1094 { "XMM1_LO_ZX" },
1095 { "XMM2_LO_ZX" },
1096 { "XMM3_LO_ZX" },
1097 { "XMM4_LO_ZX" },
1098 { "XMM5_LO_ZX" },
1099 { "XMM6_LO_ZX" },
1100 { "XMM7_LO_ZX" },
1101 { "XMM8_LO_ZX" },
1102 { "XMM9_LO_ZX" },
1103 { "XMM10_LO_ZX" },
1104 { "XMM11_LO_ZX" },
1105 { "XMM12_LO_ZX" },
1106 { "XMM13_LO_ZX" },
1107 { "XMM14_LO_ZX" },
1108 { "XMM15_LO_ZX" },
1109 { "XMM0_DW0" },
1110 { "XMM1_DW0" },
1111 { "XMM2_DW0" },
1112 { "XMM3_DW0" },
1113 { "XMM4_DW0" },
1114 { "XMM5_DW0" },
1115 { "XMM6_DW0" },
1116 { "XMM7_DW0" },
1117 { "XMM8_DW0" },
1118 { "XMM9_DW0" },
1119 { "XMM10_DW0" },
1120 { "XMM11_DW0" },
1121 { "XMM12_DW0" },
1122 { "XMM13_DW0" },
1123 { "XMM14_DW0" },
1124 { "XMM15_DW0" },
1125 { "XMM0_DW0_ZX" },
1126 { "XMM1_DW0_ZX" },
1127 { "XMM2_DW0_ZX" },
1128 { "XMM3_DW0_ZX" },
1129 { "XMM4_DW0_ZX" },
1130 { "XMM5_DW0_ZX" },
1131 { "XMM6_DW0_ZX" },
1132 { "XMM7_DW0_ZX" },
1133 { "XMM8_DW0_ZX" },
1134 { "XMM9_DW0_ZX" },
1135 { "XMM10_DW0_ZX" },
1136 { "XMM11_DW0_ZX" },
1137 { "XMM12_DW0_ZX" },
1138 { "XMM13_DW0_ZX" },
1139 { "XMM14_DW0_ZX" },
1140 { "XMM15_DW0_ZX" },
1141 { "XMM0_HI96" },
1142 { "XMM1_HI96" },
1143 { "XMM2_HI96" },
1144 { "XMM3_HI96" },
1145 { "XMM4_HI96" },
1146 { "XMM5_HI96" },
1147 { "XMM6_HI96" },
1148 { "XMM7_HI96" },
1149 { "XMM8_HI96" },
1150 { "XMM9_HI96" },
1151 { "XMM10_HI96" },
1152 { "XMM11_HI96" },
1153 { "XMM12_HI96" },
1154 { "XMM13_HI96" },
1155 { "XMM14_HI96" },
1156 { "XMM15_HI96" },
1157 { "YMM0" },
1158 { "YMM1" },
1159 { "YMM2" },
1160 { "YMM3" },
1161 { "YMM4" },
1162 { "YMM5" },
1163 { "YMM6" },
1164 { "YMM7" },
1165 { "YMM8" },
1166 { "YMM9" },
1167 { "YMM10" },
1168 { "YMM11" },
1169 { "YMM12" },
1170 { "YMM13" },
1171 { "YMM14" },
1172 { "YMM15" },
1173
1174 { "VALXCPT" },
1175};
1176AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) >= BS3CG1DST_END);
1177AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) == BS3CG1DST_END);
1178
1179
1180#if 0
1181static const struct
1182{
1183 uint8_t cbPrefixes;
1184 uint8_t abPrefixes[14];
1185 uint16_t fEffective;
1186} g_aPrefixVariations[] =
1187{
1188 { 0, { 0x00 }, BS3CG1_PF_NONE },
1189
1190 { 1, { P_OZ }, BS3CG1_PF_OZ },
1191 { 1, { P_CS }, BS3CG1_PF_CS },
1192 { 1, { P_DS }, BS3CG1_PF_DS },
1193 { 1, { P_ES }, BS3CG1_PF_ES },
1194 { 1, { P_FS }, BS3CG1_PF_FS },
1195 { 1, { P_GS }, BS3CG1_PF_GS },
1196 { 1, { P_SS }, BS3CG1_PF_SS },
1197 { 1, { P_LK }, BS3CG1_PF_LK },
1198
1199 { 2, { P_CS, P_OZ, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
1200 { 2, { P_DS, P_OZ, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
1201 { 2, { P_ES, P_OZ, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
1202 { 2, { P_FS, P_OZ, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
1203 { 2, { P_GS, P_OZ, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
1204 { 2, { P_GS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1205 { 2, { P_SS, P_OZ, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1206
1207 { 2, { P_OZ, P_CS, }, BS3CG1_PF_CS | BS3CFG1_PF_OZ },
1208 { 2, { P_OZ, P_DS, }, BS3CG1_PF_DS | BS3CFG1_PF_OZ },
1209 { 2, { P_OZ, P_ES, }, BS3CG1_PF_ES | BS3CFG1_PF_OZ },
1210 { 2, { P_OZ, P_FS, }, BS3CG1_PF_FS | BS3CFG1_PF_OZ },
1211 { 2, { P_OZ, P_GS, }, BS3CG1_PF_GS | BS3CFG1_PF_OZ },
1212 { 2, { P_OZ, P_GS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1213 { 2, { P_OZ, P_SS, }, BS3CG1_PF_SS | BS3CFG1_PF_OZ },
1214};
1215
1216static const uint16_t g_afPfxKindToIgnoredFlags[BS3CG1PFXKIND_END] =
1217{
1218 /* [BS3CG1PFXKIND_INVALID] = */ UINT16_MAX,
1219 /* [BS3CG1PFXKIND_MODRM] = */ 0,
1220 /* [BS3CG1PFXKIND_MODRM_NO_OP_SIZES] = */ BS3CG1_PF_OZ | BS3CG1_PF_W,
1221};
1222
1223#endif
1224
1225
1226/**
1227 * Checks if >= 16 byte SSE alignment are exempted for the exception type.
1228 *
1229 * @returns true / false.
1230 * @param enmXcptType The type to check.
1231 */
1232static bool BS3_NEAR_CODE Bs3Cg1XcptTypeIsUnaligned(BS3CG1XCPTTYPE enmXcptType)
1233{
1234 switch (enmXcptType)
1235 {
1236 case BS3CG1XCPTTYPE_1:
1237 case BS3CG1XCPTTYPE_2:
1238 case BS3CG1XCPTTYPE_4:
1239 return false;
1240 case BS3CG1XCPTTYPE_NONE:
1241 case BS3CG1XCPTTYPE_3:
1242 case BS3CG1XCPTTYPE_4UA:
1243 case BS3CG1XCPTTYPE_5:
1244 return true;
1245 default:
1246 return false;
1247 }
1248}
1249
1250
1251/**
1252 * Checks if >= 16 byte AVX alignment are exempted for the exception type.
1253 *
1254 * @returns true / false.
1255 * @param enmXcptType The type to check.
1256 */
1257static bool BS3_NEAR_CODE Bs3Cg1XcptTypeIsVexUnaligned(BS3CG1XCPTTYPE enmXcptType)
1258{
1259 switch (enmXcptType)
1260 {
1261 case BS3CG1XCPTTYPE_1:
1262 return false;
1263
1264 case BS3CG1XCPTTYPE_NONE:
1265 case BS3CG1XCPTTYPE_2:
1266 case BS3CG1XCPTTYPE_3:
1267 case BS3CG1XCPTTYPE_4:
1268 case BS3CG1XCPTTYPE_4UA:
1269 case BS3CG1XCPTTYPE_5:
1270 case BS3CG1XCPTTYPE_6:
1271 case BS3CG1XCPTTYPE_11:
1272 case BS3CG1XCPTTYPE_12:
1273 return true;
1274
1275 default:
1276 return false;
1277 }
1278}
1279
1280
1281DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertReqPrefix(PBS3CG1STATE pThis, unsigned offDst)
1282{
1283 switch (pThis->enmPrefixKind)
1284 {
1285 case BS3CG1PFXKIND_REQ_66:
1286 pThis->abCurInstr[offDst] = 0x66;
1287 break;
1288 case BS3CG1PFXKIND_REQ_F2:
1289 pThis->abCurInstr[offDst] = 0xf2;
1290 break;
1291 case BS3CG1PFXKIND_REQ_F3:
1292 pThis->abCurInstr[offDst] = 0xf3;
1293 break;
1294 default:
1295 return offDst;
1296 }
1297 return offDst + 1;
1298}
1299
1300
1301DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertOpcodes(PBS3CG1STATE pThis, unsigned offDst)
1302{
1303 switch (pThis->cbOpcodes)
1304 {
1305 case 4: pThis->abCurInstr[offDst + 3] = pThis->abOpcodes[3];
1306 case 3: pThis->abCurInstr[offDst + 2] = pThis->abOpcodes[2];
1307 case 2: pThis->abCurInstr[offDst + 1] = pThis->abOpcodes[1];
1308 case 1: pThis->abCurInstr[offDst] = pThis->abOpcodes[0];
1309 return offDst + pThis->cbOpcodes;
1310
1311 default:
1312 BS3_ASSERT(0);
1313 return 0;
1314 }
1315}
1316
1317
1318/**
1319 * Inserts a ModR/M byte with mod=3 and set the two idxFields members.
1320 *
1321 * @returns off + 1.
1322 * @param pThis The state.
1323 * @param off Current instruction offset.
1324 * @param uReg Register index for ModR/M.reg.
1325 * @param uRegMem Register index for ModR/M.rm.
1326 */
1327static unsigned Bs3Cg1InsertModRmWithRegFields(PBS3CG1STATE pThis, unsigned off, uint8_t uReg, uint8_t uRegMem)
1328{
1329 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, uReg & 7, uRegMem & 7);
1330 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + uReg;
1331 pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + uRegMem;
1332 return off;
1333}
1334
1335
1336
1337/**
1338 * Cleans up state and context changes made by the encoder.
1339 *
1340 * @param pThis The state.
1341 */
1342static void BS3_NEAR_CODE Bs3Cg1EncodeCleanup(PBS3CG1STATE pThis)
1343{
1344 /* Restore the DS registers in the contexts. */
1345 unsigned iRing = 4;
1346 while (iRing-- > 0)
1347 pThis->aInitialCtxs[iRing].ds = pThis->aSavedSegRegs[iRing].ds;
1348
1349 switch (pThis->enmEncoding)
1350 {
1351 /* Most encodings currently doesn't need any special cleaning up. */
1352 default:
1353 return;
1354 }
1355}
1356
1357
1358static unsigned BS3_NEAR_CODE Bs3Cfg1EncodeMemMod0Disp(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
1359 uint8_t cbOp, uint8_t cbMisalign, BS3CG1OPLOC enmLocation)
1360{
1361 pThis->aOperands[pThis->iRmOp].idxField = BS3CG1DST_INVALID;
1362 pThis->aOperands[pThis->iRmOp].enmLocation = enmLocation;
1363 pThis->aOperands[pThis->iRmOp].cbOp = cbOp;
1364 pThis->aOperands[pThis->iRmOp].off = cbOp + cbMisalign;
1365
1366 if ( BS3_MODE_IS_16BIT_CODE(pThis->bMode)
1367 || (fAddrOverride && BS3_MODE_IS_32BIT_CODE(pThis->bMode)) )
1368 {
1369 /*
1370 * 16-bit code doing 16-bit or 32-bit addressing,
1371 * or 32-bit code doing 16-bit addressing.
1372 */
1373 unsigned iRing = 4;
1374 if (BS3_MODE_IS_RM_OR_V86(pThis->bMode))
1375 while (iRing-- > 0)
1376 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel;
1377 else
1378 while (iRing-- > 0)
1379 pThis->aInitialCtxs[iRing].ds = pThis->DataPgFar.sel | iRing;
1380 if (!fAddrOverride || BS3_MODE_IS_32BIT_CODE(pThis->bMode))
1381 {
1382 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 6 /*disp16*/);
1383 *(uint16_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMisalign;
1384 off += 2;
1385 }
1386 else
1387 {
1388 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1389 *(uint32_t *)&pThis->abCurInstr[off] = pThis->DataPgFar.off + X86_PAGE_SIZE - cbOp - cbMisalign;
1390 off += 4;
1391 }
1392 }
1393 else
1394 {
1395 /*
1396 * 32-bit code doing 32-bit addressing,
1397 * or 64-bit code doing either 64-bit or 32-bit addressing.
1398 */
1399 pThis->abCurInstr[off++] = X86_MODRM_MAKE(0, iReg, 5 /*disp32*/);
1400 *(uint32_t *)&pThis->abCurInstr[off] = BS3_FP_OFF(pThis->pbDataPg) + X86_PAGE_SIZE - cbOp - cbMisalign;
1401
1402#if ARCH_BITS == 64
1403 /* In 64-bit mode we always have a rip relative encoding regardless of fAddrOverride. */
1404 if (BS3CG1_IS_64BIT_TARGET(pThis))
1405 *(uint32_t *)&pThis->abCurInstr[off] -= BS3_FP_OFF(&pThis->pbCodePg[X86_PAGE_SIZE]);
1406#endif
1407 off += 4;
1408 }
1409
1410 /*
1411 * Fill the memory with 0xcc.
1412 */
1413 switch (cbOp + cbMisalign)
1414 {
1415 case 8: pThis->pbDataPg[X86_PAGE_SIZE - 8] = 0xcc; RT_FALL_THRU();
1416 case 7: pThis->pbDataPg[X86_PAGE_SIZE - 7] = 0xcc; RT_FALL_THRU();
1417 case 6: pThis->pbDataPg[X86_PAGE_SIZE - 6] = 0xcc; RT_FALL_THRU();
1418 case 5: pThis->pbDataPg[X86_PAGE_SIZE - 5] = 0xcc; RT_FALL_THRU();
1419 case 4: pThis->pbDataPg[X86_PAGE_SIZE - 4] = 0xcc; RT_FALL_THRU();
1420 case 3: pThis->pbDataPg[X86_PAGE_SIZE - 3] = 0xcc; RT_FALL_THRU();
1421 case 2: pThis->pbDataPg[X86_PAGE_SIZE - 2] = 0xcc; RT_FALL_THRU();
1422 case 1: pThis->pbDataPg[X86_PAGE_SIZE - 1] = 0xcc; RT_FALL_THRU();
1423 case 0: break;
1424 default:
1425 {
1426 BS3CG1_DPRINTF(("Bs3MemSet(%p,%#x,%#x)\n", &pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMisalign], 0xcc, cbOp - cbMisalign));
1427 Bs3MemSet(&pThis->pbDataPg[X86_PAGE_SIZE - cbOp - cbMisalign], 0xcc, cbOp - cbMisalign);
1428 break;
1429 }
1430 }
1431
1432 return off;
1433}
1434
1435
1436#if 0 /* unused */
1437/** Also encodes idxField of the register operand using idxFieldBase. */
1438static unsigned BS3_NEAR_CODE
1439Bs3Cfg1EncodeMemMod0DispWithRegField(PBS3CG1STATE pThis, bool fAddrOverride, unsigned off, uint8_t iReg,
1440 uint8_t cbOp, uint8_t cbMisalign, BS3CG1OPLOC enmLocation)
1441{
1442 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1443 return Bs3Cfg1EncodeMemMod0Disp(pThis, fAddrOverride, off, iReg & 7, cbOp, cbMisalign, enmLocation);
1444}
1445#endif
1446
1447/** Also encodes idxField of the register operand using idxFieldBase. */
1448static unsigned BS3_NEAR_CODE
1449Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(PBS3CG1STATE pThis, unsigned off, uint8_t iReg)
1450{
1451 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1452 return Bs3Cfg1EncodeMemMod0Disp(pThis, false /*fAddrOverride*/, off, iReg & 7,
1453 pThis->aOperands[pThis->iRmOp].cbOp,
1454 0 /*cbMisalign*/,
1455 pThis->aOperands[pThis->iRmOp].enmLocation);
1456}
1457
1458/** Also encodes idxField of the register operand using idxFieldBase. */
1459static unsigned BS3_NEAR_CODE
1460Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsAddrOverride(PBS3CG1STATE pThis, unsigned off, uint8_t iReg)
1461{
1462 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1463 return Bs3Cfg1EncodeMemMod0Disp(pThis, true /*fAddrOverride*/, off, iReg & 7,
1464 pThis->aOperands[pThis->iRmOp].cbOp,
1465 0 /*cbMisalign*/,
1466 pThis->aOperands[pThis->iRmOp].enmLocation);
1467}
1468
1469
1470/** Also encodes idxField of the register operand using idxFieldBase. */
1471static unsigned BS3_NEAR_CODE
1472Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(PBS3CG1STATE pThis, unsigned off, uint8_t iReg, uint8_t cbMisalign)
1473{
1474 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1475 return Bs3Cfg1EncodeMemMod0Disp(pThis, false /*fAddrOverride*/, off, iReg & 7,
1476 pThis->aOperands[pThis->iRmOp].cbOp,
1477 cbMisalign,
1478 pThis->aOperands[pThis->iRmOp].enmLocation);
1479}
1480
1481
1482/** Also encodes idxField of the register operand using idxFieldBase. */
1483static unsigned BS3_NEAR_CODE
1484Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaults(PBS3CG1STATE pThis, unsigned off, uint8_t iReg, uint8_t cbOp)
1485{
1486 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1487 return Bs3Cfg1EncodeMemMod0Disp(pThis, false /*fAddrOverride*/, off, iReg & 7, cbOp, 0 /*cbMisalign*/,
1488 pThis->aOperands[pThis->iRmOp].enmLocation);
1489}
1490
1491/** Also encodes idxField of the register operand using idxFieldBase. */
1492static unsigned BS3_NEAR_CODE
1493Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaultsAddrOverride(PBS3CG1STATE pThis, unsigned off, uint8_t iReg, uint8_t cbOp)
1494{
1495 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + iReg;
1496 return Bs3Cfg1EncodeMemMod0Disp(pThis, true /*fAddrOverride*/, off, iReg & 7, cbOp, 0 /*cbMisalign*/,
1497 pThis->aOperands[pThis->iRmOp].enmLocation);
1498}
1499
1500
1501/** The modrm.reg value is taken from the instruction byte at @a off. */
1502static unsigned BS3_NEAR_CODE
1503Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(PBS3CG1STATE pThis, unsigned off)
1504{
1505 return Bs3Cfg1EncodeMemMod0Disp(pThis, false /*fAddrOverride*/, off,
1506 (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
1507 pThis->aOperands[pThis->iRmOp].cbOp,
1508 0 /*cbMisalign*/,
1509 pThis->aOperands[pThis->iRmOp].enmLocation);
1510}
1511
1512
1513
1514static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Eb_Gb_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
1515{
1516 unsigned off;
1517 switch (iEncoding)
1518 {
1519 /* Start by reg,reg encoding. */
1520 case 0:
1521 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1522 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1523 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, X86_GREG_xAX, X86_GREG_xCX);
1524 break;
1525 case 1:
1526 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1527 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1528 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5 /*CH*/);
1529 break;
1530 case 2:
1531 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) < BS3CPU_80386)
1532 return 0;
1533 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1534 pThis->abCurInstr[0] = P_OZ;
1535 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1536 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 6 /*DH*/);
1537 break;
1538 /* Tests with address overrides go last! */
1539 case 3:
1540 pThis->abCurInstr[0] = P_AZ;
1541 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1542 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsAddrOverride(pThis, off, 7 /*BH*/);
1543 break;
1544
1545 default:
1546 return 0;
1547 }
1548 pThis->cbCurInstr = off;
1549 return iEncoding + 1;
1550}
1551
1552
1553static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Gv_Ev__OR__MODRM_Ev_Gv(PBS3CG1STATE pThis, unsigned iEncoding)
1554{
1555 unsigned off;
1556 unsigned cbOp;
1557 switch (iEncoding)
1558 {
1559 case 0:
1560 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1561 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1562 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, X86_GREG_xBX, X86_GREG_xDX);
1563 cbOp = pThis->cbOpDefault;
1564 break;
1565 case 1:
1566 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1567 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1568 cbOp = pThis->cbOpDefault;
1569 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaults(pThis, off, X86_GREG_xBP, cbOp);
1570 break;
1571 case 2:
1572 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) < BS3CPU_80386)
1573 return 0;
1574 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1575 pThis->abCurInstr[0] = P_OZ;
1576 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1577 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, X86_GREG_xAX, X86_GREG_xCX);
1578 cbOp = pThis->cbOpOvrd66;
1579 break;
1580 case 3:
1581 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1582 pThis->abCurInstr[0] = P_OZ;
1583 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1584 cbOp = pThis->cbOpOvrd66;
1585 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaults(pThis, off, X86_GREG_xSI, cbOp);
1586 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
1587 break;
1588 case 4:
1589 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1590 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1591 pThis->abCurInstr[off++] = REX_W___;
1592 off = Bs3Cg1InsertOpcodes(pThis, off);
1593 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, X86_GREG_xBX, X86_GREG_xDX);
1594 cbOp = pThis->cbOpOvrdRexW;
1595 break;
1596 case 5:
1597 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1598 pThis->abCurInstr[off++] = REX__RB_;
1599 off = Bs3Cg1InsertOpcodes(pThis, off);
1600 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, X86_GREG_x14, X86_GREG_x12);
1601 cbOp = pThis->cbOpDefault;
1602 break;
1603 /* Tests with address overrides go last!*/
1604 case 6:
1605 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1606 pThis->abCurInstr[0] = P_AZ;
1607 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
1608 cbOp = pThis->cbOpDefault;
1609 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaultsAddrOverride(pThis, off, X86_GREG_xDI, cbOp);
1610 break;
1611 case 7:
1612 pThis->abCurInstr[0] = P_OZ;
1613 pThis->abCurInstr[1] = P_AZ;
1614 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
1615 cbOp = pThis->cbOpOvrd66;
1616 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaultsAddrOverride(pThis, off, X86_GREG_xDI, cbOp);
1617 break;
1618 default:
1619 return 0;
1620 }
1621 pThis->aOperands[0].cbOp = cbOp;
1622 pThis->aOperands[1].cbOp = cbOp;
1623 pThis->cbOperand = cbOp;
1624 pThis->cbCurInstr = off;
1625 return iEncoding + 1;
1626}
1627
1628
1629static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Qq(PBS3CG1STATE pThis, unsigned iEncoding)
1630{
1631 unsigned off;
1632 switch (iEncoding)
1633 {
1634 case 0:
1635 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1636 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1637 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1638 break;
1639 case 1:
1640 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1641 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1642 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 7);
1643 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1644 break;
1645#if ARCH_BITS == 64
1646 case 2:
1647 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1648 pThis->abCurInstr[off++] = REX__RBX;
1649 off = Bs3Cg1InsertOpcodes(pThis, off);
1650 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6 /*no +8*/, 2 /*no +8*/);
1651 break;
1652#endif
1653 case 3:
1654 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1655 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1656 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
1657 break;
1658 case 4:
1659 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1660 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
1661 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1662 break;
1663#if ARCH_BITS == 64
1664 case 5:
1665 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1666 pThis->abCurInstr[off++] = REX__RBX;
1667 off = Bs3Cg1InsertOpcodes(pThis, off);
1668 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 /*iReg - no +8*/);
1669 break;
1670#endif
1671
1672 default:
1673 return 0;
1674 }
1675
1676 pThis->cbCurInstr = off;
1677 return iEncoding + 1;
1678}
1679
1680
1681static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Uq(PBS3CG1STATE pThis, unsigned iEncoding)
1682{
1683 unsigned off;
1684 switch (iEncoding)
1685 {
1686 case 0:
1687 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1688 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1689 break;
1690 case 1:
1691 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1692 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
1693 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1694 break;
1695 case 2:
1696 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1697 pThis->abCurInstr[off++] = REX__RBX;
1698 off = Bs3Cg1InsertOpcodes(pThis, off);
1699 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6 /*no+8*/, 2 + 8);
1700 break;
1701 default:
1702 return 0;
1703 }
1704 pThis->cbCurInstr = off;
1705 return iEncoding + 1;
1706}
1707
1708
1709static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
1710{
1711 unsigned off;
1712 switch (iEncoding)
1713 {
1714 case 0:
1715 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1716 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1717 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1718 break;
1719 case 1:
1720 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1721 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
1722 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1723 break;
1724#if ARCH_BITS == 64
1725 case 2:
1726 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1727 pThis->abCurInstr[off++] = REX__RBX;
1728 off = Bs3Cg1InsertOpcodes(pThis, off);
1729 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6 /*no +8*/, 2+8);
1730 break;
1731#endif
1732 case 3:
1733 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1734 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1735 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
1736 break;
1737 case 4:
1738 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1739 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
1740 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1741 break;
1742#if ARCH_BITS == 64
1743 case 5:
1744 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1745 pThis->abCurInstr[off++] = REX__RBX;
1746 off = Bs3Cg1InsertOpcodes(pThis, off);
1747 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 /*iReg*/);
1748 break;
1749#endif
1750
1751 default:
1752 return 0;
1753 }
1754 pThis->cbCurInstr = off;
1755 return iEncoding + 1;
1756}
1757
1758
1759static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
1760{
1761#if ARCH_BITS == 64
1762 if (BS3CG1_IS_64BIT_TARGET(pThis))
1763 {
1764 unsigned off;
1765 switch (iEncoding)
1766 {
1767 case 0:
1768 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1769 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1770 pThis->abCurInstr[off++] = REX_W___;
1771 off = Bs3Cg1InsertOpcodes(pThis, off);
1772 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1773 break;
1774 case 1:
1775 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1776 pThis->abCurInstr[off++] = REX_W___;
1777 off = Bs3Cg1InsertOpcodes(pThis, off);
1778 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
1779 break;
1780 case 2:
1781 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1782 pThis->abCurInstr[off++] = REX_WRBX;
1783 off = Bs3Cg1InsertOpcodes(pThis, off);
1784 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6 /*no +8*/, 2+8);
1785 break;
1786 case 3:
1787 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1788 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1789 pThis->abCurInstr[off++] = REX_W___;
1790 off = Bs3Cg1InsertOpcodes(pThis, off);
1791 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
1792 break;
1793 case 4:
1794 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1795 pThis->abCurInstr[off++] = REX_W___;
1796 off = Bs3Cg1InsertOpcodes(pThis, off);
1797 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
1798 break;
1799 case 5:
1800 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1801 pThis->abCurInstr[off++] = REX_WRBX;
1802 off = Bs3Cg1InsertOpcodes(pThis, off);
1803 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 /*iReg*/);
1804 break;
1805
1806 default:
1807 return 0;
1808 }
1809 pThis->cbCurInstr = off;
1810 return iEncoding + 1;
1811 }
1812#endif
1813 return 0;
1814}
1815
1816
1817/* Differs from Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ in that REX.R isn't ignored. */
1818static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
1819{
1820 unsigned off;
1821 switch (iEncoding)
1822 {
1823 case 0:
1824 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1825 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1826 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1827 break;
1828 case 1:
1829 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1830 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
1831 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1832 break;
1833#if ARCH_BITS == 64
1834 case 2:
1835 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1836 pThis->abCurInstr[off++] = REX__RBX;
1837 off = Bs3Cg1InsertOpcodes(pThis, off);
1838 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6+8, 2+8);
1839 break;
1840#endif
1841 case 3:
1842 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1843 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1844 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
1845 break;
1846 case 4:
1847 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1848 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
1849 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1850 break;
1851#if ARCH_BITS == 64
1852 case 5:
1853 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1854 pThis->abCurInstr[off++] = REX__RBX;
1855 off = Bs3Cg1InsertOpcodes(pThis, off);
1856 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7+8 /*iReg*/);
1857 break;
1858#endif
1859
1860 default:
1861 return 0;
1862 }
1863 pThis->cbCurInstr = off;
1864 return iEncoding + 1;
1865}
1866
1867
1868/* Differs from Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ in that REX.R isn't ignored. */
1869static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
1870{
1871#if ARCH_BITS == 64
1872 if (BS3CG1_IS_64BIT_TARGET(pThis))
1873 {
1874 unsigned off;
1875 switch (iEncoding)
1876 {
1877 case 0:
1878 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1879 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1880 pThis->abCurInstr[off++] = REX_W___;
1881 off = Bs3Cg1InsertOpcodes(pThis, off);
1882 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1883 break;
1884 case 1:
1885 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1886 pThis->abCurInstr[off++] = REX_W___;
1887 off = Bs3Cg1InsertOpcodes(pThis, off);
1888 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
1889 break;
1890 case 2:
1891 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1892 pThis->abCurInstr[off++] = REX_WRBX;
1893 off = Bs3Cg1InsertOpcodes(pThis, off);
1894 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6+8, 2+8);
1895 break;
1896 case 4:
1897 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1898 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1899 pThis->abCurInstr[off++] = REX_W___;
1900 off = Bs3Cg1InsertOpcodes(pThis, off);
1901 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
1902 break;
1903 case 5:
1904 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1905 pThis->abCurInstr[off++] = REX_W___;
1906 off = Bs3Cg1InsertOpcodes(pThis, off);
1907 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
1908 break;
1909 case 6:
1910 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1911 pThis->abCurInstr[off++] = REX_WRBX;
1912 off = Bs3Cg1InsertOpcodes(pThis, off);
1913 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7+8 /*iReg*/);
1914 break;
1915
1916 default:
1917 return 0;
1918 }
1919 pThis->cbCurInstr = off;
1920 return iEncoding + 1;
1921 }
1922#endif
1923 return 0;
1924}
1925
1926
1927static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vsomething_Usomething_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
1928{
1929 unsigned off;
1930 switch (iEncoding)
1931 {
1932 case 0:
1933 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1934 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1935 break;
1936 case 1:
1937 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1938 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 2, 2);
1939 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1940 break;
1941 case 2:
1942 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1943 pThis->abCurInstr[off++] = REX__RBX;
1944 off = Bs3Cg1InsertOpcodes(pThis, off);
1945 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 3+8, 7+8);
1946 break;
1947 default:
1948 return 0;
1949 }
1950 pThis->cbCurInstr = off;
1951 return iEncoding + 1;
1952}
1953
1954
1955static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
1956{
1957 unsigned off;
1958 switch (iEncoding)
1959 {
1960 case 0:
1961 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
1962 off = Bs3Cg1InsertModRmWithRegFields(pThis, Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)), 1, 0);
1963 break;
1964 case 1:
1965 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
1966 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1967 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2 /*iReg*/);
1968 break;
1969 case 2:
1970 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1971 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 3 /*iReg*/, 1 /*cbMisalign*/);
1972 if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
1973 pThis->bAlignmentXcpt = X86_XCPT_GP;
1974 break;
1975 default:
1976 return 0;
1977 }
1978 pThis->cbCurInstr = off;
1979 return iEncoding + 1;
1980}
1981
1982
1983static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Vsomething_Nsomething(PBS3CG1STATE pThis, unsigned iEncoding)
1984{
1985 unsigned off;
1986 switch (iEncoding)
1987 {
1988 case 0:
1989 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1990 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
1991 break;
1992 case 1:
1993 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
1994 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 7);
1995 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
1996 break;
1997 case 2:
1998 off = Bs3Cg1InsertReqPrefix(pThis, 0);
1999 pThis->abCurInstr[off++] = REX_WRBX;
2000 off = Bs3Cg1InsertOpcodes(pThis, off);
2001 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6 + 8, 7 /*no +8*/);
2002 break;
2003
2004 default:
2005 return 0;
2006 }
2007 pThis->cbCurInstr = off;
2008 return iEncoding + 1;
2009}
2010
2011
2012static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Gv_RO_Ma(PBS3CG1STATE pThis, unsigned iEncoding) /* bound instr */
2013{
2014 unsigned off;
2015 unsigned cbOp = BS3_MODE_IS_16BIT_CODE(pThis->bMode) ? 2 : 4;
2016 switch (iEncoding)
2017 {
2018 case 0:
2019 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2020 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaults(pThis, off, X86_GREG_xBP, cbOp * 2);
2021 break;
2022 case 1:
2023 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) < BS3CPU_80386)
2024 return 0;
2025 cbOp = cbOp == 2 ? 4 : 2;
2026 pThis->abCurInstr[0] = P_OZ;
2027 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
2028 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaults(pThis, off, X86_GREG_xBP, cbOp * 2);
2029 break;
2030 case 2:
2031 pThis->abCurInstr[0] = P_AZ;
2032 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
2033 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaultsAddrOverride(pThis, off, X86_GREG_xBP, cbOp * 2);
2034 break;
2035 case 3:
2036 cbOp = cbOp == 2 ? 4 : 2;
2037 pThis->abCurInstr[0] = P_AZ;
2038 pThis->abCurInstr[1] = P_OZ;
2039 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 2));
2040 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndSizeAndDefaultsAddrOverride(pThis, off, X86_GREG_xBP, cbOp * 2);
2041 break;
2042 default:
2043 return 0;
2044 }
2045 pThis->aOperands[pThis->iRegOp].cbOp = cbOp;
2046 pThis->cbOperand = cbOp;
2047 pThis->cbCurInstr = off;
2048 return iEncoding + 1;
2049}
2050
2051
2052static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Msomething(PBS3CG1STATE pThis, unsigned iEncoding)
2053{
2054 unsigned off;
2055 switch (iEncoding)
2056 {
2057 case 0:
2058 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)) - 1;
2059 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
2060 break;
2061 default:
2062 return 0;
2063 }
2064 pThis->cbCurInstr = off;
2065 return iEncoding + 1;
2066}
2067
2068
2069static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Msomething_Psomething(PBS3CG1STATE pThis, unsigned iEncoding)
2070{
2071 unsigned off;
2072 switch (iEncoding)
2073 {
2074 case 0:
2075 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2076 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
2077 break;
2078 case 1:
2079 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2080 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 7 /*iReg*/, 1 /*cbMisalign*/);
2081 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2082 break;
2083#if ARCH_BITS == 64
2084 case 2:
2085 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2086 pThis->abCurInstr[off++] = REX__RBX;
2087 off = Bs3Cg1InsertOpcodes(pThis, off);
2088 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 /*iReg - no +8*/);
2089 break;
2090#endif
2091
2092 default:
2093 return 0;
2094 }
2095
2096 pThis->cbCurInstr = off;
2097 return iEncoding + 1;
2098}
2099
2100
2101static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2102{
2103 unsigned off;
2104 switch (iEncoding)
2105 {
2106 case 0:
2107 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2108 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2 /*iReg*/);
2109 break;
2110 case 1:
2111 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2112 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 2 /*iReg*/, 1 /*cbMisalign*/ );
2113 if (!Bs3Cg1XcptTypeIsUnaligned(pThis->enmXcptType))
2114 pThis->bAlignmentXcpt = X86_XCPT_GP;
2115 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2116 break;
2117 case 2:
2118 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2119 pThis->abCurInstr[off++] = REX__R__;
2120 off = Bs3Cg1InsertOpcodes(pThis, off);
2121 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2+8 /*iReg*/);
2122 break;
2123 default:
2124 return 0;
2125 }
2126 pThis->cbCurInstr = off;
2127 return iEncoding + 1;
2128}
2129
2130
2131static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED(PBS3CG1STATE pThis, unsigned iEncoding)
2132{
2133 unsigned off;
2134 switch (iEncoding)
2135 {
2136 case 0:
2137 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2138 pThis->cbCurInstr = off;
2139 break;
2140 default:
2141 return 0;
2142 }
2143 return iEncoding + 1;
2144}
2145
2146
2147static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED_AL_Ib(PBS3CG1STATE pThis, unsigned iEncoding)
2148{
2149 unsigned off;
2150 switch (iEncoding)
2151 {
2152 case 0:
2153 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2154 pThis->aOperands[1].off = (uint8_t)off;
2155 pThis->abCurInstr[off++] = 0xff;
2156 pThis->cbCurInstr = off;
2157 break;
2158 default:
2159 return 0;
2160 }
2161 return iEncoding + 1;
2162}
2163
2164
2165static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_FIXED_rAX_Iz(PBS3CG1STATE pThis, unsigned iEncoding)
2166{
2167 unsigned off;
2168 unsigned cbOp;
2169 switch (iEncoding)
2170 {
2171 case 0:
2172 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0));
2173 pThis->aOperands[1].off = (uint8_t)off;
2174 cbOp = pThis->cbOpDefault;
2175 if (cbOp == 2)
2176 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
2177 else
2178 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
2179 off += cbOp;
2180 pThis->aOperands[0].cbOp = cbOp;
2181 pThis->aOperands[1].cbOp = cbOp;
2182 pThis->cbOperand = cbOp;
2183 break;
2184 case 1:
2185 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) < BS3CPU_80386)
2186 return 0;
2187 pThis->abCurInstr[0] = P_OZ;
2188 off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 1));
2189 pThis->aOperands[1].off = (uint8_t)off;
2190 cbOp = pThis->cbOpOvrd66;
2191 if (cbOp == 2)
2192 *(uint16_t *)&pThis->abCurInstr[off] = UINT16_MAX;
2193 else
2194 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
2195 off += cbOp;
2196 pThis->aOperands[0].cbOp = cbOp;
2197 pThis->aOperands[1].cbOp = cbOp;
2198 pThis->cbOperand = cbOp;
2199 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2200 break;
2201 case 2:
2202 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2203 pThis->abCurInstr[off++] = REX_W___;
2204 off = Bs3Cg1InsertOpcodes(pThis, off);
2205 pThis->aOperands[1].off = (uint8_t)off;
2206 *(uint32_t *)&pThis->abCurInstr[off] = UINT32_MAX;
2207 off += 4;
2208 pThis->aOperands[0].cbOp = 8;
2209 pThis->aOperands[1].cbOp = 4;
2210 pThis->cbOperand = 8;
2211 break;
2212 default:
2213 return 0;
2214
2215 /* IMAGE PADDING - workaround for "rd err" - remove later! */
2216 case 4:
2217 ASMHalt();
2218 ASMHalt();
2219 ASMHalt();
2220 return 0;
2221
2222 }
2223 pThis->cbCurInstr = off;
2224 return iEncoding + 1;
2225}
2226
2227
2228static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_MOD_EQ_3(PBS3CG1STATE pThis, unsigned iEncoding)
2229{
2230 unsigned off;
2231 if (iEncoding < 8)
2232 {
2233 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2234 off = Bs3Cg1InsertOpcodes(pThis, off);
2235 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding, 1);
2236 }
2237 else if (iEncoding < 16)
2238 {
2239 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2240 off = Bs3Cg1InsertOpcodes(pThis, off);
2241 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
2242 }
2243 else
2244 return 0;
2245 pThis->cbCurInstr = off;
2246
2247 return iEncoding + 1;
2248}
2249
2250
2251static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_MODRM_MOD_NE_3(PBS3CG1STATE pThis, unsigned iEncoding)
2252{
2253 unsigned off;
2254 if (iEncoding < 3)
2255 {
2256 off = Bs3Cg1InsertReqPrefix(pThis, 0);
2257 off = Bs3Cg1InsertOpcodes(pThis, off);
2258 pThis->abCurInstr[off++] = X86_MODRM_MAKE(iEncoding, 0, 1);
2259 if (iEncoding >= 1)
2260 pThis->abCurInstr[off++] = 0x7f;
2261 if (iEncoding == 2)
2262 {
2263 pThis->abCurInstr[off++] = 0x5f;
2264 if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
2265 {
2266 pThis->abCurInstr[off++] = 0x3f;
2267 pThis->abCurInstr[off++] = 0x1f;
2268 }
2269 }
2270 }
2271 else
2272 return 0;
2273 pThis->cbCurInstr = off;
2274 return iEncoding + 1;
2275}
2276
2277
2278/*
2279 *
2280 * VEX
2281 * VEX
2282 * VEX
2283 *
2284 */
2285#ifdef BS3CG1_WITH_VEX
2286
2287/**
2288 * Inserts a 3-byte VEX prefix.
2289 *
2290 * @returns New offDst value.
2291 * @param pThis The state.
2292 * @param offDst The current instruction offset.
2293 * @param uVexL The VEX.L value.
2294 * @param uVexV The VEX.V value (caller inverted it already).
2295 * @param uVexR The VEX.R value (caller inverted it already).
2296 * @param uVexX The VEX.X value (caller inverted it already).
2297 * @param uVexB The VEX.B value (caller inverted it already).
2298 * @param uVexW The VEX.W value (straight).
2299 */
2300DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex3bPrefix(PBS3CG1STATE pThis, unsigned offDst, uint8_t uVexV, uint8_t uVexL,
2301 uint8_t uVexR, uint8_t uVexX, uint8_t uVexB, uint8_t uVexW)
2302{
2303 uint8_t b1;
2304 uint8_t b2;
2305 b1 = uVexR << 7;
2306 b1 |= uVexX << 6;
2307 b1 |= uVexB << 5;
2308 b1 |= pThis->uOpcodeMap;
2309 b2 = uVexV << 3;
2310 b2 |= uVexW << 7;
2311 b2 |= uVexL << 2;
2312 switch (pThis->enmPrefixKind)
2313 {
2314 case BS3CG1PFXKIND_NO_F2_F3_66: b2 |= 0; break;
2315 case BS3CG1PFXKIND_REQ_66: b2 |= 1; break;
2316 case BS3CG1PFXKIND_REQ_F3: b2 |= 2; break;
2317 case BS3CG1PFXKIND_REQ_F2: b2 |= 3; break;
2318 default:
2319 Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n", pThis->enmPrefixKind);
2320 break;
2321 }
2322
2323 pThis->abCurInstr[offDst] = 0xc4; /* vex3 */
2324 pThis->abCurInstr[offDst + 1] = b1;
2325 pThis->abCurInstr[offDst + 2] = b2;
2326 pThis->uVexL = uVexL;
2327 return offDst + 3;
2328}
2329
2330
2331/**
2332 * Inserts a 2-byte VEX prefix.
2333 *
2334 * @note Will switch to 3-byte VEX prefix if uOpcodeMap isn't one.
2335 *
2336 * @returns New offDst value.
2337 * @param pThis The state.
2338 * @param offDst The current instruction offset.
2339 * @param uVexL The VEX.L value.
2340 * @param uVexV The VEX.V value (caller inverted it already).
2341 * @param uVexR The VEX.R value (caller inverted it already).
2342 */
2343DECLINLINE(unsigned) BS3_NEAR_CODE Bs3Cg1InsertVex2bPrefix(PBS3CG1STATE pThis, unsigned offDst,
2344 uint8_t uVexV, uint8_t uVexL, uint8_t uVexR)
2345{
2346 if (pThis->uOpcodeMap == 1)
2347 {
2348 uint8_t b = uVexR << 7;
2349 b |= uVexV << 3;
2350 b |= uVexL << 2;
2351 switch (pThis->enmPrefixKind)
2352 {
2353 case BS3CG1PFXKIND_NO_F2_F3_66: b |= 0; break;
2354 case BS3CG1PFXKIND_REQ_66: b |= 1; break;
2355 case BS3CG1PFXKIND_REQ_F3: b |= 2; break;
2356 case BS3CG1PFXKIND_REQ_F2: b |= 3; break;
2357 default:
2358 Bs3TestFailedF("enmPrefixKind=%d not supported for VEX!\n");
2359 break;
2360 }
2361
2362 pThis->abCurInstr[offDst] = 0xc5; /* vex2 */
2363 pThis->abCurInstr[offDst + 1] = b;
2364 pThis->uVexL = uVexL;
2365 return offDst + 2;
2366 }
2367 return Bs3Cg1InsertVex3bPrefix(pThis, offDst, uVexV, uVexL, uVexR, 1 /*uVexX*/, 1 /*uVexB*/, 0/*uVexW*/);
2368}
2369
2370
2371/**
2372 * Inserts a ModR/M byte with mod=3 and set the two idxFields members.
2373 *
2374 * @returns off + 1.
2375 * @param pThis The state.
2376 * @param off Current instruction offset.
2377 * @param uReg Register index for ModR/M.reg.
2378 * @param uRegMem Register index for ModR/M.rm.
2379 * @param uVexVvvv The VEX.vvvv register.
2380 */
2381static unsigned Bs3Cg1InsertModRmWithRegFieldsAndVvvv(PBS3CG1STATE pThis, unsigned off,
2382 uint8_t uReg, uint8_t uRegMem, uint8_t uVexVvvv)
2383{
2384 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, uReg & 7, uRegMem & 7);
2385 pThis->aOperands[pThis->iRegOp].idxField = pThis->aOperands[pThis->iRegOp].idxFieldBase + uReg;
2386 pThis->aOperands[1 ].idxField = pThis->aOperands[1 ].idxFieldBase + uVexVvvv;
2387 pThis->aOperands[pThis->iRmOp ].idxField = pThis->aOperands[pThis->iRmOp ].idxFieldBase + uRegMem;
2388 return off;
2389}
2390
2391
2392static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ(PBS3CG1STATE pThis, unsigned iEncoding)
2393{
2394 unsigned off;
2395 switch (iEncoding)
2396 {
2397 case 0:
2398 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
2399 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2400 off = Bs3Cg1InsertOpcodes(pThis, off);
2401 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
2402 break;
2403 case 1:
2404 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2405 off = Bs3Cg1InsertOpcodes(pThis, off);
2406 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2407 break;
2408 case 2:
2409 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2410 off = Bs3Cg1InsertOpcodes(pThis, off);
2411 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2412 pThis->fInvalidEncoding = true;
2413 break;
2414 case 3:
2415 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xe /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2416 off = Bs3Cg1InsertOpcodes(pThis, off);
2417 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2418 pThis->fInvalidEncoding = true;
2419 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2420 break;
2421#if ARCH_BITS == 64
2422 case 4:
2423 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 0 /*W*/);
2424 off = Bs3Cg1InsertOpcodes(pThis, off);
2425 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6+8, 2+8);
2426 break;
2427#endif
2428 case 5:
2429 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
2430 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2431 off = Bs3Cg1InsertOpcodes(pThis, off);
2432 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
2433 break;
2434 case 6:
2435 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2436 off = Bs3Cg1InsertOpcodes(pThis, off);
2437 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
2438 break;
2439 case 7:
2440 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2441 off = Bs3Cg1InsertOpcodes(pThis, off);
2442 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 4 /*iReg*/, 1 /*cbMisalign*/);
2443 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
2444 break;
2445#if ARCH_BITS == 64
2446 case 8:
2447 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2448 off = Bs3Cg1InsertOpcodes(pThis, off);
2449 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4+8 /*iReg*/);
2450 break;
2451 case 9:
2452 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/);
2453 off = Bs3Cg1InsertOpcodes(pThis, off);
2454 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8 /*iReg*/);
2455 iEncoding += 2;
2456 break;
2457#endif
2458 case 10: /* VEX.W is ignored in 32-bit mode. flag? */
2459 BS3_ASSERT(!BS3CG1_IS_64BIT_TARGET(pThis));
2460 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2461 off = Bs3Cg1InsertOpcodes(pThis, off);
2462 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
2463 break;
2464
2465 default:
2466 return 0;
2467 }
2468 pThis->cbCurInstr = off;
2469 return iEncoding + 1;
2470}
2471
2472
2473/* Differs from Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ in that REX.R isn't ignored. */
2474static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ(PBS3CG1STATE pThis, unsigned iEncoding)
2475{
2476#if ARCH_BITS == 64
2477 if (BS3CG1_IS_64BIT_TARGET(pThis))
2478 {
2479 unsigned off;
2480 switch (iEncoding)
2481 {
2482 case 0:
2483 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
2484 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2485 off = Bs3Cg1InsertOpcodes(pThis, off);
2486 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2487 break;
2488 case 1:
2489 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2490 off = Bs3Cg1InsertOpcodes(pThis, off);
2491 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2492 pThis->fInvalidEncoding = true;
2493 break;
2494 case 2:
2495 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xe /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2496 off = Bs3Cg1InsertOpcodes(pThis, off);
2497 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6, 2);
2498 pThis->fInvalidEncoding = true;
2499 break;
2500 case 3:
2501 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 1 /*W*/);
2502 off = Bs3Cg1InsertOpcodes(pThis, off);
2503 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 6+8, 2+8);
2504 break;
2505 case 4:
2506 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
2507 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2508 off = Bs3Cg1InsertOpcodes(pThis, off);
2509 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4 /*iReg*/);
2510 break;
2511 case 5:
2512 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2513 off = Bs3Cg1InsertOpcodes(pThis, off);
2514 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 4 /*iReg*/, 1 /*cbMisalign*/);
2515 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
2516 break;
2517 case 6:
2518 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
2519 off = Bs3Cg1InsertOpcodes(pThis, off);
2520 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 4+8 /*iReg*/);
2521 break;
2522
2523 default:
2524 return 0;
2525 }
2526 pThis->cbCurInstr = off;
2527 return iEncoding + 1;
2528 }
2529#endif
2530 return 0;
2531}
2532
2533
2534/**
2535 * Wip - VEX.W ignored.
2536 * Lig - VEX.L ignored.
2537 */
2538static unsigned BS3_NEAR_CODE
2539Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2540{
2541 unsigned off;
2542 switch (iEncoding)
2543 {
2544 case 0:
2545 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2546 off = Bs3Cg1InsertOpcodes(pThis, off);
2547 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2548 break;
2549 case 1:
2550 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x8 /*~V*/, 1 /*L-ignored*/, 1 /*~R*/);
2551 off = Bs3Cg1InsertOpcodes(pThis, off);
2552 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 3, 1, 7);
2553 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2554 break;
2555 case 2:
2556#if ARCH_BITS == 64
2557 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 0 /*~R*/);
2558 off = Bs3Cg1InsertOpcodes(pThis, off);
2559 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 3+8, 2, 15);
2560 break;
2561#endif
2562 case 3:
2563 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2564 off = Bs3Cg1InsertOpcodes(pThis, off);
2565 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2566 break;
2567 case 4:
2568 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2569 off = Bs3Cg1InsertOpcodes(pThis, off);
2570 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2571 break;
2572 case 5:
2573 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2574 off = Bs3Cg1InsertOpcodes(pThis, off);
2575 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 3);
2576 break;
2577 case 6:
2578 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2579 off = Bs3Cg1InsertOpcodes(pThis, off);
2580 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
2581 break;
2582 case 7:
2583 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2584 off = Bs3Cg1InsertOpcodes(pThis, off);
2585 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
2586 break;
2587 default:
2588 return 0;
2589 }
2590 pThis->cbCurInstr = off;
2591 return iEncoding + 1;
2592}
2593
2594
2595/**
2596 * Wip - VEX.W ignored.
2597 */
2598static unsigned BS3_NEAR_CODE
2599Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_HdqCsomething_Usomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2600{
2601 unsigned off;
2602 switch (iEncoding)
2603 {
2604 case 0:
2605 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2606 off = Bs3Cg1InsertOpcodes(pThis, off);
2607 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2608 break;
2609 case 1:
2610 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x8 /*~V*/, 1 /*L-ignored*/, 1 /*~R*/);
2611 off = Bs3Cg1InsertOpcodes(pThis, off);
2612 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 3, 1, 7);
2613 pThis->fInvalidEncoding = true;
2614 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2615 break;
2616 case 2:
2617#if ARCH_BITS == 64
2618 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 0 /*~R*/);
2619 off = Bs3Cg1InsertOpcodes(pThis, off);
2620 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 3+8, 2, 15);
2621 break;
2622#endif
2623 case 3:
2624 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2625 off = Bs3Cg1InsertOpcodes(pThis, off);
2626 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2627 break;
2628 case 4:
2629 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2630 off = Bs3Cg1InsertOpcodes(pThis, off);
2631 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 0);
2632 pThis->fInvalidEncoding = true;
2633 break;
2634 case 5:
2635 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2636 off = Bs3Cg1InsertOpcodes(pThis, off);
2637 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, 3);
2638 break;
2639 case 6:
2640 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2641 off = Bs3Cg1InsertOpcodes(pThis, off);
2642 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
2643 break;
2644 case 7:
2645 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2646 off = Bs3Cg1InsertOpcodes(pThis, off);
2647 off = Bs3Cg1InsertModRmWithRegFieldsAndVvvv(pThis, off, 2, 1, BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
2648 break;
2649 default:
2650 return 0;
2651 }
2652 pThis->cbCurInstr = off;
2653 return iEncoding + 1;
2654}
2655
2656
2657/**
2658 * Wip - VEX.W ignored.
2659 */
2660static unsigned BS3_NEAR_CODE
2661Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2662{
2663 unsigned off;
2664 switch (iEncoding)
2665 {
2666 case 20: /* Switch to 256-bit operands. */
2667 pThis->aOperands[pThis->iRegOp].idxFieldBase = BS3CG1DST_YMM0;
2668 pThis->aOperands[pThis->iRegOp].cbOp = 32;
2669 pThis->aOperands[pThis->iRmOp ].cbOp = 32;
2670 RT_FALL_THRU();
2671 case 0:
2672 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
2673 off = Bs3Cg1InsertOpcodes(pThis, off);
2674 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2675 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2676 break;
2677#if ARCH_BITS == 64
2678 case 1:
2679 case 21:
2680 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/);
2681 off = Bs3Cg1InsertOpcodes(pThis, off);
2682 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 + 8);
2683 break;
2684#endif
2685 case 2:
2686 case 22:
2687 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
2688 off = Bs3Cg1InsertOpcodes(pThis, off);
2689 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2690 pThis->fInvalidEncoding = true;
2691 break;
2692 case 3:
2693 case 23:
2694 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2695 off = Bs3Cg1InsertOpcodes(pThis, off);
2696 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2697 break;
2698 case 4:
2699 case 24:
2700 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2701 off = Bs3Cg1InsertOpcodes(pThis, off);
2702 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2703 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
2704 break;
2705#if ARCH_BITS == 64
2706 case 5:
2707 case 25:
2708 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2709 off = Bs3Cg1InsertOpcodes(pThis, off);
2710 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8);
2711 break;
2712 case 6:
2713 case 26:
2714 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
2715 off = Bs3Cg1InsertOpcodes(pThis, off);
2716 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2717 break;
2718 case 7:
2719 case 27:
2720 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
2721 off = Bs3Cg1InsertOpcodes(pThis, off);
2722 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2723 break;
2724#endif
2725 case 8:
2726 case 28:
2727 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2728 off = Bs3Cg1InsertOpcodes(pThis, off);
2729 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2730 pThis->fInvalidEncoding = true;
2731 break;
2732 case 9:
2733 case 29:
2734 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2735 off = Bs3Cg1InsertOpcodes(pThis, off);
2736 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2737 pThis->fInvalidEncoding = true;
2738 iEncoding += 10;
2739 break;
2740
2741 default:
2742 return 0;
2743 }
2744 pThis->cbCurInstr = off;
2745 return iEncoding + 1;
2746}
2747
2748
2749
2750/**
2751 * Wip - VEX.W ignored.
2752 * Lig - VEX.L ignored.
2753 */
2754static unsigned BS3_NEAR_CODE
2755Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2756{
2757 unsigned off;
2758 switch (iEncoding)
2759 {
2760 case 0:
2761 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2762 off = Bs3Cg1InsertOpcodes(pThis, off);
2763 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2764 break;
2765 case 1:
2766 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 1 /*~R*/);
2767 off = Bs3Cg1InsertOpcodes(pThis, off);
2768 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7);
2769 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2770 break;
2771#if ARCH_BITS == 64
2772 case 2:
2773 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - ignored*/, 0 /*~R*/);
2774 off = Bs3Cg1InsertOpcodes(pThis, off);
2775 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 + 8);
2776 break;
2777#endif
2778 case 3:
2779 iEncoding = 3;
2780 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
2781 off = Bs3Cg1InsertOpcodes(pThis, off);
2782 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2783 pThis->fInvalidEncoding = true;
2784 break;
2785 case 4:
2786 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2787 off = Bs3Cg1InsertOpcodes(pThis, off);
2788 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2789 break;
2790 case 5:
2791 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2792 off = Bs3Cg1InsertOpcodes(pThis, off);
2793 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2794 break;
2795 case 6:
2796 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2797 off = Bs3Cg1InsertOpcodes(pThis, off);
2798 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2799 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
2800 break;
2801#if ARCH_BITS == 64
2802 case 7:
2803 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2804 off = Bs3Cg1InsertOpcodes(pThis, off);
2805 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8);
2806 break;
2807 case 8:
2808 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
2809 off = Bs3Cg1InsertOpcodes(pThis, off);
2810 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2811 break;
2812 case 9:
2813 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
2814 off = Bs3Cg1InsertOpcodes(pThis, off);
2815 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2816 break;
2817#endif
2818 case 10:
2819 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2820 off = Bs3Cg1InsertOpcodes(pThis, off);
2821 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2822 pThis->fInvalidEncoding = true;
2823 break;
2824 case 11:
2825 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2826 off = Bs3Cg1InsertOpcodes(pThis, off);
2827 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2828 pThis->fInvalidEncoding = true;
2829 break;
2830 default:
2831 return 0;
2832 }
2833 pThis->cbCurInstr = off;
2834 return iEncoding + 1;
2835}
2836
2837
2838/**
2839 * Wip - VEX.W ignored.
2840 * L0 - VEX.L must be zero.
2841 */
2842static unsigned BS3_NEAR_CODE
2843Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lmbz_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
2844{
2845 unsigned off;
2846 switch (iEncoding)
2847 {
2848 case 0:
2849 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
2850 off = Bs3Cg1InsertOpcodes(pThis, off);
2851 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2852 break;
2853 case 1:
2854 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 1 /*~R*/);
2855 off = Bs3Cg1InsertOpcodes(pThis, off);
2856 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7);
2857 pThis->fInvalidEncoding = true;
2858 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 : 0;
2859 break;
2860#if ARCH_BITS == 64
2861 case 2:
2862 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/);
2863 off = Bs3Cg1InsertOpcodes(pThis, off);
2864 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 + 8);
2865 break;
2866 case 3:
2867 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 0 /*~R*/);
2868 off = Bs3Cg1InsertOpcodes(pThis, off);
2869 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5 + 8);
2870 pThis->fInvalidEncoding = true;
2871 break;
2872#endif
2873 case 4:
2874 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
2875 off = Bs3Cg1InsertOpcodes(pThis, off);
2876 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2877 pThis->fInvalidEncoding = true;
2878 break;
2879 case 5:
2880 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2881 off = Bs3Cg1InsertOpcodes(pThis, off);
2882 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2883 break;
2884 case 6:
2885 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L - invalid*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2886 off = Bs3Cg1InsertOpcodes(pThis, off);
2887 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2888 pThis->fInvalidEncoding = true;
2889 break;
2890 case 7:
2891 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2892 off = Bs3Cg1InsertOpcodes(pThis, off);
2893 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2894 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
2895 break;
2896#if ARCH_BITS == 64
2897 case 8:
2898 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2899 off = Bs3Cg1InsertOpcodes(pThis, off);
2900 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8);
2901 break;
2902 case 9:
2903 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
2904 off = Bs3Cg1InsertOpcodes(pThis, off);
2905 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2906 break;
2907 case 10:
2908 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
2909 off = Bs3Cg1InsertOpcodes(pThis, off);
2910 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2911 break;
2912#endif
2913 case 11:
2914 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2915 off = Bs3Cg1InsertOpcodes(pThis, off);
2916 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2917 pThis->fInvalidEncoding = true;
2918 break;
2919 case 12:
2920 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2921 off = Bs3Cg1InsertOpcodes(pThis, off);
2922 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2923 pThis->fInvalidEncoding = true;
2924 break;
2925 default:
2926 return 0;
2927 }
2928 pThis->cbCurInstr = off;
2929 return iEncoding + 1;
2930}
2931
2932
2933/**
2934 * Wip - VEX.W ignored.
2935 */
2936static unsigned BS3_NEAR_CODE
2937Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lxx_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding, uint8_t uVexL)
2938{
2939 unsigned off;
2940 switch (iEncoding)
2941 {
2942 case 0:
2943 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 1 /*~R*/);
2944 off = Bs3Cg1InsertOpcodes(pThis, off);
2945 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2946 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
2947 break;
2948#if ARCH_BITS == 64
2949 case 1:
2950 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 0 /*~R*/);
2951 off = Bs3Cg1InsertOpcodes(pThis, off);
2952 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 + 8);
2953 break;
2954#endif
2955 case 2:
2956 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, uVexL, 1 /*~R*/);
2957 off = Bs3Cg1InsertOpcodes(pThis, off);
2958 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
2959 pThis->fInvalidEncoding = true;
2960 break;
2961 case 3:
2962 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2963 off = Bs3Cg1InsertOpcodes(pThis, off);
2964 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2965 break;
2966 case 4:
2967 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
2968 off = Bs3Cg1InsertOpcodes(pThis, off);
2969 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2970 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
2971 break;
2972#if ARCH_BITS == 64
2973 case 5:
2974 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2975 off = Bs3Cg1InsertOpcodes(pThis, off);
2976 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8);
2977 break;
2978 case 6:
2979 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
2980 off = Bs3Cg1InsertOpcodes(pThis, off);
2981 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
2982 break;
2983 case 7:
2984 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, uVexL, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
2985 off = Bs3Cg1InsertOpcodes(pThis, off);
2986 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2987 break;
2988#endif
2989 case 8:
2990 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, uVexL, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2991 off = Bs3Cg1InsertOpcodes(pThis, off);
2992 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
2993 pThis->fInvalidEncoding = true;
2994 break;
2995 case 9:
2996 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 7 /*~V*/, uVexL, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
2997 off = Bs3Cg1InsertOpcodes(pThis, off);
2998 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
2999 pThis->fInvalidEncoding = true;
3000 break;
3001 default:
3002 return 0;
3003 }
3004 pThis->cbCurInstr = off;
3005 return iEncoding + 1;
3006}
3007
3008
3009/**
3010 * Wip - VEX.W ignored.
3011 * L0 - VEX.L is zero (encoding may exist where it isn't).
3012 */
3013static unsigned BS3_NEAR_CODE
3014Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L0_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
3015{
3016 return Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lxx_OR_ViceVersa(pThis, iEncoding, 0 /*uVexL*/);
3017}
3018
3019
3020/**
3021 * Wip - VEX.W ignored.
3022 * L1 - VEX.L is one (encoding may exist where it isn't).
3023 */
3024static unsigned BS3_NEAR_CODE
3025Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L1_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
3026{
3027 return Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lxx_OR_ViceVersa(pThis, iEncoding, 1 /*uVexL*/);
3028}
3029
3030
3031
3032/**
3033 * Wip - VEX.W ignored.
3034 */
3035static unsigned BS3_NEAR_CODE
3036Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Msomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
3037{
3038 unsigned off;
3039 switch (iEncoding)
3040 {
3041 case 0:
3042 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xc /*~V*/, 0 /*L*/, 1 /*~R*/);
3043 off = Bs3Cg1InsertOpcodes(pThis, off);
3044 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
3045 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 3;
3046 break;
3047 case 1:
3048 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
3049 off = Bs3Cg1InsertOpcodes(pThis, off);
3050 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7);
3051 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3052 pThis->fInvalidEncoding = true;
3053 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
3054 break;
3055#if ARCH_BITS == 64
3056 case 2:
3057 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0x1 /*~V*/, 0 /*L*/, 0 /*~R*/);
3058 off = Bs3Cg1InsertOpcodes(pThis, off);
3059 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 7 + 8);
3060 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 14;
3061 break;
3062#endif
3063 case 3:
3064 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/);
3065 off = Bs3Cg1InsertOpcodes(pThis, off);
3066 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 0);
3067 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 1;
3068 break;
3069 case 4:
3070 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3071 off = Bs3Cg1InsertOpcodes(pThis, off);
3072 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
3073 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3074 break;
3075 case 5:
3076 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L-ignored*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3077 off = Bs3Cg1InsertOpcodes(pThis, off);
3078 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
3079 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3080 pThis->fInvalidEncoding = true;
3081 break;
3082 case 6:
3083 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W-ignored*/);
3084 off = Bs3Cg1InsertOpcodes(pThis, off);
3085 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
3086 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3087 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 3 : 0;
3088 break;
3089#if ARCH_BITS == 64
3090 case 7:
3091 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 0 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3092 off = Bs3Cg1InsertOpcodes(pThis, off);
3093 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5+8);
3094 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3095 break;
3096 case 8:
3097 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 0 /*~B-ignored*/, 0 /*W*/);
3098 off = Bs3Cg1InsertOpcodes(pThis, off);
3099 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 1);
3100 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3101 break;
3102 case 9:
3103 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 0 /*~X-ignored*/, 1 /*~B*/, 0 /*W*/);
3104 off = Bs3Cg1InsertOpcodes(pThis, off);
3105 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2);
3106 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + 0;
3107 break;
3108#endif
3109 case 10:
3110 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3111 off = Bs3Cg1InsertOpcodes(pThis, off);
3112 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 5);
3113 pThis->aOperands[1].idxField = pThis->aOperands[1].idxFieldBase + (BS3CG1_IS_64BIT_TARGET(pThis) ? 15 : 7);
3114 pThis->fInvalidEncoding = true;
3115 break;
3116 default:
3117 return 0;
3118 }
3119 pThis->cbCurInstr = off;
3120 return iEncoding + 1;
3121}
3122
3123
3124static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_Md_WO(PBS3CG1STATE pThis, unsigned iEncoding)
3125{
3126 unsigned off;
3127 switch (iEncoding)
3128 {
3129 case 0:
3130 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3131 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3132 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3133 break;
3134 case 1:
3135 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3136 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3137 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3138 break;
3139 case 2:
3140 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0x7 /*~V-invalid*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3141 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3142 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3143 pThis->fInvalidEncoding = true;
3144 break;
3145 case 3:
3146 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3147 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3148 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3149 pThis->fInvalidEncoding = true;
3150 break;
3151 case 4:
3152 pThis->abCurInstr[0] = P_OZ;
3153 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3154 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3155 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3156 pThis->fInvalidEncoding = true;
3157 break;
3158 case 5:
3159 pThis->abCurInstr[0] = P_RZ;
3160 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3161 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3162 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3163 pThis->fInvalidEncoding = true;
3164 break;
3165 case 6:
3166 pThis->abCurInstr[0] = P_RN;
3167 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3168 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3169 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3170 pThis->fInvalidEncoding = true;
3171 break;
3172 case 7:
3173 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W*/);
3174 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3175 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3176 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 1 : 0;
3177 break;
3178#if ARCH_BITS == 64
3179 case 8:
3180 pThis->abCurInstr[0] = REX_____;
3181 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3182 off = Bs3Cg1InsertOpcodes(pThis, off) - 1;
3183 off = Bs3Cfg1EncodeMemMod0DispWithDefaultsAndNoReg(pThis, off);
3184 pThis->fInvalidEncoding = true;
3185 break;
3186#endif
3187 default:
3188 return 0;
3189 }
3190
3191 pThis->cbCurInstr = off;
3192 return iEncoding + 1;
3193}
3194
3195
3196/**
3197 * Wip = VEX.W ignored.
3198 * Lmbz = VEX.L must be zero.
3199 */
3200static unsigned BS3_NEAR_CODE
3201Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_Lmbz_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
3202{
3203 unsigned off;
3204 switch (iEncoding)
3205 {
3206 /* 128-bit wide stuff goes first, then we'll update the operand widths afterwards. */
3207 case 0:
3208 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
3209 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3210 off = Bs3Cg1InsertOpcodes(pThis, off);
3211 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
3212 break;
3213
3214 case 1:
3215 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3216 off = Bs3Cg1InsertOpcodes(pThis, off);
3217 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3218 break;
3219 case 2:
3220 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
3221 off = Bs3Cg1InsertOpcodes(pThis, off);
3222 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 5, 4);
3223 break;
3224 case 3:
3225 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
3226 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3227 off = Bs3Cg1InsertOpcodes(pThis, off);
3228 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2 /*iReg*/);
3229 break;
3230 case 4:
3231 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3232 off = Bs3Cg1InsertOpcodes(pThis, off);
3233 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 3 /*iReg*/);
3234 break;
3235 case 5:
3236 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
3237 off = Bs3Cg1InsertOpcodes(pThis, off);
3238 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 3 /*iReg*/);
3239 break;
3240 case 6:
3241 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3242 off = Bs3Cg1InsertOpcodes(pThis, off);
3243 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 3 /*iReg*/, 1 /*cbMisalign*/);
3244 if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
3245 pThis->bAlignmentXcpt = X86_XCPT_GP;
3246 break;
3247 case 7:
3248 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3249 off = Bs3Cg1InsertOpcodes(pThis, off);
3250 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 3 /*iReg*/, 1 /*cbMisalign*/);
3251 if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
3252 pThis->bAlignmentXcpt = X86_XCPT_GP;
3253 break;
3254 /* 128-bit invalid encodings: */
3255 case 8:
3256 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
3257 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, 0 /*L*/, 1 /*~R*/); /* Bad V value */
3258 off = Bs3Cg1InsertOpcodes(pThis, off);
3259 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
3260 pThis->fInvalidEncoding = true;
3261 break;
3262 case 9:
3263 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3264 off = Bs3Cg1InsertOpcodes(pThis, off);
3265 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3266 pThis->fInvalidEncoding = true;
3267 iEncoding = 20-1;
3268 break;
3269
3270 default:
3271 return 0;
3272 }
3273
3274 pThis->cbCurInstr = off;
3275 return iEncoding + 1;
3276}
3277
3278
3279/**
3280 * Wip = VEX.W ignored.
3281 */
3282static unsigned BS3_NEAR_CODE
3283Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa(PBS3CG1STATE pThis, unsigned iEncoding)
3284{
3285 unsigned off;
3286
3287 switch (iEncoding)
3288 {
3289 case 20: /* switch to 256-bit */
3290 pThis->aOperands[pThis->iRmOp ].cbOp = 32;
3291 pThis->aOperands[pThis->iRmOp ].idxFieldBase = BS3CG1DST_YMM0;
3292 pThis->aOperands[pThis->iRegOp].cbOp = 32;
3293 pThis->aOperands[pThis->iRegOp].idxFieldBase = BS3CG1DST_YMM0;
3294 RT_FALL_THRU();
3295 case 0:
3296 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
3297 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
3298 off = Bs3Cg1InsertOpcodes(pThis, off);
3299 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
3300 break;
3301
3302 case 1:
3303 case 21:
3304 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3305 off = Bs3Cg1InsertOpcodes(pThis, off);
3306 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3307 break;
3308 case 2:
3309 case 22:
3310 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored*/);
3311 off = Bs3Cg1InsertOpcodes(pThis, off);
3312 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 5, 4);
3313 break;
3314 case 3:
3315 case 23:
3316 pThis->aOperands[pThis->iRmOp].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationMem;
3317 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
3318 off = Bs3Cg1InsertOpcodes(pThis, off);
3319 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 2 /*iReg*/);
3320 break;
3321 case 4:
3322 case 24:
3323 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3324 off = Bs3Cg1InsertOpcodes(pThis, off);
3325 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 3 /*iReg*/);
3326 break;
3327 case 5:
3328 case 25:
3329 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 1 /*W - ignored */);
3330 off = Bs3Cg1InsertOpcodes(pThis, off);
3331 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaults(pThis, off, 3 /*iReg*/);
3332 break;
3333 case 6:
3334 case 26:
3335 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/);
3336 off = Bs3Cg1InsertOpcodes(pThis, off);
3337 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 3 /*iReg*/, 1 /*cbMisalign*/);
3338 if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
3339 pThis->bAlignmentXcpt = X86_XCPT_GP;
3340 break;
3341 case 7:
3342 case 27:
3343 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3344 off = Bs3Cg1InsertOpcodes(pThis, off);
3345 off = Bs3Cfg1EncodeMemMod0DispWithRegFieldAndDefaultsMisaligned(pThis, off, 3 /*iReg*/, 1 /*cbMisalign*/);
3346 if (!Bs3Cg1XcptTypeIsVexUnaligned(pThis->enmXcptType))
3347 pThis->bAlignmentXcpt = X86_XCPT_GP;
3348 break;
3349 /* invalid encodings: */
3350 case 8:
3351 case 28:
3352 pThis->aOperands[pThis->iRmOp ].enmLocation = pThis->aOperands[pThis->iRmOp].enmLocationReg;
3353 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xe /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/); /* Bad V value */
3354 off = Bs3Cg1InsertOpcodes(pThis, off);
3355 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1, 0);
3356 pThis->fInvalidEncoding = true;
3357 break;
3358 case 9:
3359 case 29:
3360 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0 /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3361 off = Bs3Cg1InsertOpcodes(pThis, off);
3362 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3363 pThis->fInvalidEncoding = true;
3364 break;
3365
3366 case 10:
3367 case 30:
3368 pThis->abCurInstr[0] = P_RN;
3369 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3370 off = Bs3Cg1InsertOpcodes(pThis, off);
3371 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3372 pThis->fInvalidEncoding = true;
3373 break;
3374 case 11:
3375 case 31:
3376 pThis->abCurInstr[0] = P_RZ;
3377 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3378 off = Bs3Cg1InsertOpcodes(pThis, off);
3379 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3380 pThis->fInvalidEncoding = true;
3381 break;
3382 case 12:
3383 case 32:
3384 pThis->abCurInstr[0] = P_OZ;
3385 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3386 off = Bs3Cg1InsertOpcodes(pThis, off);
3387 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3388 pThis->fInvalidEncoding = true;
3389 break;
3390 case 13:
3391 case 33:
3392 pThis->abCurInstr[0] = P_LK;
3393 off = Bs3Cg1InsertVex3bPrefix(pThis, 1 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3394 off = Bs3Cg1InsertOpcodes(pThis, off);
3395 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 4, 5);
3396 pThis->fInvalidEncoding = true;
3397 iEncoding += !BS3CG1_IS_64BIT_TARGET(pThis) ? 2 + 4 : 0;
3398 break;
3399
3400#if ARCH_BITS == 64
3401 /* 64-bit mode registers */
3402 case 14:
3403 case 34:
3404 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/);
3405 off = Bs3Cg1InsertOpcodes(pThis, off);
3406 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 3+8, 4);
3407 break;
3408 case 15:
3409 case 35:
3410 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, iEncoding >= 20 /*L*/, 0 /*~R*/, 1 /*~X*/, 0 /*~B*/, 0 /*W*/);
3411 off = Bs3Cg1InsertOpcodes(pThis, off);
3412 off = Bs3Cg1InsertModRmWithRegFields(pThis, off, 1+8, 4+8);
3413 iEncoding += 4;
3414 break;
3415#endif
3416 default:
3417 return 0;
3418 }
3419
3420 pThis->cbCurInstr = off;
3421 return iEncoding + 1;
3422}
3423
3424
3425//static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_FIXED(PBS3CG1STATE pThis, unsigned iEncoding)
3426//{
3427// unsigned off;
3428// if (iEncoding == 0)
3429// off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3430// else if (iEncoding == 0)
3431// off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3432// else
3433// return 0;
3434// pThis->cbCurInstr = off;
3435// return iEncoding + 1;
3436//}
3437
3438
3439static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3(PBS3CG1STATE pThis, unsigned iEncoding)
3440{
3441 unsigned off;
3442 if (iEncoding < 8)
3443 {
3444 if (iEncoding & 1)
3445 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3446 else
3447 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3448 off = Bs3Cg1InsertOpcodes(pThis, off);
3449 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding, 1);
3450 }
3451 else if (iEncoding < 16)
3452 {
3453 if (iEncoding & 1)
3454 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/);
3455 else
3456 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 1 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3457 off = Bs3Cg1InsertOpcodes(pThis, off);
3458 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, iEncoding & 7, 1);
3459 }
3460 else if (iEncoding < 24)
3461 {
3462 if (iEncoding & 1)
3463 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/);
3464 else
3465 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, 0 /*L*/, 1 /*~R*/, 1 /*~X*/, 1 /*~B*/, 0 /*W*/);
3466 off = Bs3Cg1InsertOpcodes(pThis, off);
3467 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
3468 }
3469 else if (iEncoding < 32)
3470 {
3471 if (iEncoding & 1)
3472 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 3) != 0 /*L*/, 1 /*~R*/);
3473 else
3474 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/, 1 /*~X*/,
3475 1 /*~B*/, (iEncoding & 4) != 0 /*W*/);
3476 off = Bs3Cg1InsertOpcodes(pThis, off);
3477 pThis->abCurInstr[off++] = X86_MODRM_MAKE(3, 0, iEncoding & 7);
3478 }
3479 else
3480 return 0;
3481 pThis->cbCurInstr = off;
3482
3483 return iEncoding + 1;
3484}
3485
3486
3487static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3(PBS3CG1STATE pThis, unsigned iEncoding)
3488{
3489 unsigned off;
3490 if (iEncoding < 8)
3491 {
3492 unsigned iMod = iEncoding % 3;
3493 if (iEncoding & 1)
3494 off = Bs3Cg1InsertVex2bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/);
3495 else
3496 off = Bs3Cg1InsertVex3bPrefix(pThis, 0 /*offDst*/, 0xf /*~V*/, (iEncoding & 2) != 0 /*L*/, 1 /*~R*/,
3497 1 /*~X*/, 1 /*~B*/, (iEncoding & 4) != 0 /*W*/);
3498 off = Bs3Cg1InsertOpcodes(pThis, off);
3499 pThis->abCurInstr[off++] = X86_MODRM_MAKE(iMod, 0, 1);
3500 if (iMod >= 1)
3501 pThis->abCurInstr[off++] = 0x7f;
3502 if (iMod == 2)
3503 {
3504 pThis->abCurInstr[off++] = 0x5f;
3505 if (!BS3_MODE_IS_16BIT_CODE(pThis->bMode))
3506 {
3507 pThis->abCurInstr[off++] = 0x3f;
3508 pThis->abCurInstr[off++] = 0x1f;
3509 }
3510 }
3511 }
3512 else
3513 return 0;
3514 pThis->cbCurInstr = off;
3515 return iEncoding + 1;
3516}
3517
3518
3519static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext_VEX_MODRM(PBS3CG1STATE pThis, unsigned iEncoding)
3520{
3521 const unsigned cFirstEncodings = 32;
3522 if (iEncoding < cFirstEncodings)
3523 {
3524 unsigned iRet = Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3(pThis, iEncoding);
3525 BS3_ASSERT(iRet > iEncoding);
3526 return iRet;
3527 }
3528 return Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3(pThis, iEncoding - cFirstEncodings) + cFirstEncodings;
3529}
3530
3531#endif /* BS3CG1_WITH_VEX */
3532
3533
3534/**
3535 * Encodes the next instruction.
3536 *
3537 * @returns Next iEncoding value. Returns @a iEncoding unchanged to indicate
3538 * that there are no more encodings to test.
3539 * @param pThis The state.
3540 * @param iEncoding The encoding to produce. Meaning is specific to
3541 * each BS3CG1ENC_XXX value and should be considered
3542 * internal.
3543 */
3544static unsigned BS3_NEAR_CODE Bs3Cg1EncodeNext(PBS3CG1STATE pThis, unsigned iEncoding)
3545{
3546 pThis->bAlignmentXcpt = UINT8_MAX;
3547 pThis->uVexL = UINT8_MAX;
3548 if (pThis->pfnEncoder)
3549 return pThis->pfnEncoder(pThis, iEncoding);
3550
3551 Bs3TestFailedF("Internal error! BS3CG1ENC_XXX = %u not implemented", pThis->enmEncoding);
3552 return iEncoding;
3553}
3554
3555
3556/**
3557 * Prepares doing instruction encodings.
3558 *
3559 * This is in part specific to how the instruction is encoded, but generally it
3560 * sets up basic operand values that doesn't change (much) when Bs3Cg1EncodeNext
3561 * is called from within the loop.
3562 *
3563 * @returns Success indicator (true/false).
3564 * @param pThis The state.
3565 */
3566#define Bs3Cg1EncodePrep BS3_CMN_NM(Bs3Cg1EncodePrep)
3567bool BS3_NEAR_CODE Bs3Cg1EncodePrep(PBS3CG1STATE pThis)
3568{
3569 unsigned i = 4;
3570 while (i-- > 0)
3571 pThis->aSavedSegRegs[i].ds = pThis->aInitialCtxs[i].ds;
3572
3573 i = RT_ELEMENTS(pThis->aOperands);
3574 while (i-- > 0)
3575 {
3576 pThis->aOperands[i].enmLocationReg = BS3CG1OPLOC_INVALID;
3577 pThis->aOperands[i].enmLocationMem = BS3CG1OPLOC_INVALID;
3578 pThis->aOperands[i].idxFieldBase = BS3CG1DST_INVALID;
3579 }
3580
3581 pThis->iRmOp = RT_ELEMENTS(pThis->aOperands) - 1;
3582 pThis->iRegOp = RT_ELEMENTS(pThis->aOperands) - 1;
3583 pThis->fSameRingNotOkay = false;
3584 pThis->cbOperand = 0;
3585 pThis->pfnEncoder = NULL;
3586
3587 switch (pThis->enmEncoding)
3588 {
3589 case BS3CG1ENC_MODRM_Eb_Gb:
3590 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Eb_Gb_OR_ViceVersa;
3591 pThis->iRmOp = 0;
3592 pThis->iRegOp = 1;
3593 pThis->aOperands[0].cbOp = 1;
3594 pThis->aOperands[1].cbOp = 1;
3595 pThis->aOperands[0].idxFieldBase = BS3CG1DST_AL;
3596 pThis->aOperands[1].idxFieldBase = BS3CG1DST_AL;
3597 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3598 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_RW;
3599 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3600 break;
3601
3602 case BS3CG1ENC_MODRM_Ev_Gv:
3603 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Gv_Ev__OR__MODRM_Ev_Gv;
3604 pThis->iRmOp = 0;
3605 pThis->iRegOp = 1;
3606 pThis->cbOperand = 2;
3607 pThis->aOperands[0].idxFieldBase = BS3CG1DST_OZ_RAX;
3608 pThis->aOperands[1].idxFieldBase = BS3CG1DST_OZ_RAX;
3609 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3610 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_RW;
3611 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3612 break;
3613
3614 case BS3CG1ENC_MODRM_Ed_WO_Pd_WZ:
3615 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ;
3616 pThis->iRmOp = 0;
3617 pThis->iRegOp = 1;
3618 pThis->aOperands[0].cbOp = 4;
3619 pThis->aOperands[1].cbOp = 4;
3620 pThis->aOperands[0].idxFieldBase = BS3CG1DST_EAX;
3621 pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
3622 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3623 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3624 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3625 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3626 break;
3627
3628 case BS3CG1ENC_MODRM_Eq_WO_Pq_WNZ:
3629 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ;
3630 pThis->iRmOp = 0;
3631 pThis->iRegOp = 1;
3632 pThis->aOperands[0].cbOp = 8;
3633 pThis->aOperands[1].cbOp = 8;
3634 pThis->aOperands[0].idxFieldBase = BS3CG1DST_RAX;
3635 pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
3636 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3637 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3638 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3639 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3640 break;
3641
3642 case BS3CG1ENC_MODRM_Ed_WO_Vd_WZ:
3643 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ;
3644 pThis->iRmOp = 0;
3645 pThis->iRegOp = 1;
3646 pThis->aOperands[0].cbOp = 4;
3647 pThis->aOperands[1].cbOp = 4;
3648 pThis->aOperands[0].idxFieldBase = BS3CG1DST_EAX;
3649 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
3650 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3651 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3652 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3653 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3654 break;
3655
3656 case BS3CG1ENC_MODRM_Eq_WO_Vq_WNZ:
3657 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ;
3658 pThis->iRmOp = 0;
3659 pThis->iRegOp = 1;
3660 pThis->aOperands[0].cbOp = 8;
3661 pThis->aOperands[1].cbOp = 8;
3662 pThis->aOperands[0].idxFieldBase = BS3CG1DST_RAX;
3663 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
3664 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3665 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3666 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3667 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3668 break;
3669
3670 case BS3CG1ENC_MODRM_Gb_Eb:
3671 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Eb_Gb_OR_ViceVersa;
3672 pThis->iRegOp = 0;
3673 pThis->iRmOp = 1;
3674 pThis->aOperands[0].cbOp = 1;
3675 pThis->aOperands[1].cbOp = 1;
3676 pThis->aOperands[0].idxFieldBase = BS3CG1DST_AL;
3677 pThis->aOperands[1].idxFieldBase = BS3CG1DST_AL;
3678 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3679 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3680 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3681 break;
3682
3683 case BS3CG1ENC_MODRM_Gv_Ev:
3684 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Gv_Ev__OR__MODRM_Ev_Gv;
3685 pThis->iRegOp = 0;
3686 pThis->iRmOp = 1;
3687 pThis->cbOperand = 2;
3688 pThis->aOperands[0].idxFieldBase = BS3CG1DST_OZ_RAX;
3689 pThis->aOperands[1].idxFieldBase = BS3CG1DST_OZ_RAX;
3690 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3691 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3692 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3693 break;
3694
3695 case BS3CG1ENC_MODRM_Gv_RO_Ma: /* bound instr */
3696 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Gv_RO_Ma;
3697 pThis->iRmOp = 1;
3698 pThis->iRegOp = 0;
3699 pThis->cbOperand = 2;
3700 pThis->aOperands[0].cbOp = 2;
3701 pThis->aOperands[1].cbOp = 4;
3702 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3703 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
3704 pThis->aOperands[0].idxFieldBase = BS3CG1DST_OZ_RAX;
3705 break;
3706
3707 case BS3CG1ENC_MODRM_Wss_WO_Vss:
3708 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3709 pThis->iRmOp = 0;
3710 pThis->iRegOp = 1;
3711 pThis->aOperands[0].cbOp = 4;
3712 pThis->aOperands[1].cbOp = 4;
3713 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0;
3714 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_DW0;
3715 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3716 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3717 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3718 break;
3719
3720 case BS3CG1ENC_MODRM_Wsd_WO_Vsd:
3721 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3722 pThis->iRmOp = 0;
3723 pThis->iRegOp = 1;
3724 pThis->aOperands[0].cbOp = 8;
3725 pThis->aOperands[1].cbOp = 8;
3726 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
3727 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3728 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3729 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3730 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3731 break;
3732
3733 case BS3CG1ENC_MODRM_WqZxReg_WO_Vq:
3734 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3735 pThis->iRmOp = 0;
3736 pThis->iRegOp = 1;
3737 pThis->aOperands[0].cbOp = 8;
3738 pThis->aOperands[1].cbOp = 8;
3739 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
3740 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3741 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3742 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3743 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3744 break;
3745
3746 case BS3CG1ENC_MODRM_Wps_WO_Vps:
3747 case BS3CG1ENC_MODRM_Wpd_WO_Vpd:
3748 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3749 pThis->iRmOp = 0;
3750 pThis->iRegOp = 1;
3751 pThis->aOperands[0].cbOp = 16;
3752 pThis->aOperands[1].cbOp = 16;
3753 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
3754 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
3755 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
3756 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3757 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3758 break;
3759
3760 case BS3CG1ENC_MODRM_Vdq_WO_Mdq:
3761 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
3762 pThis->iRegOp = 0;
3763 pThis->iRmOp = 1;
3764 pThis->aOperands[0].cbOp = 16;
3765 pThis->aOperands[1].cbOp = 16;
3766 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3767 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
3768 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
3769 break;
3770
3771 case BS3CG1ENC_MODRM_Vdq_WO_Wdq:
3772 case BS3CG1ENC_MODRM_Vpd_WO_Wpd:
3773 case BS3CG1ENC_MODRM_Vps_WO_Wps:
3774 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3775 pThis->iRegOp = 0;
3776 pThis->iRmOp = 1;
3777 pThis->aOperands[0].cbOp = 16;
3778 pThis->aOperands[1].cbOp = 16;
3779 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
3780 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
3781 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3782 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3783 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3784 break;
3785
3786 case BS3CG1ENC_MODRM_Pq_WO_Qq:
3787 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Pq_WO_Qq;
3788 pThis->iRegOp = 0;
3789 pThis->iRmOp = 1;
3790 pThis->aOperands[0].cbOp = 8;
3791 pThis->aOperands[1].cbOp = 8;
3792 pThis->aOperands[0].idxFieldBase = BS3CG1DST_MM0;
3793 pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
3794 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3795 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3796 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3797 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3798 break;
3799
3800 case BS3CG1ENC_MODRM_Pq_WO_Uq:
3801 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Pq_WO_Uq;
3802 pThis->iRegOp = 0;
3803 pThis->iRmOp = 1;
3804 pThis->aOperands[0].cbOp = 8;
3805 pThis->aOperands[1].cbOp = 8;
3806 pThis->aOperands[0].idxFieldBase = BS3CG1DST_MM0;
3807 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3808 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3809 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX; /* reg only */
3810 break;
3811
3812 case BS3CG1ENC_MODRM_PdZx_WO_Ed_WZ:
3813 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_PdZx_WO_Ed_WZ;
3814 pThis->iRegOp = 0;
3815 pThis->iRmOp = 1;
3816 pThis->aOperands[0].cbOp = 4;
3817 pThis->aOperands[1].cbOp = 4;
3818 pThis->aOperands[0].idxFieldBase = BS3CG1DST_MM0_LO_ZX;
3819 pThis->aOperands[1].idxFieldBase = BS3CG1DST_EAX;
3820 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3821 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3822 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3823 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3824 break;
3825
3826 case BS3CG1ENC_MODRM_Pq_WO_Eq_WNZ:
3827 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Pq_WO_Eq_WNZ;
3828 pThis->iRegOp = 0;
3829 pThis->iRmOp = 1;
3830 pThis->aOperands[0].cbOp = 8;
3831 pThis->aOperands[1].cbOp = 8;
3832 pThis->aOperands[0].idxFieldBase = BS3CG1DST_MM0;
3833 pThis->aOperands[1].idxFieldBase = BS3CG1DST_RAX;
3834 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3835 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3836 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3837 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3838 break;
3839
3840 case BS3CG1ENC_MODRM_VdZx_WO_Ed_WZ:
3841 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vd_WO_Ed_WZ;
3842 pThis->iRegOp = 0;
3843 pThis->iRmOp = 1;
3844 pThis->aOperands[0].cbOp = 4;
3845 pThis->aOperands[1].cbOp = 4;
3846 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0_ZX;
3847 pThis->aOperands[1].idxFieldBase = BS3CG1DST_EAX;
3848 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3849 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3850 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3851 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3852 break;
3853
3854 case BS3CG1ENC_MODRM_VqZx_WO_Eq_WNZ:
3855 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vq_WO_Eq_WNZ;
3856 pThis->iRegOp = 0;
3857 pThis->iRmOp = 1;
3858 pThis->aOperands[0].cbOp = 8;
3859 pThis->aOperands[1].cbOp = 8;
3860 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
3861 pThis->aOperands[1].idxFieldBase = BS3CG1DST_RAX;
3862 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3863 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3864 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3865 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3866 break;
3867
3868 case BS3CG1ENC_MODRM_Vq_WO_UqHi:
3869 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Usomething_OR_ViceVersa;
3870 pThis->iRegOp = 0;
3871 pThis->iRmOp = 1;
3872 pThis->aOperands[0].cbOp = 8;
3873 pThis->aOperands[1].cbOp = 8;
3874 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
3875 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
3876 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3877 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3878 break;
3879
3880 case BS3CG1ENC_MODRM_VqHi_WO_Uq:
3881 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Usomething_OR_ViceVersa;
3882 pThis->iRegOp = 0;
3883 pThis->iRmOp = 1;
3884 pThis->aOperands[0].cbOp = 8;
3885 pThis->aOperands[1].cbOp = 8;
3886 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_HI;
3887 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3888 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3889 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3890 break;
3891
3892 case BS3CG1ENC_MODRM_VqHi_WO_Mq:
3893 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
3894 pThis->iRegOp = 0;
3895 pThis->iRmOp = 1;
3896 pThis->aOperands[0].cbOp = 8;
3897 pThis->aOperands[1].cbOp = 8;
3898 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_HI;
3899 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3900 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
3901 break;
3902
3903 case BS3CG1ENC_MODRM_Vq_WO_Mq:
3904 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
3905 pThis->iRegOp = 0;
3906 pThis->iRmOp = 1;
3907 pThis->aOperands[0].cbOp = 8;
3908 pThis->aOperands[1].cbOp = 8;
3909 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
3910 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3911 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
3912 break;
3913
3914 case BS3CG1ENC_MODRM_VssZx_WO_Wss:
3915 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3916 pThis->iRegOp = 0;
3917 pThis->iRmOp = 1;
3918 pThis->aOperands[0].cbOp = 4;
3919 pThis->aOperands[1].cbOp = 4;
3920 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3921 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3922 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3923 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0_ZX;
3924 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3925 break;
3926
3927 case BS3CG1ENC_MODRM_VqZx_WO_Nq:
3928 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Nsomething;
3929 pThis->iRegOp = 0;
3930 pThis->iRmOp = 1;
3931 pThis->aOperands[0].cbOp = 8;
3932 pThis->aOperands[1].cbOp = 8;
3933 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3934 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3935 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
3936 pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
3937 break;
3938
3939 case BS3CG1ENC_MODRM_VsdZx_WO_Wsd:
3940 case BS3CG1ENC_MODRM_VqZx_WO_Wq:
3941 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Vsomething_Wsomething_OR_ViceVersa;
3942 pThis->iRegOp = 0;
3943 pThis->iRmOp = 1;
3944 pThis->aOperands[0].cbOp = 8;
3945 pThis->aOperands[1].cbOp = 8;
3946 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
3947 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3948 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
3949 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
3950 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
3951 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
3952 break;
3953
3954 case BS3CG1ENC_MODRM_Mb_RO:
3955 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething;
3956 pThis->iRmOp = 0;
3957 pThis->aOperands[0].cbOp = 1;
3958 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
3959 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM;
3960 break;
3961
3962 case BS3CG1ENC_MODRM_Md_RO:
3963 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething;
3964 pThis->iRmOp = 0;
3965 pThis->aOperands[0].cbOp = 4;
3966 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
3967 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM;
3968 break;
3969
3970 case BS3CG1ENC_MODRM_Md_WO:
3971 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething;
3972 pThis->iRmOp = 0;
3973 pThis->aOperands[0].cbOp = 4;
3974 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
3975 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
3976 break;
3977
3978 case BS3CG1ENC_MODRM_Mdq_WO_Vdq:
3979 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
3980 pThis->iRmOp = 0;
3981 pThis->iRegOp = 1;
3982 pThis->aOperands[0].cbOp = 16;
3983 pThis->aOperands[1].cbOp = 16;
3984 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
3985 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3986 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
3987 break;
3988
3989 case BS3CG1ENC_MODRM_Mq_WO_Pq:
3990 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Psomething;
3991 pThis->iRmOp = 0;
3992 pThis->iRegOp = 1;
3993 pThis->aOperands[0].cbOp = 8;
3994 pThis->aOperands[1].cbOp = 8;
3995 pThis->aOperands[1].idxFieldBase = BS3CG1DST_MM0;
3996 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
3997 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
3998 break;
3999
4000 case BS3CG1ENC_MODRM_Mq_WO_Vq:
4001 case BS3CG1ENC_MODRM_Mq_WO_VqHi:
4002 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
4003 pThis->iRmOp = 0;
4004 pThis->iRegOp = 1;
4005 pThis->aOperands[0].cbOp = 8;
4006 pThis->aOperands[1].cbOp = 8;
4007 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4008 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4009 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4010 pThis->aOperands[1].idxFieldBase = pThis->enmEncoding == BS3CG1ENC_MODRM_Mq_WO_Vq
4011 ? BS3CG1DST_XMM0_LO : BS3CG1DST_XMM0_HI;
4012 break;
4013
4014 case BS3CG1ENC_MODRM_Mps_WO_Vps:
4015 case BS3CG1ENC_MODRM_Mpd_WO_Vpd:
4016 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_Msomething_Vsomething_OR_ViceVersa;
4017 pThis->iRmOp = 0;
4018 pThis->iRegOp = 1;
4019 pThis->aOperands[0].cbOp = 16;
4020 pThis->aOperands[1].cbOp = 16;
4021 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4022 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4023 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4024 break;
4025
4026 case BS3CG1ENC_FIXED:
4027 pThis->pfnEncoder = Bs3Cg1EncodeNext_FIXED;
4028 break;
4029
4030 case BS3CG1ENC_FIXED_AL_Ib:
4031 pThis->pfnEncoder = Bs3Cg1EncodeNext_FIXED_AL_Ib;
4032 pThis->aOperands[0].cbOp = 1;
4033 pThis->aOperands[1].cbOp = 1;
4034 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
4035 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
4036 pThis->aOperands[0].idxField = BS3CG1DST_AL;
4037 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
4038 break;
4039
4040 case BS3CG1ENC_FIXED_rAX_Iz:
4041 pThis->pfnEncoder = Bs3Cg1EncodeNext_FIXED_rAX_Iz;
4042 pThis->aOperands[0].cbOp = 2;
4043 pThis->aOperands[1].cbOp = 2;
4044 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
4045 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_IMM;
4046 pThis->aOperands[0].idxField = BS3CG1DST_OZ_RAX;
4047 pThis->aOperands[1].idxField = BS3CG1DST_INVALID;
4048 break;
4049
4050 /* Unused or invalid instructions mostly. */
4051 case BS3CG1ENC_MODRM_MOD_EQ_3:
4052 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_MOD_EQ_3;
4053 break;
4054 case BS3CG1ENC_MODRM_MOD_NE_3:
4055 pThis->pfnEncoder = Bs3Cg1EncodeNext_MODRM_MOD_NE_3;
4056 break;
4057
4058#ifdef BS3CG1_WITH_VEX
4059
4060 case BS3CG1ENC_VEX_MODRM_Vd_WO_Ed_WZ:
4061 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ;
4062 pThis->iRegOp = 0;
4063 pThis->iRmOp = 1;
4064 pThis->aOperands[0].cbOp = 4;
4065 pThis->aOperands[1].cbOp = 4;
4066 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0_ZX;
4067 pThis->aOperands[1].idxFieldBase = BS3CG1DST_EAX;
4068 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4069 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4070 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
4071 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
4072 break;
4073
4074 case BS3CG1ENC_VEX_MODRM_Vq_WO_Eq_WNZ:
4075 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ;
4076 pThis->iRegOp = 0;
4077 pThis->iRmOp = 1;
4078 pThis->aOperands[0].cbOp = 8;
4079 pThis->aOperands[1].cbOp = 8;
4080 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
4081 pThis->aOperands[1].idxFieldBase = BS3CG1DST_RAX;
4082 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4083 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4084 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
4085 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
4086 break;
4087
4088 case BS3CG1ENC_VEX_MODRM_Vps_WO_Wps:
4089 case BS3CG1ENC_VEX_MODRM_Vpd_WO_Wpd:
4090 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
4091 pThis->iRegOp = 0;
4092 pThis->iRmOp = 1;
4093 pThis->aOperands[0].cbOp = 16;
4094 pThis->aOperands[1].cbOp = 16;
4095 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4096 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4097 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
4098 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
4099 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4100 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4101 break;
4102
4103 case BS3CG1ENC_VEX_MODRM_VssZx_WO_Md:
4104 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
4105 pThis->iRmOp = 1;
4106 pThis->iRegOp = 0;
4107 pThis->aOperands[0].cbOp = 4;
4108 pThis->aOperands[1].cbOp = 4;
4109 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4110 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
4111 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_DW0;
4112 pThis->aOperands[1].idxFieldBase = BS3CG1DST_INVALID;
4113 break;
4114
4115 case BS3CG1ENC_VEX_MODRM_Vss_WO_HssHi_Uss:
4116 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
4117 pThis->iRegOp = 0;
4118 pThis->iRmOp = 2;
4119 pThis->aOperands[0].cbOp = 16;
4120 pThis->aOperands[1].cbOp = 12;
4121 pThis->aOperands[2].cbOp = 4;
4122 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4123 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4124 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_CTX;
4125 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4126 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI96;
4127 pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_DW0;
4128 break;
4129
4130 case BS3CG1ENC_VEX_MODRM_VsdZx_WO_Mq:
4131 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
4132 pThis->iRmOp = 1;
4133 pThis->iRegOp = 0;
4134 pThis->aOperands[0].cbOp = 8;
4135 pThis->aOperands[1].cbOp = 8;
4136 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4137 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
4138 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
4139 pThis->aOperands[1].idxFieldBase = BS3CG1DST_INVALID;
4140 break;
4141
4142 case BS3CG1ENC_VEX_MODRM_Vx_WO_Mx_L0:
4143 BS3_ASSERT(!(pThis->fFlags & BS3CG1INSTR_F_VEX_L_ZERO));
4144 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L0_OR_ViceVersa;
4145 pThis->iRegOp = 0;
4146 pThis->iRmOp = 1;
4147 pThis->aOperands[0].cbOp = 16;
4148 pThis->aOperands[1].cbOp = 16;
4149 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4150 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
4151 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4152 break;
4153
4154 case BS3CG1ENC_VEX_MODRM_Vx_WO_Mx_L1:
4155 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_L1_OR_ViceVersa;
4156 pThis->iRegOp = 0;
4157 pThis->iRmOp = 1;
4158 pThis->aOperands[0].cbOp = 32;
4159 pThis->aOperands[1].cbOp = 32;
4160 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4161 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_MEM;
4162 pThis->aOperands[0].idxFieldBase = BS3CG1DST_YMM0;
4163 break;
4164
4165 case BS3CG1ENC_VEX_MODRM_Vsd_WO_HsdHi_Usd:
4166 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
4167 pThis->iRegOp = 0;
4168 pThis->iRmOp = 2;
4169 pThis->aOperands[0].cbOp = 16;
4170 pThis->aOperands[1].cbOp = 8;
4171 pThis->aOperands[2].cbOp = 8;
4172 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4173 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4174 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_CTX;
4175 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4176 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
4177 pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_LO;
4178 break;
4179
4180 case BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_UqHi:
4181 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_HdqCsomething_Usomething_Wip_OR_ViceVersa;
4182 pThis->iRegOp = 0;
4183 pThis->iRmOp = 2;
4184 pThis->aOperands[0].cbOp = 16;
4185 pThis->aOperands[1].cbOp = 8;
4186 pThis->aOperands[2].cbOp = 8;
4187 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4188 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4189 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_CTX;
4190 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4191 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
4192 pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_HI;
4193 break;
4194
4195 case BS3CG1ENC_VEX_MODRM_Vq_WO_HqHi_Mq:
4196 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Msomething_Wip_OR_ViceVersa;
4197 pThis->iRegOp = 0;
4198 pThis->iRmOp = 2;
4199 pThis->aOperands[0].cbOp = 16;
4200 pThis->aOperands[1].cbOp = 8;
4201 pThis->aOperands[2].cbOp = 8;
4202 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4203 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4204 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_MEM;
4205 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4206 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
4207 pThis->aOperands[2].idxFieldBase = BS3CG1DST_INVALID;
4208 break;
4209
4210 case BS3CG1ENC_VEX_MODRM_Vq_WO_Wq:
4211 BS3_ASSERT(pThis->fFlags & BS3CG1INSTR_F_VEX_L_ZERO);
4212 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_Lmbz_OR_ViceVersa;
4213 pThis->iRegOp = 0;
4214 pThis->iRmOp = 1;
4215 pThis->aOperands[0].cbOp = 8;
4216 pThis->aOperands[1].cbOp = 8;
4217 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4218 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4219 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
4220 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
4221 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
4222 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
4223 break;
4224
4225 case BS3CG1ENC_VEX_MODRM_Vx_WO_Wx:
4226 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
4227 pThis->iRegOp = 0;
4228 pThis->iRmOp = 1;
4229 pThis->aOperands[0].cbOp = 16;
4230 pThis->aOperands[1].cbOp = 16;
4231 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4232 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4233 pThis->aOperands[1].enmLocationReg = BS3CG1OPLOC_CTX;
4234 pThis->aOperands[1].enmLocationMem = BS3CG1OPLOC_MEM;
4235 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4236 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4237 break;
4238
4239 case BS3CG1ENC_VEX_MODRM_Ed_WO_Vd_WZ:
4240 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_Vd_WO_Ed_WZ;
4241 pThis->iRmOp = 0;
4242 pThis->iRegOp = 1;
4243 pThis->aOperands[0].cbOp = 4;
4244 pThis->aOperands[1].cbOp = 4;
4245 pThis->aOperands[0].idxFieldBase = BS3CG1DST_EAX;
4246 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_DW0_ZX;
4247 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
4248 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
4249 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4250 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4251 break;
4252
4253 case BS3CG1ENC_VEX_MODRM_Eq_WO_Vq_WNZ:
4254 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_Vq_WO_Eq_WNZ;
4255 pThis->iRmOp = 0;
4256 pThis->iRegOp = 1;
4257 pThis->aOperands[0].cbOp = 8;
4258 pThis->aOperands[1].cbOp = 8;
4259 pThis->aOperands[0].idxFieldBase = BS3CG1DST_RAX;
4260 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO_ZX;
4261 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX;
4262 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX;
4263 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4264 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4265 break;
4266
4267 case BS3CG1ENC_VEX_MODRM_Md_WO:
4268 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_Md_WO;
4269 pThis->iRmOp = 0;
4270 pThis->aOperands[0].cbOp = 4;
4271 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4272 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4273 break;
4274
4275 case BS3CG1ENC_VEX_MODRM_Md_WO_Vss:
4276 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
4277 pThis->iRmOp = 0;
4278 pThis->iRegOp = 1;
4279 pThis->aOperands[0].cbOp = 4;
4280 pThis->aOperands[1].cbOp = 4;
4281 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4282 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4283 pThis->aOperands[0].idxFieldBase = BS3CG1DST_INVALID;
4284 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_DW0;
4285 break;
4286
4287 case BS3CG1ENC_VEX_MODRM_Mq_WO_Vq:
4288 BS3_ASSERT(pThis->fFlags & (BS3CG1INSTR_F_VEX_L_ZERO | BS3CG1INSTR_F_VEX_L_IGNORED));
4289 pThis->pfnEncoder = pThis->fFlags & BS3CG1INSTR_F_VEX_L_ZERO
4290 ? Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lmbz_OR_ViceVersa
4291 : Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
4292 pThis->iRmOp = 0;
4293 pThis->iRegOp = 1;
4294 pThis->aOperands[0].cbOp = 8;
4295 pThis->aOperands[1].cbOp = 8;
4296 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4297 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4298 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
4299 break;
4300
4301 case BS3CG1ENC_VEX_MODRM_Mq_WO_Vsd:
4302 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_Lig_OR_ViceVersa;
4303 pThis->iRmOp = 0;
4304 pThis->iRegOp = 1;
4305 pThis->aOperands[0].cbOp = 8;
4306 pThis->aOperands[1].cbOp = 8;
4307 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4308 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4309 pThis->aOperands[0].idxFieldBase = BS3CG1DST_INVALID;
4310 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
4311 break;
4312
4313 case BS3CG1ENC_VEX_MODRM_Mps_WO_Vps:
4314 case BS3CG1ENC_VEX_MODRM_Mpd_WO_Vpd:
4315 case BS3CG1ENC_VEX_MODRM_Mx_WO_Vx:
4316 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Msomething_Wip_OR_ViceVersa;
4317 pThis->iRmOp = 0;
4318 pThis->iRegOp = 1;
4319 pThis->aOperands[0].cbOp = 16;
4320 pThis->aOperands[1].cbOp = 16;
4321 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM_WO;
4322 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4323 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4324 break;
4325
4326 case BS3CG1ENC_VEX_MODRM_Uss_WO_HssHi_Vss:
4327 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
4328 pThis->iRegOp = 2;
4329 pThis->iRmOp = 0;
4330 pThis->aOperands[0].cbOp = 16;
4331 pThis->aOperands[1].cbOp = 96;
4332 pThis->aOperands[2].cbOp = 4;
4333 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4334 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4335 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_CTX;
4336 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4337 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI96;
4338 pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_DW0;
4339 break;
4340
4341 case BS3CG1ENC_VEX_MODRM_Usd_WO_HsdHi_Vsd:
4342 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_VsomethingWO_Hsomething_Usomething_Lip_Wip_OR_ViceVersa;
4343 pThis->iRegOp = 2;
4344 pThis->iRmOp = 0;
4345 pThis->aOperands[0].cbOp = 16;
4346 pThis->aOperands[1].cbOp = 8;
4347 pThis->aOperands[2].cbOp = 8;
4348 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4349 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4350 pThis->aOperands[2].enmLocation = BS3CG1OPLOC_CTX;
4351 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4352 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_HI;
4353 pThis->aOperands[2].idxFieldBase = BS3CG1DST_XMM0_LO;
4354 break;
4355
4356 case BS3CG1ENC_VEX_MODRM_Wps_WO_Vps:
4357 case BS3CG1ENC_VEX_MODRM_Wpd_WO_Vpd:
4358 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
4359 pThis->iRmOp = 0;
4360 pThis->iRegOp = 1;
4361 pThis->aOperands[0].cbOp = 16;
4362 pThis->aOperands[1].cbOp = 16;
4363 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4364 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX_ZX_VLMAX;
4365 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4366 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4367 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4368 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4369 break;
4370
4371 case BS3CG1ENC_VEX_MODRM_Wq_WO_Vq:
4372 BS3_ASSERT(pThis->fFlags & BS3CG1INSTR_F_VEX_L_ZERO);
4373 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_Lmbz_OR_ViceVersa;
4374 pThis->iRegOp = 1;
4375 pThis->iRmOp = 0;
4376 pThis->aOperands[0].cbOp = 8;
4377 pThis->aOperands[1].cbOp = 8;
4378 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4379 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX_ZX_VLMAX;
4380 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4381 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4382 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0_LO;
4383 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0_LO;
4384 break;
4385
4386 case BS3CG1ENC_VEX_MODRM_Wx_WO_Vx:
4387 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_WsomethingWO_Vsomething_Wip_OR_ViceVersa;
4388 pThis->iRmOp = 0;
4389 pThis->iRegOp = 1;
4390 pThis->aOperands[0].cbOp = 16;
4391 pThis->aOperands[1].cbOp = 16;
4392 pThis->aOperands[0].enmLocation = BS3CG1OPLOC_CTX_ZX_VLMAX;
4393 pThis->aOperands[0].enmLocationReg = BS3CG1OPLOC_CTX_ZX_VLMAX;
4394 pThis->aOperands[0].enmLocationMem = BS3CG1OPLOC_MEM_WO;
4395 pThis->aOperands[1].enmLocation = BS3CG1OPLOC_CTX;
4396 pThis->aOperands[0].idxFieldBase = BS3CG1DST_XMM0;
4397 pThis->aOperands[1].idxFieldBase = BS3CG1DST_XMM0;
4398 break;
4399
4400
4401 /* Unused or invalid instructions mostly. */
4402 //case BS3CG1ENC_VEX_FIXED:
4403 // pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_FIXED;
4404 // break;
4405 case BS3CG1ENC_VEX_MODRM_MOD_EQ_3:
4406 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_MOD_EQ_3;
4407 break;
4408 case BS3CG1ENC_VEX_MODRM_MOD_NE_3:
4409 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM_MOD_NE_3;
4410 break;
4411 case BS3CG1ENC_VEX_MODRM:
4412 pThis->pfnEncoder = Bs3Cg1EncodeNext_VEX_MODRM;
4413 break;
4414
4415#endif /* BS3CG1_WITH_VEX */
4416
4417 default:
4418 Bs3TestFailedF("Invalid/unimplemented enmEncoding for instruction #%RU32 (%.*s): %d",
4419 pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic, pThis->enmEncoding);
4420 return false;
4421 }
4422 return true;
4423}
4424
4425
4426/**
4427 * Calculates the appropriate non-intel invalid instruction encoding.
4428 *
4429 * @returns the encoding to use instead.
4430 * @param enmEncoding The intel invalid instruction encoding.
4431 */
4432static BS3CG1ENC Bs3Cg1CalcNoneIntelInvalidEncoding(BS3CG1ENC enmEncoding)
4433{
4434 switch (enmEncoding)
4435 {
4436 case BS3CG1ENC_MODRM_Gb_Eb:
4437 case BS3CG1ENC_MODRM_Gv_RO_Ma:
4438 case BS3CG1ENC_FIXED:
4439 return BS3CG1ENC_FIXED;
4440 default:
4441 Bs3TestFailedF("Bs3Cg1CalcNoneIntelInvalidEncoding: Unsupported encoding: %d\n", enmEncoding);
4442 return BS3CG1ENC_FIXED;
4443 }
4444}
4445
4446
4447/**
4448 * Sets cbOpDefault, cbOpOvrd66 and cbOpOvrdRexW.
4449 *
4450 * @param pThis The state.
4451 * @param bMode The mode (only code part is used).
4452 */
4453static void Bs3Cg1SetOpSizes(PBS3CG1STATE pThis, uint8_t bMode)
4454{
4455 if (BS3_MODE_IS_16BIT_CODE(bMode))
4456 {
4457 pThis->cbOpDefault = 2;
4458 pThis->cbOpOvrd66 = 4;
4459 pThis->cbOpOvrdRexW = 0;
4460 }
4461 else if (BS3_MODE_IS_32BIT_CODE(bMode))
4462 {
4463 pThis->cbOpDefault = 4;
4464 pThis->cbOpOvrd66 = 2;
4465 pThis->cbOpOvrdRexW = 0;
4466 }
4467 else
4468 {
4469 pThis->cbOpDefault = 4;
4470 pThis->cbOpOvrd66 = 2;
4471 pThis->cbOpOvrdRexW = 8;
4472 }
4473}
4474
4475
4476/**
4477 * Sets up SSE and maybe AVX.
4478 *
4479 * @returns true (if successful, false if not and the SSE instructions ends up
4480 * being invalid).
4481 * @param pThis The state.
4482 */
4483static bool BS3_NEAR_CODE Bs3Cg3SetupSseAndAvx(PBS3CG1STATE pThis)
4484{
4485 if (!pThis->fWorkExtCtx)
4486 {
4487 unsigned i;
4488 uint32_t cr0 = ASMGetCR0();
4489 uint32_t cr4 = ASMGetCR4();
4490
4491 cr0 &= ~(X86_CR0_TS | X86_CR0_MP | X86_CR0_EM);
4492 cr0 |= X86_CR0_NE;
4493 ASMSetCR0(cr0);
4494 if (pThis->pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
4495 {
4496 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE;
4497 ASMSetCR4(cr4);
4498 ASMSetXcr0(pThis->pExtCtx->fXcr0Nominal);
4499 }
4500 else
4501 {
4502 cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT;
4503 ASMSetCR4(cr4);
4504 }
4505
4506 for (i = 0; i < RT_ELEMENTS(pThis->aInitialCtxs); i++)
4507 {
4508 pThis->aInitialCtxs[i].cr0.u32 = cr0;
4509 pThis->aInitialCtxs[i].cr4.u32 = cr4;
4510 }
4511 pThis->fWorkExtCtx = true;
4512 }
4513
4514 return true;
4515}
4516
4517
4518/**
4519 * Next CPU configuration to test the current instruction in.
4520 *
4521 * This is for testing FPU, SSE and AVX instructions with the various lazy state
4522 * load and enable bits in different configurations to ensure we're getting the
4523 * right response.
4524 *
4525 * This also cleans up the CPU and test driver state.
4526 *
4527 * @returns true if we're to do another round, false if we're done.
4528 * @param pThis The state.
4529 * @param iCpuSetup The current CPU setup number.
4530 * @param pfInvalidInstr Where to indicate whether the setup causes an
4531 * invalid instruction or not. This is also used as
4532 * input to avoid unnecessary CPUID work.
4533 */
4534static bool BS3_NEAR_CODE Bs3Cg1CpuSetupNext(PBS3CG1STATE pThis, unsigned iCpuSetup, bool BS3_FAR *pfInvalidInstr)
4535{
4536 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
4537 && BS3CG1_IS_64BIT_TARGET(pThis))
4538 return false;
4539
4540 switch (pThis->enmCpuTest)
4541 {
4542 case BS3CG1CPU_ANY:
4543 case BS3CG1CPU_GE_80186:
4544 case BS3CG1CPU_GE_80286:
4545 case BS3CG1CPU_GE_80386:
4546 case BS3CG1CPU_GE_80486:
4547 case BS3CG1CPU_GE_Pentium:
4548 case BS3CG1CPU_CLFSH:
4549 case BS3CG1CPU_CLFLUSHOPT:
4550 return false;
4551
4552 case BS3CG1CPU_MMX:
4553 return false;
4554
4555 case BS3CG1CPU_SSE:
4556 case BS3CG1CPU_SSE2:
4557 case BS3CG1CPU_SSE3:
4558 case BS3CG1CPU_SSE4_1:
4559 case BS3CG1CPU_AVX:
4560 case BS3CG1CPU_AVX2:
4561 if (iCpuSetup > 0 || *pfInvalidInstr)
4562 {
4563 /** @todo do more configs here. */
4564 pThis->fWorkExtCtx = false;
4565 ASMSetCR0(ASMGetCR0() | X86_CR0_EM | X86_CR0_MP);
4566 ASMSetCR4(ASMGetCR4() & ~(X86_CR4_OSFXSR | X86_CR4_OSXMMEEXCPT | X86_CR4_OSXSAVE));
4567 return false;
4568 }
4569 return false;
4570
4571 default:
4572 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
4573 return false;
4574 }
4575}
4576
4577
4578/**
4579 * Check if the instruction is supported by the CPU, possibly making state
4580 * adjustments to enable support for it.
4581 *
4582 * @returns true if supported, false if not.
4583 * @param pThis The state.
4584 */
4585static bool BS3_NEAR_CODE Bs3Cg1CpuSetupFirst(PBS3CG1STATE pThis)
4586{
4587 uint32_t fEax;
4588 uint32_t fEbx;
4589 uint32_t fEcx;
4590 uint32_t fEdx;
4591
4592 if ( (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT)
4593 && BS3CG1_IS_64BIT_TARGET(pThis))
4594 return false;
4595
4596 switch (pThis->enmCpuTest)
4597 {
4598 case BS3CG1CPU_ANY:
4599 return true;
4600
4601 case BS3CG1CPU_GE_80186:
4602 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80186)
4603 return true;
4604 return false;
4605
4606 case BS3CG1CPU_GE_80286:
4607 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80286)
4608 return true;
4609 return false;
4610
4611 case BS3CG1CPU_GE_80386:
4612 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
4613 return true;
4614 return false;
4615
4616 case BS3CG1CPU_GE_80486:
4617 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486)
4618 return true;
4619 return false;
4620
4621 case BS3CG1CPU_GE_Pentium:
4622 if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_Pentium)
4623 return true;
4624 return false;
4625
4626 case BS3CG1CPU_MMX:
4627 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
4628 {
4629 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, NULL, &fEdx);
4630 if (fEdx & X86_CPUID_FEATURE_EDX_MMX)
4631 return Bs3Cg3SetupSseAndAvx(pThis); /** @todo only do FNSAVE/FXSAVE here? */
4632 }
4633 return false;
4634
4635 case BS3CG1CPU_SSE:
4636 case BS3CG1CPU_SSE2:
4637 case BS3CG1CPU_SSE3:
4638 case BS3CG1CPU_SSE4_1:
4639 case BS3CG1CPU_AVX:
4640 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
4641 {
4642 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, &fEdx);
4643 switch (pThis->enmCpuTest)
4644 {
4645 case BS3CG1CPU_SSE:
4646 if (fEdx & X86_CPUID_FEATURE_EDX_SSE)
4647 return Bs3Cg3SetupSseAndAvx(pThis);
4648 return false;
4649 case BS3CG1CPU_SSE2:
4650 if (fEdx & X86_CPUID_FEATURE_EDX_SSE2)
4651 return Bs3Cg3SetupSseAndAvx(pThis);
4652 return false;
4653 case BS3CG1CPU_SSE3:
4654 if (fEcx & X86_CPUID_FEATURE_ECX_SSE3)
4655 return Bs3Cg3SetupSseAndAvx(pThis);
4656 return false;
4657 case BS3CG1CPU_SSE4_1:
4658 if (fEcx & X86_CPUID_FEATURE_ECX_SSE4_1)
4659 return Bs3Cg3SetupSseAndAvx(pThis);
4660 return false;
4661 case BS3CG1CPU_AVX:
4662 if (fEcx & X86_CPUID_FEATURE_ECX_AVX)
4663 return Bs3Cg3SetupSseAndAvx(pThis) && !BS3_MODE_IS_RM_OR_V86(pThis->bMode);
4664 return false;
4665 default: BS3_ASSERT(0); /* impossible */
4666 }
4667 }
4668 return false;
4669
4670 case BS3CG1CPU_AVX2:
4671 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
4672 {
4673 ASMCpuIdExSlow(7, 0, 0/*leaf*/, 0, &fEax, &fEbx, &fEcx, &fEdx);
4674 switch (pThis->enmCpuTest)
4675 {
4676 case BS3CG1CPU_AVX2:
4677 if (fEbx & X86_CPUID_STEXT_FEATURE_EBX_AVX2)
4678 return Bs3Cg3SetupSseAndAvx(pThis) && !BS3_MODE_IS_RM_OR_V86(pThis->bMode);
4679 return false;
4680 default: BS3_ASSERT(0); return false; /* impossible */
4681 }
4682 }
4683 return false;
4684
4685 case BS3CG1CPU_CLFSH:
4686 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
4687 {
4688 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, NULL, &fEdx);
4689 if (fEdx & X86_CPUID_FEATURE_EDX_CLFSH)
4690 return true;
4691 }
4692 return false;
4693
4694 case BS3CG1CPU_CLFLUSHOPT:
4695 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
4696 {
4697 ASMCpuIdExSlow(7, 0, 0/*leaf*/, 0, NULL, &fEbx, NULL, NULL);
4698 if (fEbx & X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT)
4699 return true;
4700 }
4701 return false;
4702
4703 default:
4704 Bs3TestFailedF("Invalid enmCpuTest value: %d", pThis->enmCpuTest);
4705 return false;
4706 }
4707}
4708
4709
4710
4711/**
4712 * Checks the preconditions for a test.
4713 *
4714 * @returns true if the test be executed, false if not.
4715 * @param pThis The state.
4716 * @param pHdr The test header.
4717 */
4718static bool BS3_NEAR_CODE Bs3Cg1RunSelector(PBS3CG1STATE pThis, PCBS3CG1TESTHDR pHdr)
4719{
4720
4721 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1);
4722 unsigned cbLeft = pHdr->cbSelector;
4723 while (cbLeft-- > 0)
4724 {
4725 switch (*pbCode++)
4726 {
4727#define CASE_PRED(a_Pred, a_Expr) \
4728 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_TRUE: \
4729 if (!(a_Expr)) return false; \
4730 break; \
4731 case ((a_Pred) << BS3CG1SEL_OP_KIND_MASK) | BS3CG1SEL_OP_IS_FALSE: \
4732 if (a_Expr) return false; \
4733 break
4734 CASE_PRED(BS3CG1PRED_SIZE_O16, pThis->cbOperand == 2);
4735 CASE_PRED(BS3CG1PRED_SIZE_O32, pThis->cbOperand == 4);
4736 CASE_PRED(BS3CG1PRED_SIZE_O64, pThis->cbOperand == 8);
4737 CASE_PRED(BS3CG1PRED_VEXL_0, pThis->uVexL == 0);
4738 CASE_PRED(BS3CG1PRED_VEXL_1, pThis->uVexL == 1);
4739 CASE_PRED(BS3CG1PRED_RING_0, pThis->uCpl == 0);
4740 CASE_PRED(BS3CG1PRED_RING_1, pThis->uCpl == 1);
4741 CASE_PRED(BS3CG1PRED_RING_2, pThis->uCpl == 2);
4742 CASE_PRED(BS3CG1PRED_RING_3, pThis->uCpl == 3);
4743 CASE_PRED(BS3CG1PRED_RING_0_THRU_2, pThis->uCpl <= 2);
4744 CASE_PRED(BS3CG1PRED_RING_1_THRU_3, pThis->uCpl >= 1);
4745 CASE_PRED(BS3CG1PRED_CODE_64BIT, BS3CG1_IS_64BIT_TARGET(pThis));
4746 CASE_PRED(BS3CG1PRED_CODE_32BIT, BS3_MODE_IS_32BIT_CODE(pThis->bMode));
4747 CASE_PRED(BS3CG1PRED_CODE_16BIT, BS3_MODE_IS_16BIT_CODE(pThis->bMode));
4748 CASE_PRED(BS3CG1PRED_MODE_REAL, BS3_MODE_IS_RM_SYS(pThis->bMode));
4749 CASE_PRED(BS3CG1PRED_MODE_PROT, BS3_MODE_IS_PM_SYS(pThis->bMode));
4750 CASE_PRED(BS3CG1PRED_MODE_LONG, BS3_MODE_IS_64BIT_SYS(pThis->bMode));
4751 CASE_PRED(BS3CG1PRED_MODE_SMM, false);
4752 CASE_PRED(BS3CG1PRED_MODE_VMX, false);
4753 CASE_PRED(BS3CG1PRED_MODE_SVM, false);
4754 CASE_PRED(BS3CG1PRED_PAGING_ON, BS3_MODE_IS_PAGED(pThis->bMode));
4755 CASE_PRED(BS3CG1PRED_PAGING_OFF, !BS3_MODE_IS_PAGED(pThis->bMode));
4756 CASE_PRED(BS3CG1PRED_VENDOR_AMD, pThis->bCpuVendor == BS3CPUVENDOR_AMD);
4757 CASE_PRED(BS3CG1PRED_VENDOR_INTEL, pThis->bCpuVendor == BS3CPUVENDOR_INTEL);
4758 CASE_PRED(BS3CG1PRED_VENDOR_VIA, pThis->bCpuVendor == BS3CPUVENDOR_VIA);
4759 CASE_PRED(BS3CG1PRED_VENDOR_SHANGHAI, pThis->bCpuVendor == BS3CPUVENDOR_SHANGHAI);
4760 CASE_PRED(BS3CG1PRED_VENDOR_HYGON, pThis->bCpuVendor == BS3CPUVENDOR_HYGON);
4761
4762#undef CASE_PRED
4763 default:
4764 return Bs3TestFailedF("Invalid selector opcode %#x!", pbCode[-1]);
4765 }
4766 }
4767
4768 return true;
4769}
4770
4771
4772#ifdef BS3CG1_DEBUG_CTX_MOD
4773/**
4774 * Translates the operator into a string.
4775 *
4776 * @returns Read-only string pointer.
4777 * @param bOpcode The context modifier program opcode.
4778 */
4779static const char BS3_FAR * BS3_NEAR_CODE Bs3Cg1CtxOpToString(uint8_t bOpcode)
4780{
4781 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
4782 {
4783 case BS3CG1_CTXOP_ASSIGN: return "=";
4784 case BS3CG1_CTXOP_OR: return "|=";
4785 case BS3CG1_CTXOP_AND: return "&=";
4786 case BS3CG1_CTXOP_AND_INV: return "&~=";
4787 default: return "?WTF?";
4788 }
4789}
4790#endif
4791
4792
4793/**
4794 * Runs a context modifier program.
4795 *
4796 * @returns Success indicator (true/false).
4797 * @param pThis The state.
4798 * @param pCtx The context.
4799 * @param pHdr The program header.
4800 * @param off The program offset relative to the end of the header.
4801 * @param cb The program size.
4802 * @param pEflCtx The context to take undefined EFLAGS from. (This is NULL
4803 * if we're processing a input context modifier program.)
4804 * @param pbInstr Points to the first instruction byte. For storing
4805 * immediate operands during input context modification.
4806 * NULL for output contexts.
4807 */
4808static bool BS3_NEAR_CODE Bs3Cg1RunContextModifier(PBS3CG1STATE pThis, PBS3REGCTX pCtx, PCBS3CG1TESTHDR pHdr,
4809 unsigned off, unsigned cb,
4810 PCBS3REGCTX pEflCtx, uint8_t BS3_FAR *pbInstr)
4811{
4812 uint8_t const BS3_FAR *pbCode = (uint8_t const BS3_FAR *)(pHdr + 1) + off;
4813 int cbLeft = cb;
4814 while (cbLeft-- > 0)
4815 {
4816 /*
4817 * Decode the instruction.
4818 */
4819 uint8_t const bOpcode = *pbCode++;
4820 unsigned cbValue;
4821 unsigned cbDst;
4822 BS3CG1DST idxField;
4823 BS3PTRUNION PtrField;
4824 uint8_t BS3_FAR *pbMemCopy = NULL;
4825 bool fZxVlMax;
4826
4827 /* Expand the destiation field (can be escaped). Set fZxVlMax. */
4828 switch (bOpcode & BS3CG1_CTXOP_DST_MASK)
4829 {
4830 case BS3CG1_CTXOP_OP1:
4831 idxField = pThis->aOperands[0].idxField;
4832 if (idxField == BS3CG1DST_INVALID)
4833 idxField = BS3CG1DST_OP1;
4834 fZxVlMax = pEflCtx != NULL && pThis->aOperands[0].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
4835 break;
4836
4837 case BS3CG1_CTXOP_OP2:
4838 idxField = pThis->aOperands[1].idxField;
4839 if (idxField == BS3CG1DST_INVALID)
4840 idxField = BS3CG1DST_OP2;
4841 fZxVlMax = pEflCtx != NULL && pThis->aOperands[1].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
4842 break;
4843
4844 case BS3CG1_CTXOP_EFL:
4845 idxField = BS3CG1DST_EFL;
4846 fZxVlMax = false;
4847 break;
4848
4849 case BS3CG1_CTXOP_DST_ESC:
4850 if (cbLeft-- > 0)
4851 {
4852 idxField = (BS3CG1DST)*pbCode++;
4853 if (idxField <= BS3CG1DST_OP4)
4854 {
4855 if (idxField > BS3CG1DST_INVALID)
4856 {
4857 unsigned idxOp = idxField - BS3CG1DST_OP1;
4858 uint8_t idxField2 = pThis->aOperands[idxOp].idxField;
4859 if (idxField2 != BS3CG1DST_INVALID)
4860 idxField = idxField2;
4861 fZxVlMax = pEflCtx != NULL && pThis->aOperands[idxOp].enmLocation == BS3CG1OPLOC_CTX_ZX_VLMAX;
4862 break;
4863 }
4864 }
4865 else if (idxField < BS3CG1DST_END)
4866 {
4867 fZxVlMax = false;
4868 break;
4869 }
4870 return Bs3TestFailedF("Malformed context instruction: idxField=%d", idxField);
4871 }
4872 RT_FALL_THRU();
4873 default:
4874 return Bs3TestFailed("Malformed context instruction: Destination");
4875 }
4876
4877 /* Expand value size (can be escaped). */
4878 switch (bOpcode & BS3CG1_CTXOP_SIZE_MASK)
4879 {
4880 case BS3CG1_CTXOP_1_BYTE: cbValue = 1; break;
4881 case BS3CG1_CTXOP_2_BYTES: cbValue = 2; break;
4882 case BS3CG1_CTXOP_4_BYTES: cbValue = 4; break;
4883 case BS3CG1_CTXOP_8_BYTES: cbValue = 8; break;
4884 case BS3CG1_CTXOP_16_BYTES: cbValue = 16; break;
4885 case BS3CG1_CTXOP_32_BYTES: cbValue = 32; break;
4886 case BS3CG1_CTXOP_12_BYTES: cbValue = 12; break;
4887 case BS3CG1_CTXOP_SIZE_ESC:
4888 if (cbLeft-- > 0)
4889 {
4890 cbValue = *pbCode++;
4891 if (cbValue)
4892 break;
4893 }
4894 RT_FALL_THRU();
4895 default:
4896 return Bs3TestFailed("Malformed context instruction: size");
4897 }
4898
4899 /* Make sure there is enough instruction bytes for the value. */
4900 if (cbValue <= cbLeft)
4901 { /* likely */ }
4902 else
4903 return Bs3TestFailedF("Malformed context instruction: %u bytes value, %u bytes left", cbValue, cbLeft);
4904
4905 /*
4906 * Do value processing specific to the target field size.
4907 */
4908 cbDst = g_acbBs3Cg1DstFields[idxField];
4909 if (cbDst == BS3CG1DSTSIZE_OPERAND)
4910 cbDst = pThis->aOperands[idxField - BS3CG1DST_OP1].cbOp;
4911 else if (cbDst == BS3CG1DSTSIZE_OPERAND_SIZE_GRP)
4912 cbDst = pThis->cbOperand;
4913 if (cbDst <= 8)
4914 {
4915 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
4916
4917 /*
4918 * Deal with fields up to 8-byte wide.
4919 */
4920
4921 /* Get the value. */
4922 uint64_t uValue;
4923 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT))
4924 switch (cbValue)
4925 {
4926 case 1: uValue = *(int8_t const BS3_FAR *)pbCode; break;
4927 case 2: uValue = *(int16_t const BS3_FAR *)pbCode; break;
4928 case 4: uValue = *(int32_t const BS3_FAR *)pbCode; break;
4929 default:
4930 if (cbValue >= 8)
4931 {
4932 uValue = *(uint64_t const BS3_FAR *)pbCode;
4933 break;
4934 }
4935 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
4936 }
4937 else
4938 switch (cbValue)
4939 {
4940 case 1: uValue = *(uint8_t const BS3_FAR *)pbCode; break;
4941 case 2: uValue = *(uint16_t const BS3_FAR *)pbCode; break;
4942 case 4: uValue = *(uint32_t const BS3_FAR *)pbCode; break;
4943 default:
4944 if (cbValue >= 8)
4945 {
4946 uValue = *(uint64_t const BS3_FAR *)pbCode;
4947 break;
4948 }
4949 return Bs3TestFailedF("Malformed context instruction: %u bytes value (%u dst)", cbValue, cbDst);
4950 }
4951
4952 /* Find the field. */
4953 if (offField < sizeof(BS3REGCTX))
4954 PtrField.pu8 = (uint8_t BS3_FAR *)pCtx + offField;
4955 /* Non-register operands: */
4956 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
4957 {
4958 unsigned const idxOp = idxField - BS3CG1DST_OP1;
4959
4960 switch (pThis->aOperands[idxOp].enmLocation)
4961 {
4962 case BS3CG1OPLOC_IMM:
4963 if (pbInstr)
4964 PtrField.pu8 = &pbInstr[pThis->aOperands[idxOp].off];
4965 else
4966 return Bs3TestFailedF("Immediate operand referenced in output context!");
4967 break;
4968
4969 case BS3CG1OPLOC_MEM:
4970 if (!pbInstr)
4971 return Bs3TestFailedF("Read only operand specified in output!");
4972 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
4973 break;
4974
4975 case BS3CG1OPLOC_MEM_RW:
4976 case BS3CG1OPLOC_MEM_WO:
4977 if (pbInstr)
4978 {
4979 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
4980 pbMemCopy = pThis->MemOp.ab;
4981 }
4982 else
4983 PtrField.pu8 = pThis->MemOp.ab;
4984 break;
4985
4986 default:
4987 if (pThis->enmEncoding != pThis->enmEncodingNonInvalid)
4988 goto l_advance_to_next;
4989 return Bs3TestFailedF("Internal error: cbDst=%u idxField=%d (%d) offField=%#x: enmLocation=%u off=%#x idxField=%u",
4990 cbDst, idxField, idxOp, offField, pThis->aOperands[idxOp].enmLocation,
4991 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
4992 }
4993 }
4994 /* Special field: Copying in undefined EFLAGS from the result context. */
4995 else if (idxField == BS3CG1DST_EFL_UNDEF)
4996 {
4997 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN)
4998 return Bs3TestFailed("Invalid BS3CG1DST_EFL_UNDEF usage");
4999 PtrField.pu32 = &pCtx->rflags.u32;
5000 uValue = (*PtrField.pu32 & ~(uint32_t)uValue) | (pEflCtx->rflags.u32 & (uint32_t)uValue);
5001 }
5002 /* Special field: Expected value (in/result) exception. */
5003 else if (idxField == BS3CG1DST_VALUE_XCPT)
5004 {
5005 if (!pEflCtx || (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK) != BS3CG1_CTXOP_ASSIGN || cbDst != 1)
5006 return Bs3TestFailed("Invalid BS3CG1DST_VALUE_XCPT usage");
5007 PtrField.pu8 = &pThis->bValueXcpt;
5008 }
5009 /* FPU and FXSAVE format. */
5010 else if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
5011 && offField - sizeof(BS3REGCTX) < RT_UOFFSET_AFTER(BS3EXTCTX, Ctx.x87.aXMM[15]))
5012 {
5013 if (pThis->fWorkExtCtx)
5014 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
5015 else if (!pThis->fCpuSetupFirstResult)
5016 {
5017 BS3CG1_DPRINTF(("dbg: Extended context disabled: skipping modification (<=8)\n"));
5018 goto l_advance_to_next;
5019 }
5020 else
5021 return Bs3TestFailedF("Extended context disabled: Field %d (%s) @ %#x LB %u\n",
5022 idxField, g_aszBs3Cg1DstFields[idxField].sz, offField, cbDst);
5023 }
5024 /** @todo other FPU fields and FPU state formats. */
5025 else
5026 return Bs3TestFailedF("Todo implement me: cbDst=%u idxField=%d %s offField=%#x (<= 8)",
5027 cbDst, idxField, g_aszBs3Cg1DstFields[idxField].sz, offField);
5028
5029#ifdef BS3CG1_DEBUG_CTX_MOD
5030 switch (cbDst)
5031 {
5032 case 1:
5033 BS3CG1_DPRINTF(("dbg: modify %s: %#04RX8 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
5034 *PtrField.pu8, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
5035 break;
5036 case 2:
5037 BS3CG1_DPRINTF(("dbg: modify %s: %#06RX16 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
5038 *PtrField.pu16, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
5039 break;
5040 case 4:
5041 BS3CG1_DPRINTF(("dbg: modify %s: %#010RX32 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
5042 *PtrField.pu32, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
5043 break;
5044 default:
5045 BS3CG1_DPRINTF(("dbg: modify %s: %#018RX64 (LB %u) %s %#RX64 (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
5046 *PtrField.pu64, cbDst, Bs3Cg1CtxOpToString(bOpcode), uValue, cbValue));
5047 break;
5048 }
5049#endif
5050
5051 /* Modify the field. */
5052 switch (cbDst)
5053 {
5054 case 1:
5055 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5056 {
5057 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu8 = (uint8_t)uValue; break;
5058 case BS3CG1_CTXOP_OR: *PtrField.pu8 |= (uint8_t)uValue; break;
5059 case BS3CG1_CTXOP_AND: *PtrField.pu8 &= (uint8_t)uValue; break;
5060 case BS3CG1_CTXOP_AND_INV: *PtrField.pu8 &= ~(uint8_t)uValue; break;
5061 }
5062 break;
5063
5064 case 2:
5065 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5066 {
5067 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu16 = (uint16_t)uValue; break;
5068 case BS3CG1_CTXOP_OR: *PtrField.pu16 |= (uint16_t)uValue; break;
5069 case BS3CG1_CTXOP_AND: *PtrField.pu16 &= (uint16_t)uValue; break;
5070 case BS3CG1_CTXOP_AND_INV: *PtrField.pu16 &= ~(uint16_t)uValue; break;
5071 }
5072 break;
5073
5074 case 4:
5075 if ( (unsigned)(idxField - BS3CG1DST_XMM0_DW0_ZX) <= (unsigned)(BS3CG1DST_XMM15_DW0_ZX - BS3CG1DST_XMM0_DW0_ZX)
5076 || fZxVlMax)
5077 {
5078 PtrField.pu32[1] = 0;
5079 PtrField.pu64[1] = 0;
5080 }
5081 else if (offField <= RT_UOFFSETOF(BS3REGCTX, r15) /* Clear the top dword. */)
5082 PtrField.pu32[1] = 0;
5083 else if ((unsigned)(idxField - BS3CG1DST_MM0_LO_ZX) <= (unsigned)(BS3CG1DST_MM7_LO_ZX - BS3CG1DST_MM0_LO_ZX))
5084 {
5085 PtrField.pu32[1] = 0;
5086 PtrField.pu32[2] = 0xffff; /* observed on skylake */
5087 }
5088 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5089 {
5090 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu32 = (uint32_t)uValue; break;
5091 case BS3CG1_CTXOP_OR: *PtrField.pu32 |= (uint32_t)uValue; break;
5092 case BS3CG1_CTXOP_AND: *PtrField.pu32 &= (uint32_t)uValue; break;
5093 case BS3CG1_CTXOP_AND_INV: *PtrField.pu32 &= ~(uint32_t)uValue; break;
5094 }
5095 break;
5096
5097 case 8:
5098 if ( (unsigned)(idxField - BS3CG1DST_XMM0_LO_ZX) <= (unsigned)(BS3CG1DST_XMM15_LO_ZX - BS3CG1DST_XMM0_LO_ZX)
5099 || fZxVlMax)
5100 PtrField.pu64[1] = 0;
5101 else if ((unsigned)(idxField - BS3CG1DST_MM0) <= (unsigned)(BS3CG1DST_MM7 - BS3CG1DST_MM0))
5102 PtrField.pu32[2] = 0xffff; /* observed on skylake */
5103
5104 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5105 {
5106 case BS3CG1_CTXOP_ASSIGN: *PtrField.pu64 = (uint64_t)uValue; break;
5107 case BS3CG1_CTXOP_OR: *PtrField.pu64 |= (uint64_t)uValue; break;
5108 case BS3CG1_CTXOP_AND: *PtrField.pu64 &= (uint64_t)uValue; break;
5109 case BS3CG1_CTXOP_AND_INV: *PtrField.pu64 &= ~(uint64_t)uValue; break;
5110 }
5111 break;
5112
5113 default:
5114 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, expected 1, 2, 4, or 8", cbDst);
5115 }
5116
5117#ifdef BS3CG1_DEBUG_CTX_MOD
5118 switch (cbDst)
5119 {
5120 case 1: BS3CG1_DPRINTF(("dbg: --> %s: %#04RX8\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu8)); break;
5121 case 2: BS3CG1_DPRINTF(("dbg: --> %s: %#06RX16\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu16)); break;
5122 case 4: BS3CG1_DPRINTF(("dbg: --> %s: %#010RX32\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu32)); break;
5123 default: BS3CG1_DPRINTF(("dbg: --> %s: %#018RX64\n", g_aszBs3Cg1DstFields[idxField].sz, *PtrField.pu64)); break;
5124 }
5125#endif
5126 if (fZxVlMax)
5127 {
5128 uintptr_t iReg = ((uintptr_t)PtrField.pu8 - (uintptr_t)&pThis->pExtCtx->Ctx.x87.aXMM[0])
5129 / sizeof(pThis->pExtCtx->Ctx.x87.aXMM[0]);
5130 pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0] = 0;
5131 pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[1] = 0;
5132#ifdef BS3CG1_DEBUG_CTX_MOD
5133 BS3CG1_DPRINTF(("dbg: --> cleared YMM%u_HI\n", iReg));
5134#endif
5135 }
5136 }
5137 /*
5138 * Deal with larger field (FPU, SSE, AVX, ...).
5139 */
5140 else if (pThis->fWorkExtCtx)
5141 {
5142 union
5143 {
5144 X86FPUREG FpuReg;
5145 X86XMMREG XmmReg;
5146 X86YMMREG YmmReg;
5147 X86ZMMREG ZmmReg;
5148 uint8_t ab[sizeof(X86ZMMREG)];
5149 uint32_t au32[sizeof(X86ZMMREG) / sizeof(uint32_t)];
5150 uint64_t au64[sizeof(X86ZMMREG) / sizeof(uint64_t)];
5151 } Value;
5152 unsigned const offField = g_aoffBs3Cg1DstFields[idxField];
5153 unsigned iReg;
5154
5155 /* Copy the value into the union, doing the zero padding / extending. */
5156 Bs3MemCpy(&Value, pbCode, cbValue);
5157 if (cbValue < sizeof(Value))
5158 {
5159 if ((bOpcode & BS3CG1_CTXOP_SIGN_EXT) && (Value.ab[cbValue - 1] & 0x80))
5160 Bs3MemSet(&Value.ab[cbValue], 0xff, sizeof(Value) - cbValue);
5161 else
5162 Bs3MemSet(&Value.ab[cbValue], 0x00, sizeof(Value) - cbValue);
5163 }
5164
5165 /* Optimized access to XMM and STx registers. */
5166 if ( pThis->pExtCtx->enmMethod != BS3EXTCTXMETHOD_ANCIENT
5167 && offField - sizeof(BS3REGCTX) < RT_UOFFSET_AFTER(BS3EXTCTX, Ctx.x87.aXMM[15]) )
5168 PtrField.pb = (uint8_t *)pThis->pExtCtx + offField - sizeof(BS3REGCTX);
5169 /* Non-register operands: */
5170 else if ((unsigned)(idxField - BS3CG1DST_OP1) < 4U)
5171 {
5172 unsigned const idxOp = idxField - BS3CG1DST_OP1;
5173 switch (pThis->aOperands[idxOp].enmLocation)
5174 {
5175 case BS3CG1OPLOC_MEM:
5176 if (!pbInstr)
5177 return Bs3TestFailedF("Read only operand specified in output!");
5178 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
5179 break;
5180
5181 case BS3CG1OPLOC_MEM_RW:
5182 case BS3CG1OPLOC_MEM_WO:
5183 if (pbInstr)
5184 {
5185 PtrField.pu8 = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[idxOp].off];
5186 pbMemCopy = pThis->MemOp.ab;
5187 }
5188 else
5189 PtrField.pu8 = pThis->MemOp.ab;
5190 break;
5191
5192 default:
5193 return Bs3TestFailedF("Internal error: Field %d (%d) @ %#x LB %u: enmLocation=%u off=%#x idxField=%u",
5194 idxField, idxOp, offField, cbDst, pThis->aOperands[idxOp].enmLocation,
5195 pThis->aOperands[idxOp].off, pThis->aOperands[idxOp].idxField);
5196 }
5197 }
5198 /* The YMM (AVX) registers have split storage in the state, so they need special handling. */
5199 else if ((iReg = idxField - BS3CG1DST_YMM0) < 16U)
5200 {
5201 /* The first 128-bits in XMM land. */
5202 PtrField.pu64 = &pThis->pExtCtx->Ctx.x87.aXMM[iReg].au64[0];
5203 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5204 {
5205 case BS3CG1_CTXOP_ASSIGN:
5206 PtrField.pu64[0] = Value.au64[0];
5207 PtrField.pu64[1] = Value.au64[1];
5208 break;
5209 case BS3CG1_CTXOP_OR:
5210 PtrField.pu64[0] |= Value.au64[0];
5211 PtrField.pu64[1] |= Value.au64[1];
5212 break;
5213 case BS3CG1_CTXOP_AND:
5214 PtrField.pu64[0] &= Value.au64[0];
5215 PtrField.pu64[1] &= Value.au64[1];
5216 break;
5217 case BS3CG1_CTXOP_AND_INV:
5218 PtrField.pu64[0] &= ~Value.au64[0];
5219 PtrField.pu64[1] &= ~Value.au64[1];
5220 break;
5221 }
5222
5223 /* The second 128-bit in YMM_HI land. */
5224 PtrField.pu64 = &pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0];
5225 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5226 {
5227 case BS3CG1_CTXOP_ASSIGN:
5228 PtrField.pu64[0] = Value.au64[2];
5229 PtrField.pu64[1] = Value.au64[3];
5230 break;
5231 case BS3CG1_CTXOP_OR:
5232 PtrField.pu64[0] |= Value.au64[2];
5233 PtrField.pu64[1] |= Value.au64[3];
5234 break;
5235 case BS3CG1_CTXOP_AND:
5236 PtrField.pu64[0] &= Value.au64[2];
5237 PtrField.pu64[1] &= Value.au64[3];
5238 break;
5239 case BS3CG1_CTXOP_AND_INV:
5240 PtrField.pu64[0] &= ~Value.au64[2];
5241 PtrField.pu64[1] &= ~Value.au64[3];
5242 break;
5243 }
5244 PtrField.pb = NULL;
5245 }
5246 /* AVX512 needs handling like above, but more complicated. */
5247 else
5248 return Bs3TestFailedF("TODO: implement me: cbDst=%d idxField=%d (AVX and other weird state)", cbDst, idxField);
5249
5250 if (PtrField.pb)
5251 {
5252 /* Modify the field / memory. */
5253 unsigned i;
5254 if (cbDst & 3)
5255 return Bs3TestFailedF("Malformed context instruction: cbDst=%u, multiple of 4", cbDst);
5256
5257#ifdef BS3CG1_DEBUG_CTX_MOD
5258 BS3CG1_DPRINTF(("dbg: modify %s: %.*Rhxs (LB %u) %s %.*Rhxs (LB %u)\n", g_aszBs3Cg1DstFields[idxField].sz,
5259 cbDst, PtrField.pb, cbDst, Bs3Cg1CtxOpToString(bOpcode), cbValue, Value.ab, cbValue));
5260#endif
5261
5262 i = cbDst / 4;
5263 while (i-- > 0)
5264 {
5265 switch (bOpcode & BS3CG1_CTXOP_OPERATOR_MASK)
5266 {
5267 case BS3CG1_CTXOP_ASSIGN: PtrField.pu32[i] = Value.au32[i]; break;
5268 case BS3CG1_CTXOP_OR: PtrField.pu32[i] |= Value.au32[i]; break;
5269 case BS3CG1_CTXOP_AND: PtrField.pu32[i] &= Value.au32[i]; break;
5270 case BS3CG1_CTXOP_AND_INV: PtrField.pu32[i] &= ~Value.au32[i]; break;
5271 }
5272 }
5273
5274#ifdef BS3CG1_DEBUG_CTX_MOD
5275 BS3CG1_DPRINTF(("dbg: --> %s: %.*Rhxs\n", g_aszBs3Cg1DstFields[idxField].sz, cbDst, PtrField.pb));
5276#endif
5277
5278 if (fZxVlMax)
5279 {
5280 uintptr_t iReg = ((uintptr_t)PtrField.pu8 - (uintptr_t)&pThis->pExtCtx->Ctx.x87.aXMM[0])
5281 / sizeof(pThis->pExtCtx->Ctx.x87.aXMM[0]);
5282 if (cbDst < 16)
5283 {
5284 for (i = cbDst / 4; i < 4; i++)
5285 PtrField.pu32[i++] = 0;
5286#ifdef BS3CG1_DEBUG_CTX_MOD
5287 BS3CG1_DPRINTF(("dbg: --> cleared high %u bytes of XMM%u\n", 16 - cbDst, iReg));
5288#endif
5289 }
5290 pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0] = 0;
5291 pThis->pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[1] = 0;
5292#ifdef BS3CG1_DEBUG_CTX_MOD
5293 BS3CG1_DPRINTF(("dbg: --> cleared YMM%u_HI\n", iReg));
5294#endif
5295 }
5296 }
5297
5298 /*
5299 * Hack! Update pThis->MemOp when setting up the inputs so we can
5300 * correctly validate value and alignment exceptions.
5301 */
5302 if (pbMemCopy && PtrField.pv)
5303 Bs3MemCpy(pbMemCopy, PtrField.pv, cbDst);
5304 }
5305 /* !pThis->fWorkExtCtx: */
5306 else if (pThis->fCpuSetupFirstResult)
5307 return Bs3TestFailedF("Extended context disabled: Field %d (%s) @ %#x LB %u\n",
5308 idxField, g_aszBs3Cg1DstFields[idxField].sz, g_aoffBs3Cg1DstFields[idxField], cbDst);
5309 else
5310 BS3CG1_DPRINTF(("dbg: Extended context disabled: skipping modification [> 8]\n"));
5311
5312 /*
5313 * Advance to the next instruction.
5314 */
5315l_advance_to_next:
5316 pbCode += cbValue;
5317 cbLeft -= cbValue;
5318 }
5319
5320 return true;
5321}
5322
5323
5324/**
5325 * Checks the result of a run.
5326 *
5327 * @returns true if successful, false if not.
5328 * @param pThis The state.
5329 * @param bTestXcptExpected The exception causing the test code to stop
5330 * executing.
5331 * @param fInvalidEncodingPgFault Set if we've cut the instruction a byte
5332 * short and is expecting a \#PF on the page
5333 * boundrary rather than a \#UD. Only set if
5334 * fInvalidEncoding is also set.
5335 * @param iEncoding For error reporting.
5336 */
5337static bool BS3_NEAR_CODE Bs3Cg1CheckResult(PBS3CG1STATE pThis, uint8_t bTestXcptExpected,
5338 bool fInvalidEncodingPgFault, unsigned iEncoding)
5339{
5340 unsigned iOperand;
5341
5342 /*
5343 * Check the exception state first.
5344 */
5345 uint8_t bExpectedXcpt;
5346 uint8_t cbAdjustPc;
5347 if (!pThis->fInvalidEncoding)
5348 {
5349 bExpectedXcpt = pThis->bAlignmentXcpt;
5350 if (bExpectedXcpt == UINT8_MAX)
5351 bExpectedXcpt = pThis->bValueXcpt;
5352 if (bExpectedXcpt == UINT8_MAX)
5353 {
5354 cbAdjustPc = pThis->cbCurInstr;
5355 bExpectedXcpt = bTestXcptExpected;
5356 if (bTestXcptExpected == X86_XCPT_PF)
5357 pThis->Ctx.cr2.u = pThis->uCodePgFlat + X86_PAGE_SIZE;
5358 }
5359 else
5360 cbAdjustPc = 0;
5361 }
5362 else
5363 {
5364 cbAdjustPc = 0;
5365 if (!fInvalidEncodingPgFault)
5366 bExpectedXcpt = X86_XCPT_UD;
5367 else
5368 {
5369 bExpectedXcpt = X86_XCPT_PF;
5370 pThis->Ctx.cr2.u = pThis->uCodePgFlat + X86_PAGE_SIZE;
5371 }
5372 }
5373 if (RT_LIKELY( pThis->TrapFrame.bXcpt == bExpectedXcpt
5374 && pThis->TrapFrame.Ctx.rip.u == pThis->Ctx.rip.u + cbAdjustPc))
5375 {
5376 /*
5377 * Check the register content.
5378 */
5379 bool fOkay = Bs3TestCheckRegCtxEx(&pThis->TrapFrame.Ctx, &pThis->Ctx,
5380 cbAdjustPc, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/,
5381 pThis->pszMode, iEncoding);
5382
5383 /*
5384 * Check memory output operands.
5385 */
5386 if (!pThis->fInvalidEncoding)
5387 {
5388 iOperand = pThis->cOperands;
5389 while (iOperand-- > 0)
5390 if ( pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW
5391 || pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_WO)
5392 {
5393 if (pThis->aOperands[iOperand].off)
5394 {
5395 BS3PTRUNION PtrUnion;
5396 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
5397 switch (pThis->aOperands[iOperand].cbOp)
5398 {
5399 case 1:
5400 if (*PtrUnion.pu8 == pThis->MemOp.ab[0])
5401 continue;
5402 Bs3TestFailedF("op%u: Wrote %#04RX8, expected %#04RX8",
5403 iOperand, *PtrUnion.pu8, pThis->MemOp.ab[0]);
5404 break;
5405 case 2:
5406 if (*PtrUnion.pu16 == pThis->MemOp.au16[0])
5407 continue;
5408 Bs3TestFailedF("op%u: Wrote %#06RX16, expected %#06RX16",
5409 iOperand, *PtrUnion.pu16, pThis->MemOp.au16[0]);
5410 break;
5411 case 4:
5412 if (*PtrUnion.pu32 == pThis->MemOp.au32[0])
5413 continue;
5414 Bs3TestFailedF("op%u: Wrote %#010RX32, expected %#010RX32",
5415 iOperand, *PtrUnion.pu32, pThis->MemOp.au32[0]);
5416 break;
5417 case 8:
5418 if (*PtrUnion.pu64 == pThis->MemOp.au64[0])
5419 continue;
5420 Bs3TestFailedF("op%u: Wrote %#018RX64, expected %#018RX64",
5421 iOperand, *PtrUnion.pu64, pThis->MemOp.au64[0]);
5422 break;
5423 default:
5424 if (Bs3MemCmp(PtrUnion.pb, pThis->MemOp.ab, pThis->aOperands[iOperand].cbOp) == 0)
5425 continue;
5426 Bs3TestFailedF("op%u: Wrote %.*Rhxs, expected %.*Rhxs",
5427 iOperand,
5428 pThis->aOperands[iOperand].cbOp, PtrUnion.pb,
5429 pThis->aOperands[iOperand].cbOp, pThis->MemOp.ab);
5430 break;
5431 }
5432 }
5433 else
5434 Bs3TestFailedF("op%u: off is zero\n", iOperand);
5435 fOkay = false;
5436 }
5437 }
5438
5439 /*
5440 * Check extended context if enabled.
5441 */
5442 if (pThis->fWorkExtCtx)
5443 {
5444 PBS3EXTCTX pExpect = pThis->pExtCtx;
5445 PBS3EXTCTX pResult = pThis->pResultExtCtx;
5446 unsigned i;
5447 if ( pExpect->enmMethod == BS3EXTCTXMETHOD_XSAVE
5448 || pExpect->enmMethod == BS3EXTCTXMETHOD_FXSAVE)
5449 {
5450 /* Compare the x87 state, ASSUMING XCR0 bit 1 is set. */
5451#define CHECK_FIELD(a_Field, a_szFmt) \
5452 if (pResult->Ctx.a_Field != pExpect->Ctx.a_Field) fOkay = Bs3TestFailedF(a_szFmt, pResult->Ctx.a_Field, pExpect->Ctx.a_Field)
5453 CHECK_FIELD(x87.FCW, "FCW: %#06x, expected %#06x");
5454 CHECK_FIELD(x87.FSW, "FSW: %#06x, expected %#06x");
5455 CHECK_FIELD(x87.FTW, "FTW: %#06x, expected %#06x");
5456 //CHECK_FIELD(x87.FOP, "FOP: %#06x, expected %#06x");
5457 //CHECK_FIELD(x87.FPUIP, "FPUIP: %#010RX32, expected %#010RX32");
5458 //CHECK_FIELD(x87.CS, "FPUCS: %#06x, expected %#06x");
5459 //CHECK_FIELD(x87.Rsrvd1, "Rsrvd1: %#06x, expected %#06x");
5460 //CHECK_FIELD(x87.DP, "FPUDP: %#010RX32, expected %#010RX32");
5461 //CHECK_FIELD(x87.DS, "FPUDS: %#06x, expected %#06x");
5462 //CHECK_FIELD(x87.Rsrvd2, "Rsrvd2: %#06x, expected %#06x");
5463 CHECK_FIELD(x87.MXCSR, "MXCSR: %#010RX32, expected %#010RX32");
5464#undef CHECK_FIELD
5465 for (i = 0; i < RT_ELEMENTS(pExpect->Ctx.x87.aRegs); i++)
5466 if ( pResult->Ctx.x87.aRegs[i].au64[0] != pExpect->Ctx.x87.aRegs[i].au64[0]
5467 || pResult->Ctx.x87.aRegs[i].au16[4] != pExpect->Ctx.x87.aRegs[i].au16[4])
5468 fOkay = Bs3TestFailedF("ST[%u]: %c m=%#RX64 e=%d, expected %c m=%#RX64 e=%d", i,
5469 pResult->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
5470 pResult->Ctx.x87.aRegs[i].r80Ex.s.uMantissa,
5471 pResult->Ctx.x87.aRegs[i].r80Ex.s.uExponent,
5472 pExpect->Ctx.x87.aRegs[i].r80Ex.s.fSign ? '-' : '+',
5473 pExpect->Ctx.x87.aRegs[i].r80Ex.s.uMantissa,
5474 pExpect->Ctx.x87.aRegs[i].r80Ex.s.uExponent);
5475 for (i = 0; i < (ARCH_BITS == 64 ? 16 : 8); i++)
5476 if ( pResult->Ctx.x87.aXMM[i].au64[0] != pExpect->Ctx.x87.aXMM[i].au64[0]
5477 || pResult->Ctx.x87.aXMM[i].au64[1] != pExpect->Ctx.x87.aXMM[i].au64[1])
5478 fOkay = Bs3TestFailedF("XMM%u: %#010RX64'%016RX64, expected %#010RX64'%08RX64", i,
5479 pResult->Ctx.x87.aXMM[i].au64[1],
5480 pResult->Ctx.x87.aXMM[i].au64[0],
5481 pExpect->Ctx.x87.aXMM[i].au64[1],
5482 pExpect->Ctx.x87.aXMM[i].au64[0]);
5483 if (pExpect->fXcr0Saved & XSAVE_C_YMM)
5484 for (i = 0; i < (ARCH_BITS == 64 ? 16 : 8); i++)
5485 if ( pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[0] != pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[0]
5486 || pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[1] != pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[1])
5487 fOkay = Bs3TestFailedF("YMM%u_HI: %#010RX64'%016RX64, expected %#010RX64'%08RX64", i,
5488 pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[1],
5489 pResult->Ctx.x.u.YmmHi.aYmmHi[i].au64[0],
5490 pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[1],
5491 pExpect->Ctx.x.u.YmmHi.aYmmHi[i].au64[0]);
5492 }
5493 else
5494 fOkay = Bs3TestFailedF("Unsupported extended CPU context method: %d", pExpect->enmMethod);
5495 }
5496
5497 /*
5498 * Done.
5499 */
5500 if (fOkay)
5501 return true;
5502
5503 /*
5504 * Report failure.
5505 */
5506 Bs3TestFailedF("ins#%RU32/test#%u: encoding #%u: %.*Rhxs%s",
5507 pThis->iInstr, pThis->iTest, iEncoding, pThis->cbCurInstr, pThis->abCurInstr,
5508 fInvalidEncodingPgFault ? " (cut short)" : "");
5509 }
5510 else
5511 Bs3TestFailedF("ins#%RU32/test#%u: bXcpt=%#x expected %#x; rip=%RX64 expected %RX64; encoding#%u: %.*Rhxs%s",
5512 pThis->iInstr, pThis->iTest,
5513 pThis->TrapFrame.bXcpt, bExpectedXcpt,
5514 pThis->TrapFrame.Ctx.rip.u, pThis->Ctx.rip.u + cbAdjustPc,
5515 iEncoding, pThis->cbCurInstr, pThis->abCurInstr, fInvalidEncodingPgFault ? " (cut short)" : "");
5516 Bs3TestPrintf("cpl=%u cbOperands=%u\n", pThis->uCpl, pThis->cbOperand);
5517
5518 /*
5519 * Display memory operands.
5520 */
5521 for (iOperand = 0; iOperand < pThis->cOperands; iOperand++)
5522 {
5523 BS3PTRUNION PtrUnion;
5524 switch (pThis->aOperands[iOperand].enmLocation)
5525 {
5526 case BS3CG1OPLOC_CTX:
5527 {
5528 uint8_t idxField = pThis->aOperands[iOperand].idxField;
5529 unsigned offField = g_aoffBs3Cg1DstFields[idxField];
5530 if (offField <= sizeof(BS3REGCTX))
5531 PtrUnion.pb = (uint8_t BS3_FAR *)&pThis->Ctx + offField;
5532 else
5533 {
5534 Bs3TestPrintf("op%u: ctx%u: xxxx\n", iOperand, pThis->aOperands[iOperand].cbOp * 8);
5535 break;
5536 }
5537 switch (pThis->aOperands[iOperand].cbOp)
5538 {
5539 case 1: Bs3TestPrintf("op%u: ctx08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
5540 case 2: Bs3TestPrintf("op%u: ctx16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
5541 case 4: Bs3TestPrintf("op%u: ctx32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
5542 case 8: Bs3TestPrintf("op%u: ctx64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
5543 default:
5544 Bs3TestPrintf("op%u: ctx%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
5545 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
5546 break;
5547 }
5548 break;
5549 }
5550
5551 case BS3CG1OPLOC_IMM:
5552 PtrUnion.pb = &pThis->pbCodePg[pThis->aOperands[iOperand].off];
5553 switch (pThis->aOperands[iOperand].cbOp)
5554 {
5555 case 1: Bs3TestPrintf("op%u: imm08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
5556 case 2: Bs3TestPrintf("op%u: imm16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
5557 case 4: Bs3TestPrintf("op%u: imm32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
5558 case 8: Bs3TestPrintf("op%u: imm64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
5559 default:
5560 Bs3TestPrintf("op%u: imm%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
5561 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
5562 break;
5563 }
5564 break;
5565
5566 case BS3CG1OPLOC_MEM:
5567 case BS3CG1OPLOC_MEM_RW:
5568 case BS3CG1OPLOC_MEM_WO:
5569 if (pThis->aOperands[iOperand].off)
5570 {
5571 PtrUnion.pb = &pThis->pbDataPg[X86_PAGE_SIZE - pThis->aOperands[iOperand].off];
5572 switch (pThis->aOperands[iOperand].cbOp)
5573 {
5574 case 1: Bs3TestPrintf("op%u: result mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
5575 case 2: Bs3TestPrintf("op%u: result mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
5576 case 4: Bs3TestPrintf("op%u: result mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
5577 case 8: Bs3TestPrintf("op%u: result mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
5578 default:
5579 Bs3TestPrintf("op%u: result mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
5580 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
5581 break;
5582 }
5583 if ( pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_WO
5584 || pThis->aOperands[iOperand].enmLocation == BS3CG1OPLOC_MEM_RW)
5585 {
5586 PtrUnion.pb = pThis->MemOp.ab;
5587 switch (pThis->aOperands[iOperand].cbOp)
5588 {
5589 case 1: Bs3TestPrintf("op%u: expect mem08: %#04RX8\n", iOperand, *PtrUnion.pu8); break;
5590 case 2: Bs3TestPrintf("op%u: expect mem16: %#06RX16\n", iOperand, *PtrUnion.pu16); break;
5591 case 4: Bs3TestPrintf("op%u: expect mem32: %#010RX32\n", iOperand, *PtrUnion.pu32); break;
5592 case 8: Bs3TestPrintf("op%u: expect mem64: %#018RX64\n", iOperand, *PtrUnion.pu64); break;
5593 default:
5594 Bs3TestPrintf("op%u: expect mem%u: %.*Rhxs\n", iOperand, pThis->aOperands[iOperand].cbOp * 8,
5595 pThis->aOperands[iOperand].cbOp, PtrUnion.pb);
5596 break;
5597 }
5598 }
5599 }
5600 else
5601 Bs3TestPrintf("op%u: mem%u: zero off value!!\n", iOperand, pThis->aOperands[iOperand].cbOp * 8);
5602 break;
5603 }
5604 }
5605
5606 /*
5607 * Display contexts.
5608 */
5609 Bs3TestPrintf("-- Expected context:\n");
5610 Bs3RegCtxPrint(&pThis->Ctx);
5611 if (pThis->fWorkExtCtx)
5612 Bs3TestPrintf("xcr0=%RX64\n", pThis->pExtCtx->fXcr0Saved);
5613 Bs3TestPrintf("-- Actual context:\n");
5614 Bs3TrapPrintFrame(&pThis->TrapFrame);
5615 if (pThis->fWorkExtCtx)
5616 Bs3TestPrintf("xcr0=%RX64\n", pThis->pResultExtCtx->fXcr0Saved);
5617 Bs3TestPrintf("\n");
5618 return false;
5619}
5620
5621
5622/**
5623 * Destroys the state, freeing all allocations and such.
5624 *
5625 * @param pThis The state.
5626 */
5627static void BS3_NEAR_CODE Bs3Cg1Destroy(PBS3CG1STATE pThis)
5628{
5629 if (BS3_MODE_IS_PAGED(pThis->bMode))
5630 {
5631#if ARCH_BITS != 16
5632 Bs3MemGuardedTestPageFree(pThis->pbCodePg);
5633 Bs3MemGuardedTestPageFree(pThis->pbDataPg);
5634#endif
5635 }
5636 else
5637 {
5638 Bs3MemFree(pThis->pbCodePg, X86_PAGE_SIZE);
5639 Bs3MemFree(pThis->pbDataPg, X86_PAGE_SIZE);
5640 }
5641
5642 if (pThis->pExtCtx)
5643 Bs3MemFree(pThis->pExtCtx, pThis->pExtCtx->cb * 3);
5644
5645 pThis->pbCodePg = NULL;
5646 pThis->pbDataPg = NULL;
5647 pThis->pExtCtx = NULL;
5648 pThis->pResultExtCtx = NULL;
5649 pThis->pInitialExtCtx = NULL;
5650
5651 Bs3TestSubDone();
5652}
5653
5654
5655/**
5656 * Initializes the state.
5657 *
5658 * @returns Success indicator (true/false)
5659 * @param pThis The state.
5660 * @param bMode The mode being tested.
5661 */
5662bool BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1Init)(PBS3CG1STATE pThis, uint8_t bMode)
5663{
5664 BS3MEMKIND const enmMemKind = BS3_MODE_IS_RM_OR_V86(bMode) ? BS3MEMKIND_REAL
5665 : !BS3_MODE_IS_64BIT_CODE(bMode) ? BS3MEMKIND_TILED : BS3MEMKIND_FLAT32;
5666 unsigned iRing;
5667 unsigned cb;
5668 unsigned i;
5669 uint64_t fFlags;
5670 PBS3EXTCTX pExtCtx;
5671
5672 Bs3MemSet(pThis, 0, sizeof(*pThis));
5673
5674 pThis->iFirstRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
5675 pThis->iEndRing = BS3_MODE_IS_RM_SYS(bMode) ? 1 : 4;
5676 pThis->bMode = bMode;
5677 pThis->pszMode = Bs3GetModeName(bMode);
5678 pThis->pszModeShort = Bs3GetModeNameShortLower(bMode);
5679 pThis->bCpuVendor = Bs3GetCpuVendor();
5680 pThis->pchMnemonic = g_achBs3Cg1Mnemonics;
5681 pThis->pabOperands = g_abBs3Cg1Operands;
5682 pThis->pabOpcodes = g_abBs3Cg1Opcodes;
5683 pThis->fAdvanceMnemonic = 1;
5684
5685 /* Start the mode sub-test before we start reporting errors against it. */
5686 Bs3TestSub(pThis->pszModeShort);
5687
5688 /* Allocate extended context structures. */
5689 cb = Bs3ExtCtxGetSize(&fFlags);
5690 pExtCtx = Bs3MemAlloc(BS3MEMKIND_TILED, cb * 3);
5691 if (!pExtCtx)
5692 return Bs3TestFailedF("Bs3MemAlloc(tiled,%#x)", cb * 3);
5693 pThis->pExtCtx = pExtCtx;
5694 pThis->pResultExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb);
5695 pThis->pInitialExtCtx = (PBS3EXTCTX)((uint8_t BS3_FAR *)pExtCtx + cb + cb);
5696
5697 Bs3ExtCtxInit(pThis->pExtCtx, cb, fFlags);
5698 Bs3ExtCtxInit(pThis->pResultExtCtx, cb, fFlags);
5699 Bs3ExtCtxInit(pThis->pInitialExtCtx, cb, fFlags);
5700 //Bs3TestPrintf("fCR0=%RX64 cbExtCtx=%#x method=%d\n", fFlags, cb, pExtCtx->enmMethod);
5701
5702 /* Allocate guarded exectuable and data memory. */
5703 if (BS3_MODE_IS_PAGED(bMode))
5704 {
5705#if ARCH_BITS != 16
5706 pThis->pbCodePg = Bs3MemGuardedTestPageAlloc(enmMemKind);
5707 pThis->pbDataPg = Bs3MemGuardedTestPageAlloc(enmMemKind);
5708 if (!pThis->pbCodePg || !pThis->pbDataPg)
5709 {
5710 Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
5711 Bs3MemPrintInfo();
5712 Bs3Shutdown();
5713 return Bs3TestFailedF("Bs3MemGuardedTestPageAlloc(%d) failed", enmMemKind);
5714 }
5715 if ( BS3_MODE_IS_64BIT_CODE(bMode)
5716 && (uintptr_t)pThis->pbDataPg >= _2G)
5717 return Bs3TestFailedF("pbDataPg=%p is above 2GB and not simple to address from 64-bit code", pThis->pbDataPg);
5718#else
5719 return Bs3TestFailed("WTF?! #1");
5720#endif
5721 }
5722 else
5723 {
5724 pThis->pbCodePg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
5725 pThis->pbDataPg = Bs3MemAlloc(enmMemKind, X86_PAGE_SIZE);
5726 if (!pThis->pbCodePg || !pThis->pbDataPg)
5727 {
5728 Bs3MemPrintInfo();
5729 return Bs3TestFailedF("Bs3MemAlloc(%d,Pg) failed", enmMemKind);
5730 }
5731 }
5732 pThis->uCodePgFlat = Bs3SelPtrToFlat(pThis->pbCodePg);
5733 pThis->uDataPgFlat = Bs3SelPtrToFlat(pThis->pbDataPg);
5734#if ARCH_BITS == 16
5735 pThis->CodePgFar.sel = BS3_FP_SEG(pThis->pbCodePg);
5736 pThis->CodePgFar.off = BS3_FP_OFF(pThis->pbCodePg);
5737 pThis->CodePgRip = BS3_FP_OFF(pThis->pbCodePg);
5738 pThis->DataPgFar.sel = BS3_FP_SEG(pThis->pbDataPg);
5739 pThis->DataPgFar.off = BS3_FP_OFF(pThis->pbDataPg);
5740#else
5741 if (BS3_MODE_IS_RM_OR_V86(bMode))
5742 {
5743 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToRealMode(pThis->uDataPgFlat);
5744 ASMCompilerBarrier();
5745 pThis->CodePgFar.off = 0;
5746 pThis->CodePgFar.sel = pThis->uCodePgFlat >> 4;
5747 pThis->CodePgRip = pThis->CodePgFar.off;
5748 }
5749 else if (BS3_MODE_IS_16BIT_CODE(bMode))
5750 {
5751 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
5752 ASMCompilerBarrier();
5753 pThis->CodePgFar.sel = BS3_SEL_SPARE_00;
5754 pThis->CodePgFar.off = 0;
5755 pThis->CodePgRip = 0;
5756 }
5757 else if (BS3_MODE_IS_32BIT_CODE(bMode))
5758 {
5759 *(uint32_t *)&pThis->DataPgFar = Bs3SelFlatDataToProtFar16(pThis->uDataPgFlat);
5760 ASMCompilerBarrier();
5761 pThis->CodePgFar.sel = 0;
5762 pThis->CodePgFar.off = 0;
5763 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
5764 }
5765 else
5766 {
5767 pThis->DataPgFar.off = 0;
5768 pThis->DataPgFar.sel = 0;
5769 pThis->CodePgFar.off = 0;
5770 pThis->CodePgFar.sel = 0;
5771 pThis->CodePgRip = (uintptr_t)pThis->pbCodePg;
5772 }
5773#endif
5774 BS3CG1_DPRINTF(("pbDataPg=%p %04x:%04x pbCodePg=%p %04x:%04x\n",
5775 pThis->pbDataPg, pThis->DataPgFar.sel, pThis->DataPgFar.off,
5776 pThis->pbCodePg, pThis->CodePgFar.sel, pThis->CodePgFar.off));
5777
5778 /*
5779 * Create basic context for each target ring.
5780 *
5781 * In protected 16-bit code we need set up code selectors that can access
5782 * pbCodePg.
5783 *
5784 * In long mode we make sure the high 32-bits of GPRs (sans RSP) have some
5785 * bits set so we can check that the implicit clearing is tested.
5786 */
5787 Bs3RegCtxSaveEx(&pThis->aInitialCtxs[pThis->iFirstRing], bMode, 1024 * 3);
5788#if ARCH_BITS == 64
5789 pThis->aInitialCtxs[pThis->iFirstRing].rax.u |= UINT64_C(0x0101010100000000);
5790 pThis->aInitialCtxs[pThis->iFirstRing].rbx.u |= UINT64_C(0x0202020200000000);
5791 pThis->aInitialCtxs[pThis->iFirstRing].rcx.u |= UINT64_C(0x0303030300000000);
5792 pThis->aInitialCtxs[pThis->iFirstRing].rdx.u |= UINT64_C(0x0404040400000000);
5793 pThis->aInitialCtxs[pThis->iFirstRing].rbp.u |= UINT64_C(0x0505050500000000);
5794 pThis->aInitialCtxs[pThis->iFirstRing].rdi.u |= UINT64_C(0x0606060600000000);
5795 pThis->aInitialCtxs[pThis->iFirstRing].rsi.u |= UINT64_C(0x0707070700000000);
5796 pThis->aInitialCtxs[pThis->iFirstRing].r8.u |= UINT64_C(0x0808080800000000);
5797 pThis->aInitialCtxs[pThis->iFirstRing].r9.u |= UINT64_C(0x0909090900000000);
5798 pThis->aInitialCtxs[pThis->iFirstRing].r10.u |= UINT64_C(0x1010101000000000);
5799 pThis->aInitialCtxs[pThis->iFirstRing].r11.u |= UINT64_C(0x1111111100000000);
5800 pThis->aInitialCtxs[pThis->iFirstRing].r12.u |= UINT64_C(0x1212121200000000);
5801 pThis->aInitialCtxs[pThis->iFirstRing].r13.u |= UINT64_C(0x1313131300000000);
5802 pThis->aInitialCtxs[pThis->iFirstRing].r14.u |= UINT64_C(0x1414141400000000);
5803 pThis->aInitialCtxs[pThis->iFirstRing].r15.u |= UINT64_C(0x1515151500000000);
5804#endif
5805
5806 if (BS3_MODE_IS_RM_OR_V86(bMode))
5807 {
5808 pThis->aInitialCtxs[pThis->iFirstRing].cs = pThis->CodePgFar.sel;
5809 BS3_ASSERT(pThis->iFirstRing + 1 == pThis->iEndRing);
5810 }
5811 else if (BS3_MODE_IS_16BIT_CODE(bMode))
5812 {
5813#if ARCH_BITS == 16
5814 uintptr_t const uFlatCodePgSeg = Bs3SelPtrToFlat(BS3_FP_MAKE(BS3_FP_SEG(pThis->pbCodePg), 0));
5815#else
5816 uintptr_t const uFlatCodePgSeg = (uintptr_t)pThis->pbCodePg;
5817#endif
5818 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
5819 {
5820 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
5821 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
5822 }
5823 for (iRing = pThis->iFirstRing; iRing < pThis->iEndRing; iRing++)
5824 {
5825 pThis->aInitialCtxs[iRing].cs = BS3_SEL_SPARE_00 + iRing * 8 + iRing;
5826 Bs3SelSetup16BitCode(&Bs3GdteSpare00 + iRing, uFlatCodePgSeg, iRing);
5827 }
5828 }
5829 else
5830 {
5831 Bs3RegCtxSetRipCsFromCurPtr(&pThis->aInitialCtxs[pThis->iFirstRing], (FPFNBS3FAR)pThis->pbCodePg);
5832 for (iRing = pThis->iFirstRing + 1; iRing < pThis->iEndRing; iRing++)
5833 {
5834 Bs3MemCpy(&pThis->aInitialCtxs[iRing], &pThis->aInitialCtxs[pThis->iFirstRing], sizeof(pThis->aInitialCtxs[iRing]));
5835 Bs3RegCtxConvertToRingX(&pThis->aInitialCtxs[iRing], iRing);
5836 }
5837 }
5838
5839 /*
5840 * Create an initial extended CPU context.
5841 */
5842 pExtCtx = pThis->pInitialExtCtx;
5843 if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE
5844 || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE)
5845 {
5846 pExtCtx->Ctx.x87.FCW = X86_FCW_MASK_ALL | X86_FCW_PC_64 | X86_FCW_RC_NEAREST;
5847 pExtCtx->Ctx.x87.FSW = 0;
5848 pExtCtx->Ctx.x87.MXCSR = X86_MXCSR_IM | X86_MXCSR_DM | X86_MXCSR_RC_NEAREST;
5849 pExtCtx->Ctx.x87.MXCSR_MASK = 0;
5850 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aRegs); i++)
5851 {
5852 pExtCtx->Ctx.x87.aRegs[i].au16[0] = i << 4;
5853 pExtCtx->Ctx.x87.aRegs[i].au16[1] = i << 4;
5854 pExtCtx->Ctx.x87.aRegs[i].au16[2] = i << 4;
5855 pExtCtx->Ctx.x87.aRegs[i].au16[3] = i << 4;
5856 }
5857 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM); i++)
5858 {
5859 pExtCtx->Ctx.x87.aXMM[i].au16[0] = i | UINT16_C(0x8f00);
5860 pExtCtx->Ctx.x87.aXMM[i].au16[1] = i | UINT16_C(0x8e00);
5861 pExtCtx->Ctx.x87.aXMM[i].au16[2] = i | UINT16_C(0x8d00);
5862 pExtCtx->Ctx.x87.aXMM[i].au16[3] = i | UINT16_C(0x8c00);
5863 pExtCtx->Ctx.x87.aXMM[i].au16[4] = i | UINT16_C(0x8b00);
5864 pExtCtx->Ctx.x87.aXMM[i].au16[5] = i | UINT16_C(0x8a00);
5865 pExtCtx->Ctx.x87.aXMM[i].au16[6] = i | UINT16_C(0x8900);
5866 pExtCtx->Ctx.x87.aXMM[i].au16[7] = i | UINT16_C(0x8800);
5867 }
5868 if (pExtCtx->fXcr0Nominal & XSAVE_C_YMM)
5869 for (i = 0; i < RT_ELEMENTS(pExtCtx->Ctx.x.u.YmmHi.aYmmHi); i++)
5870 {
5871 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[0] = (i << 8) | (i << 12) | 0xff;
5872 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[1] = (i << 8) | (i << 12) | 0xfe;
5873 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[2] = (i << 8) | (i << 12) | 0xfd;
5874 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[3] = (i << 8) | (i << 12) | 0xfc;
5875 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[4] = (i << 8) | (i << 12) | 0xfb;
5876 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[5] = (i << 8) | (i << 12) | 0xfa;
5877 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[6] = (i << 8) | (i << 12) | 0xf9;
5878 pExtCtx->Ctx.x.u.YmmHi.aYmmHi[i].au16[7] = (i << 8) | (i << 12) | 0xf8;
5879 }
5880
5881 }
5882 //else if (pExtCtx->enmMethod == BS3EXTCTXMETHOD_ANCIENT)
5883 else
5884 return Bs3TestFailedF("Unsupported extended CPU context method: %d", pExtCtx->enmMethod);
5885
5886 return true;
5887}
5888
5889
5890static uint8_t BS3_NEAR_CODE BS3_CMN_NM(Bs3Cg1WorkerInner)(PBS3CG1STATE pThis)
5891{
5892 uint8_t iRing;
5893 unsigned iInstr;
5894
5895 /*
5896 * Test the instructions.
5897 */
5898 for (iInstr = 0; iInstr < g_cBs3Cg1Instructions;
5899 iInstr++,
5900 pThis->pchMnemonic += pThis->fAdvanceMnemonic * pThis->cchMnemonic,
5901 pThis->pabOperands += pThis->cOperands,
5902 pThis->pabOpcodes += pThis->cbOpcodes)
5903 {
5904 uint8_t const bTestXcptExpected = BS3_MODE_IS_PAGED(pThis->bMode) ? X86_XCPT_PF : X86_XCPT_UD;
5905 bool fOuterInvalidInstr = false;
5906 unsigned iCpuSetup;
5907
5908 /*
5909 * Expand the instruction information into the state.
5910 * Note! 16-bit will switch to a two level test header lookup once we exceed 64KB.
5911 */
5912 PCBS3CG1INSTR pInstr = &g_aBs3Cg1Instructions[iInstr];
5913 pThis->iInstr = iInstr;
5914 pThis->pTestHdr = (PCBS3CG1TESTHDR)&g_abBs3Cg1Tests[pInstr->offTests];
5915 pThis->fFlags = pInstr->fFlags;
5916 pThis->enmEncoding = (BS3CG1ENC)pInstr->enmEncoding;
5917 pThis->enmEncodingNonInvalid = (BS3CG1ENC)pInstr->enmEncoding;
5918 pThis->enmCpuTest = (BS3CG1CPU)pInstr->enmCpuTest;
5919 pThis->enmPrefixKind = (BS3CG1PFXKIND)pInstr->enmPrefixKind;
5920 pThis->enmXcptType = (BS3CG1XCPTTYPE)pInstr->enmXcptType;
5921 pThis->cchMnemonic = pInstr->cchMnemonic;
5922 if (pThis->fAdvanceMnemonic)
5923 Bs3TestSubSubF("%.*s", pThis->cchMnemonic, pThis->pchMnemonic);
5924 pThis->fAdvanceMnemonic = pInstr->fAdvanceMnemonic;
5925 pThis->uOpcodeMap = pInstr->uOpcodeMap;
5926 pThis->cOperands = pInstr->cOperands;
5927 pThis->cbOpcodes = pInstr->cbOpcodes;
5928 switch (pThis->cOperands)
5929 {
5930 case 4: pThis->aenmOperands[3] = (BS3CG1OP)pThis->pabOperands[3];
5931 case 3: pThis->aenmOperands[2] = (BS3CG1OP)pThis->pabOperands[2];
5932 case 2: pThis->aenmOperands[1] = (BS3CG1OP)pThis->pabOperands[1];
5933 case 1: pThis->aenmOperands[0] = (BS3CG1OP)pThis->pabOperands[0];
5934 }
5935 switch (pThis->cbOpcodes)
5936 {
5937 case 4: pThis->abOpcodes[3] = pThis->pabOpcodes[3];
5938 case 3: pThis->abOpcodes[2] = pThis->pabOpcodes[2];
5939 case 2: pThis->abOpcodes[1] = pThis->pabOpcodes[1];
5940 case 1: pThis->abOpcodes[0] = pThis->pabOpcodes[0];
5941 }
5942
5943 /*
5944 * Check if the CPU supports the instruction.
5945 */
5946 pThis->fCpuSetupFirstResult = Bs3Cg1CpuSetupFirst(pThis);
5947 if ( !pThis->fCpuSetupFirstResult
5948 || (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID)))
5949 fOuterInvalidInstr = true;
5950
5951 /* Switch the encoder for some of the invalid instructions on non-intel CPUs. */
5952 if ( (pThis->fFlags & BS3CG1INSTR_F_INTEL_DECODES_INVALID)
5953 && pThis->bCpuVendor != BS3CPUVENDOR_INTEL
5954 && ( (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID))
5955 || (BS3CG1_IS_64BIT_TARGET(pThis) && (pThis->fFlags & BS3CG1INSTR_F_INVALID_64BIT))
5956 || fOuterInvalidInstr ) )
5957 pThis->enmEncoding = Bs3Cg1CalcNoneIntelInvalidEncoding(pThis->enmEncoding);
5958
5959 for (iCpuSetup = 0;; iCpuSetup++)
5960 {
5961 unsigned iEncoding;
5962 unsigned iEncodingNext;
5963
5964 /*
5965 * Prep the operands and encoding handling.
5966 */
5967 Bs3Cg1SetOpSizes(pThis, pThis->bMode);
5968 if (!Bs3Cg1EncodePrep(pThis))
5969 break;
5970
5971 /*
5972 * Encode the instruction in various ways and check out the test values.
5973 */
5974 for (iEncoding = 0;; iEncoding = iEncodingNext)
5975 {
5976 /*
5977 * Encode the next instruction variation.
5978 */
5979 pThis->fInvalidEncoding = fOuterInvalidInstr;
5980 iEncodingNext = Bs3Cg1EncodeNext(pThis, iEncoding);
5981 if (iEncodingNext <= iEncoding)
5982 break;
5983 BS3CG1_DPRINTF(("\ndbg: Encoding #%u: cbCurInst=%u: %.*Rhxs fInvalidEncoding=%d\n",
5984 iEncoding, pThis->cbCurInstr, pThis->cbCurInstr, pThis->abCurInstr, pThis->fInvalidEncoding));
5985
5986 /*
5987 * Do the rings.
5988 */
5989 for (iRing = pThis->iFirstRing + pThis->fSameRingNotOkay; iRing < pThis->iEndRing; iRing++)
5990 {
5991 PCBS3CG1TESTHDR pHdr;
5992
5993 pThis->uCpl = iRing;
5994 BS3CG1_DPRINTF(("dbg: Ring %u\n", iRing));
5995
5996 /*
5997 * Do the tests one by one.
5998 */
5999 pHdr = pThis->pTestHdr;
6000 for (pThis->iTest = 0;; pThis->iTest++)
6001 {
6002 if (Bs3Cg1RunSelector(pThis, pHdr))
6003 {
6004 /* Okay, set up the execution context. */
6005 unsigned offCode;
6006 uint8_t BS3_FAR *pbCode;
6007
6008 Bs3MemCpy(&pThis->Ctx, &pThis->aInitialCtxs[iRing], sizeof(pThis->Ctx));
6009 if (pThis->fWorkExtCtx)
6010 Bs3ExtCtxCopy(pThis->pExtCtx, pThis->pInitialExtCtx);
6011 if (BS3_MODE_IS_PAGED(pThis->bMode))
6012 {
6013 offCode = X86_PAGE_SIZE - pThis->cbCurInstr;
6014 pbCode = &pThis->pbCodePg[offCode];
6015 //if (iEncoding > 0) { pbCode[-1] = 0xf4; offCode--; }
6016 }
6017 else
6018 {
6019 pbCode = pThis->pbCodePg;
6020 pbCode[pThis->cbCurInstr] = 0x0f; /* UD2 */
6021 pbCode[pThis->cbCurInstr + 1] = 0x0b;
6022 offCode = 0;
6023 }
6024 pThis->Ctx.rip.u = pThis->CodePgRip + offCode;
6025 Bs3MemCpy(pbCode, pThis->abCurInstr, pThis->cbCurInstr);
6026
6027 if (Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr, pHdr->cbSelector, pHdr->cbInput, NULL, pbCode))
6028 {
6029 /* Run the instruction. */
6030 BS3CG1_DPRINTF(("dbg: Running test #%u\n", pThis->iTest));
6031 //Bs3RegCtxPrint(&pThis->Ctx);
6032 if (pThis->fWorkExtCtx)
6033 Bs3ExtCtxRestore(pThis->pExtCtx);
6034 Bs3TrapSetJmpAndRestore(&pThis->Ctx, &pThis->TrapFrame);
6035 if (pThis->fWorkExtCtx)
6036 Bs3ExtCtxSave(pThis->pResultExtCtx);
6037 BS3CG1_DPRINTF(("dbg: bXcpt=%#x rip=%RX64 -> %RX64\n",
6038 pThis->TrapFrame.bXcpt, pThis->Ctx.rip.u, pThis->TrapFrame.Ctx.rip.u));
6039
6040 /*
6041 * Apply the output modification program to the context.
6042 */
6043 pThis->Ctx.rflags.u32 &= ~X86_EFL_RF;
6044 pThis->Ctx.rflags.u32 |= pThis->TrapFrame.Ctx.rflags.u32 & X86_EFL_RF;
6045 pThis->bValueXcpt = UINT8_MAX; //???
6046 if ( pThis->fInvalidEncoding
6047 || pThis->bAlignmentXcpt != UINT8_MAX
6048 || pThis->bValueXcpt != UINT8_MAX
6049 || Bs3Cg1RunContextModifier(pThis, &pThis->Ctx, pHdr,
6050 pHdr->cbSelector + pHdr->cbInput, pHdr->cbOutput,
6051 &pThis->TrapFrame.Ctx, NULL /*pbCode*/))
6052 Bs3Cg1CheckResult(pThis, bTestXcptExpected, false /*fInvalidEncodingPgFault*/, iEncoding);
6053 else
6054 {
6055 Bs3TestPrintf("Bs3Cg1RunContextModifier(out): iEncoding=%u iTest=%RU32 iInstr=%u %.*s\n",
6056 iEncoding, pThis->iTest, pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic);
6057 ASMHalt();
6058 }
6059
6060 /*
6061 * If this is an invalid encoding or instruction, check that we
6062 * get a page fault when shortening it by one byte.
6063 * (Since we didn't execute the output context modifier, we don't
6064 * need to re-initialize the start context.)
6065 */
6066 if ( pThis->fInvalidEncoding
6067 && BS3_MODE_IS_PAGED(pThis->bMode)
6068 && pThis->cbCurInstr)
6069 {
6070 pbCode += 1;
6071 offCode += 1;
6072 pThis->Ctx.rip.u = pThis->CodePgRip + offCode;
6073 Bs3MemCpy(pbCode, pThis->abCurInstr, pThis->cbCurInstr - 1);
6074
6075 /* Run the instruction. */
6076 BS3CG1_DPRINTF(("dbg: Running test #%u (cut short #PF)\n", pThis->iTest));
6077 //Bs3RegCtxPrint(&pThis->Ctx);
6078 if (pThis->fWorkExtCtx)
6079 Bs3ExtCtxRestore(pThis->pExtCtx);
6080 Bs3TrapSetJmpAndRestore(&pThis->Ctx, &pThis->TrapFrame);
6081 if (pThis->fWorkExtCtx)
6082 Bs3ExtCtxSave(pThis->pResultExtCtx);
6083 BS3CG1_DPRINTF(("dbg: bXcpt=%#x rip=%RX64 -> %RX64 (cut short #PF)\n",
6084 pThis->TrapFrame.bXcpt, pThis->Ctx.rip.u, pThis->TrapFrame.Ctx.rip.u));
6085
6086 /* Check it */
6087 pThis->Ctx.rflags.u32 &= ~X86_EFL_RF;
6088 pThis->Ctx.rflags.u32 |= pThis->TrapFrame.Ctx.rflags.u32 & X86_EFL_RF;
6089 Bs3Cg1CheckResult(pThis, X86_XCPT_PF, true /*fInvalidEncodingPgFault*/, iEncoding);
6090 }
6091 }
6092 else
6093 {
6094 Bs3TestPrintf("Bs3Cg1RunContextModifier(in): iEncoding=%u iTest=%u iInstr=%RU32 %.*s\n",
6095 iEncoding, pThis->iTest, pThis->iInstr, pThis->cchMnemonic, pThis->pchMnemonic);
6096 ASMHalt();
6097 }
6098 }
6099 else
6100 BS3CG1_DPRINTF(("dbg: Skipping #%u\n", pThis->iTest));
6101
6102 /* advance */
6103 if (pHdr->fLast)
6104 {
6105 BS3CG1_DPRINTF(("dbg: Last\n\n"));
6106 break;
6107 }
6108 pHdr = (PCBS3CG1TESTHDR)((uint8_t BS3_FAR *)(pHdr + 1) + pHdr->cbInput + pHdr->cbOutput + pHdr->cbSelector);
6109 }
6110 }
6111 }
6112
6113 /*
6114 * Clean up (segment registers, etc) and get the next CPU config.
6115 */
6116 Bs3Cg1EncodeCleanup(pThis);
6117 if (!Bs3Cg1CpuSetupNext(pThis, iCpuSetup, &fOuterInvalidInstr))
6118 break;
6119 if (pThis->fFlags & (BS3CG1INSTR_F_UNUSED | BS3CG1INSTR_F_INVALID))
6120 fOuterInvalidInstr = true;
6121 }
6122 }
6123
6124 return 0;
6125}
6126
6127
6128BS3_DECL_FAR(uint8_t) BS3_CMN_NM(Bs3Cg1Worker)(uint8_t bMode)
6129{
6130 uint8_t bRet = 1;
6131 BS3CG1STATE This;
6132
6133#if 0
6134 /* (for debugging) */
6135 if (bMode != BS3_MODE_LM64)
6136 return BS3TESTDOMODE_SKIPPED;
6137#endif
6138
6139 if (BS3_CMN_NM(Bs3Cg1Init)(&This, bMode))
6140 bRet = BS3_CMN_NM(Bs3Cg1WorkerInner)(&This);
6141 Bs3Cg1Destroy(&This);
6142
6143#if 0
6144 /* (for debugging) */
6145 if (bMode == BS3_MODE_PPV86)
6146 {
6147 Bs3TestTerm();
6148 Bs3Shutdown();
6149 }
6150#endif
6151 return bRet;
6152}
6153
Note: See TracBrowser for help on using the repository browser.

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