VirtualBox

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

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

IEM: More tests for vmovups.

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