VirtualBox

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

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

IEM: Implemented vmovapd Vpd,Wpd (VEX.66.28).

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