VirtualBox

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

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

IEM,bs3-cpu-generated-1: Made the current testcases pass on AMD.

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

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