VirtualBox

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

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

bs3-cpu-generated-1: Mark write-only memory as such, for what it's worth...

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

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