VirtualBox

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

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

IEM: Implemented vmovntps Mps,Vps (VEX.0F 2b) and vmovntpd Mpd,Vpd (VEX.66.0F 2b).

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