VirtualBox

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

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