VirtualBox

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

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

IEM: More vstmxcsr work.

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

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