VirtualBox

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

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

IEM: Documented movd Ed,Vd and mov Eq,Vq (0x66 0x0f 0x7e).

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

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