VirtualBox

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

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

IEM: Some VEX related regression fixes and cleanups.

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

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