VirtualBox

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

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

IEM: clearly mark operands that are written to.

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