VirtualBox

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

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

bs3-cpu-generated-1: cleanups

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