VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-instr-2-template.c@ 103615

最後變更 在這個檔案從103615是 103611,由 vboxsync 提交於 13 月 前

ValKit/bs3-cpu-instr-2: Test the alternate reg/reg encoding of and, or, xor, add, adc, sub, sbb and cmp. Extended x86extra.mac with macros for manually encoding reg/reg instructions like this. bugref:10376

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 218.7 KB
 
1/* $Id: bs3-cpu-instr-2-template.c 103611 2024-02-29 11:26:29Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-instr-2, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/asm.h>
42#include <iprt/asm-amd64-x86.h>
43#include "bs3-cpu-instr-2.h"
44#include "bs3-cpu-instr-2-data.h"
45
46
47/*********************************************************************************************************************************
48* Structures and Typedefs *
49*********************************************************************************************************************************/
50#ifdef BS3_INSTANTIATING_CMN
51# if ARCH_BITS == 64
52typedef struct BS3CI2FSGSBASE
53{
54 const char *pszDesc;
55 bool f64BitOperand;
56 FPFNBS3FAR pfnWorker;
57 uint8_t offWorkerUd2;
58 FPFNBS3FAR pfnVerifyWorker;
59 uint8_t offVerifyWorkerUd2;
60} BS3CI2FSGSBASE;
61# endif
62#endif
63
64
65/*********************************************************************************************************************************
66* External Symbols *
67*********************************************************************************************************************************/
68#ifdef BS3_INSTANTIATING_CMN
69# if ARCH_BITS == 64
70# define BS3CPUINSTR2_BINARY_OP_PROTO64(a_Ins) \
71 /* 8-bit */ \
72 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _sil_dil); \
73 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9b_r8b); \
74 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_r13b); \
75 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dl_r14b); \
76 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r8b_bl); \
77 /* 16-bit */ \
78 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8w_cx); \
79 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r15w_r10w); \
80 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r13w_ax); \
81 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _si_r9w); \
82 /* 32-bit */ \
83 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_r8d); \
84 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9d_ecx); \
85 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r13d_r14d); \
86 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15d_esi); \
87 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _eax_r10d); \
88 /* 64-bit */ \
89 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_rbx); \
90 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_rax); \
91 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rdx_r10); \
92 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15_rsi); \
93 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _rbx_r14);
94
95# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(a_Ins) \
96 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _sil_dil), X86_GREG_xSI, X86_GREG_xDI }, \
97 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9b_r8b), X86_GREG_x9, X86_GREG_x8 }, \
98 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_r13b), X86_GREG_xAX, X86_GREG_x13 },
99# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(a_Ins) \
100 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dl_r14b), X86_GREG_xDX, X86_GREG_x14 }, \
101 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r8b_bl), X86_GREG_x8, X86_GREG_xBX },
102# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(a_Ins) \
103 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8w_cx), X86_GREG_x8, X86_GREG_xCX }, \
104 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r15w_r10w), X86_GREG_x15, X86_GREG_x10 },
105# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(a_Ins) \
106 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r13w_ax), X86_GREG_x13, X86_GREG_xAX }, \
107 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _si_r9w), X86_GREG_xSI, X86_GREG_x9 },
108# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins) \
109 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_r8d), X86_GREG_xAX, X86_GREG_x8 }, \
110 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9d_ecx), X86_GREG_x9, X86_GREG_xCX }, \
111 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r13d_r14d), X86_GREG_x13, X86_GREG_x14 },
112# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32_64BIT(a_Ins) \
113 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15d_esi), X86_GREG_x15, X86_GREG_xSI }, \
114 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _eax_r10d), X86_GREG_xAX, X86_GREG_x10 },
115# define BS3CPUINSTR2CMNBINTEST_ENTRIES_64(a_Ins) \
116 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_rbx), X86_GREG_xAX, X86_GREG_xBX }, \
117 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_rax), X86_GREG_x8, X86_GREG_xAX }, \
118 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rdx_r10), X86_GREG_xDX, X86_GREG_x10 },
119# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(a_Ins) \
120 BS3CPUINSTR2CMNBINTEST_ENTRIES_64(a_Ins) \
121 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15_rsi), X86_GREG_x15, X86_GREG_xSI }, \
122 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _rbx_r14), X86_GREG_xBX, X86_GREG_x14 },
123# else
124# define BS3CPUINSTR2_BINARY_OP_PROTO64(a_Ins)
125# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(aIns)
126# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(aIns)
127# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(aIns)
128# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(aIns)
129# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(aIns)
130# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32_64BIT(aIns)
131# endif
132# define BS3CPUINSTR2_BINARY_OP_PROTO(a_Ins) \
133 BS3CPUINSTR2_BINARY_OP_PROTO64(a_Ins) \
134 /* 8-bit */ \
135 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_dl); \
136 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ch_bh); \
137 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dl_ah); \
138 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dh_cl); \
139 /* 16-bit */ \
140 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _di_si); \
141 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _cx_bp); \
142 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _bp_bx); \
143 /* 32-bit */ \
144 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_ebx); \
145 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ecx_ebp); \
146 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _edx_edi); \
147 extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _edi_esi)
148
149# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8(a_Ins) \
150 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_dl), X86_GREG_xAX, X86_GREG_xDX }, \
151 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ch_bh), X86_GREG_xCX+16, X86_GREG_xBX+16 }, \
152 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dl_ah), X86_GREG_xDX, X86_GREG_xAX+16 }, \
153 BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(a_Ins)
154# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(a_Ins) \
155 BS3CPUINSTR2CMNBINTEST_ENTRIES_8(a_Ins) \
156 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dh_cl), X86_GREG_xDX+16, X86_GREG_xCX }, \
157 BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(a_Ins)
158
159# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16(a_Ins) \
160 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _di_si), X86_GREG_xDI, X86_GREG_xSI }, \
161 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _cx_bp), X86_GREG_xCX, X86_GREG_xBP }, \
162 BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(a_Ins)
163# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(a_Ins) \
164 BS3CPUINSTR2CMNBINTEST_ENTRIES_16(a_Ins) \
165 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _bp_bx), X86_GREG_xBP, X86_GREG_xBX }, \
166 BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(a_Ins)
167
168# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32(a_Ins) \
169 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_ebx), X86_GREG_xAX, X86_GREG_xBX }, \
170 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ecx_ebp), X86_GREG_xCX, X86_GREG_xBP }, \
171 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _edx_edi), X86_GREG_xDX, X86_GREG_xDI }, \
172 BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins)
173# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(a_Ins) \
174 BS3CPUINSTR2CMNBINTEST_ENTRIES_32(a_Ins) \
175 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _edi_esi), X86_GREG_xDI, X86_GREG_xSI }, \
176 BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins)
177
178
179BS3CPUINSTR2_BINARY_OP_PROTO(and);
180BS3CPUINSTR2_BINARY_OP_PROTO(or);
181BS3CPUINSTR2_BINARY_OP_PROTO(xor);
182BS3CPUINSTR2_BINARY_OP_PROTO(test);
183
184BS3CPUINSTR2_BINARY_OP_PROTO(add);
185BS3CPUINSTR2_BINARY_OP_PROTO(adc);
186BS3CPUINSTR2_BINARY_OP_PROTO(sub);
187BS3CPUINSTR2_BINARY_OP_PROTO(sbb);
188BS3CPUINSTR2_BINARY_OP_PROTO(cmp);
189
190BS3CPUINSTR2_BINARY_OP_PROTO(bt); /* ignore 8-bit protos */
191BS3CPUINSTR2_BINARY_OP_PROTO(btc);
192BS3CPUINSTR2_BINARY_OP_PROTO(btr);
193BS3CPUINSTR2_BINARY_OP_PROTO(bts);
194
195extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2);
196
197extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2);
198extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2);
199
200extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2);
201extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2);
202
203extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_AX_BX_ud2);
204extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_EBX_ud2);
205extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_RBX_ud2);
206extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_AX_FSxBX_ud2);
207extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_FSxBX_ud2);
208extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_FSxBX_ud2);
209
210extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_BX_ud2);
211extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_EBX_ud2);
212extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_RBX_ud2);
213extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_FSxBX_ud2);
214extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_FSxBX_ud2);
215extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_FSxBX_ud2);
216
217extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_BX_ud2);
218extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_EBX_ud2);
219extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_RBX_ud2);
220extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_FSxBX_ud2);
221extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_FSxBX_ud2);
222extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_FSxBX_ud2);
223
224extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_BX_ud2);
225extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_EBX_ud2);
226extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_RBX_ud2);
227extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_FSxBX_ud2);
228extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_FSxBX_ud2);
229extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_FSxBX_ud2);
230
231extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_AX_BX_ud2);
232extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_EBX_ud2);
233extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_RBX_ud2);
234extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_AX_FSxBX_ud2);
235extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_FSxBX_ud2);
236extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_FSxBX_ud2);
237
238extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_BX_ud2);
239extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_EBX_ud2);
240extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_RBX_ud2);
241extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_FSxBX_ud2);
242extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_FSxBX_ud2);
243extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_FSxBX_ud2);
244
245extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_BX_ud2);
246extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_EBX_ud2);
247extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_RBX_ud2);
248extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_FSxBX_ud2);
249extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_FSxBX_ud2);
250extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_FSxBX_ud2);
251
252extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_BX_ud2);
253extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_EBX_ud2);
254extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_RBX_ud2);
255extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_FSxBX_ud2);
256extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_FSxBX_ud2);
257extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_FSxBX_ud2);
258
259extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp);
260extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp);
261extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_L1);
262# if ARCH_BITS == 64
263extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_X1);
264# endif
265extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V1);
266extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V15);
267extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp);
268extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp);
269
270extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp);
271extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp);
272extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp);
273extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp);
274
275extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_RBX_RCX_icebp);
276extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_FSxBX_RCX_icebp);
277extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_EBX_ECX_icebp);
278extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_FSxBX_ECX_icebp);
279
280extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_RBX_RCX_icebp);
281extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_FSxBX_RCX_icebp);
282extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_EBX_ECX_icebp);
283extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_FSxBX_ECX_icebp);
284
285extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_RBX_icebp);
286extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_FSxBX_icebp);
287extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_EBX_icebp);
288extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_FSxBX_icebp);
289
290extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_RBX_icebp);
291extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_FSxBX_icebp);
292extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_EBX_icebp);
293extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_FSxBX_icebp);
294
295extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_RBX_RCX_icebp);
296extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_FSxBX_RCX_icebp);
297extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_EBX_ECX_icebp);
298extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_FSxBX_ECX_icebp);
299
300extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_RBX_RCX_icebp);
301extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_FSxBX_RCX_icebp);
302extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_EBX_ECX_icebp);
303extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_FSxBX_ECX_icebp);
304
305extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_RBX_RCX_icebp);
306extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_FSxBX_RCX_icebp);
307extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_EBX_ECX_icebp);
308extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_FSxBX_ECX_icebp);
309
310extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_RBX_icebp);
311extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_FSxBX_icebp);
312extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_EBX_icebp);
313extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_FSxBX_icebp);
314
315extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_RBX_icebp);
316extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_FSxBX_icebp);
317extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_EBX_icebp);
318extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_FSxBX_icebp);
319
320extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_RBX_icebp);
321extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_FSxBX_icebp);
322extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_EBX_icebp);
323extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_FSxBX_icebp);
324
325extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp);
326extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RCX_RCX_RBX_RDX_icebp);
327extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp);
328extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp);
329extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_ECX_ECX_EBX_EDX_icebp);
330extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp);
331
332extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp);
333extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp);
334extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp);
335extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp);
336extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp);
337extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp);
338
339extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BL_icebp);
340extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_byte_FSxBX_icebp);
341extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BX_icebp);
342extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_word_FSxBX_icebp);
343extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_EBX_icebp);
344extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_dword_FSxBX_icebp);
345extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_RBX_icebp);
346extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_qword_FSxBX_icebp);
347
348extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_EBX_icebp);
349extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_dword_FSxBX_icebp);
350extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_RBX_icebp);
351extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_qword_FSxBX_icebp);
352extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_EAX_EBX_icebp);
353extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_EAX_dword_FSxBX_icebp);
354extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_RAX_RBX_icebp);
355extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_RAX_qword_FSxBX_icebp);
356
357extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_AX_word_FSxBX_icebp);
358extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_EAX_dword_FSxBX_icebp);
359extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_RAX_qword_FSxBX_icebp);
360extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_word_FSxBX_AX_icebp);
361extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_dword_FSxBX_EAX_icebp);
362extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_movbe_qword_FSxBX_RAX_icebp);
363
364extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_cmpxchg8b_FSxDI_icebp);
365extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg8b_FSxDI_icebp);
366extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg8b_FSxDI_icebp);
367extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg8b_FSxDI_icebp);
368extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg8b_FSxDI_icebp);
369extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg8b_FSxDI_icebp);
370extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg8b_FSxDI_icebp);
371extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg8b_FSxDI_icebp);
372
373# if ARCH_BITS == 64
374extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2);
375extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2);
376extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2);
377extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2);
378extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2);
379extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2);
380extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2);
381extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2);
382
383extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_ud2);
384extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_ud2);
385extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2);
386extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2);
387
388extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_ud2);
389extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_ud2);
390extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2);
391extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2);
392
393extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdfsbase_rbx_ud2);
394extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdfsbase_ebx_ud2);
395extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdgsbase_rbx_ud2);
396extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdgsbase_ebx_ud2);
397# endif
398#endif
399
400
401/*********************************************************************************************************************************
402* Global Variables *
403*********************************************************************************************************************************/
404#ifdef BS3_INSTANTIATING_CMN
405# if ARCH_BITS == 64
406static BS3CI2FSGSBASE const s_aWrFsBaseWorkers[] =
407{
408 { "wrfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
409 { "wrfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
410};
411
412static BS3CI2FSGSBASE const s_aWrGsBaseWorkers[] =
413{
414 { "wrgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
415 { "wrgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
416};
417
418static BS3CI2FSGSBASE const s_aRdFsBaseWorkers[] =
419{
420 { "rdfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
421 { "rdfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
422};
423
424static BS3CI2FSGSBASE const s_aRdGsBaseWorkers[] =
425{
426 { "rdgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
427 { "rdgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
428};
429# endif
430#endif /* BS3_INSTANTIATING_CMN - global */
431
432
433/*
434 * Common code.
435 * Common code.
436 * Common code.
437 */
438#ifdef BS3_INSTANTIATING_CMN
439
440/*
441 * Basic binary arithmetic tests.
442 */
443
444typedef struct BS3CPUINSTR2CMNBINTEST
445{
446 FPFNBS3FAR pfnWorker;
447 uint8_t idxDstReg;
448 uint8_t idxSrcReg;
449} BS3CPUINSTR2CMNBINTEST;
450typedef BS3CPUINSTR2CMNBINTEST const BS3_FAR_DATA *PCBS3CPUINSTR2CMNBINTEST;
451
452
453static uint16_t const g_auEflStatusBitsVars[] =
454{
455 0,
456 X86_EFL_STATUS_BITS,
457 X86_EFL_CF,
458 X86_EFL_PF,
459 X86_EFL_AF,
460 X86_EFL_ZF,
461 X86_EFL_SF,
462 X86_EFL_OF,
463 X86_EFL_PF | X86_EFL_AF,
464};
465
466#define BS3CPUINSTR2_COMMON_BINARY_U(a_cBits, a_UIntType, a_szFmt) \
467static uint8_t \
468RT_CONCAT(bs3CpuInstr2_CommonBinaryU,a_cBits)(uint8_t bMode, PCBS3CPUINSTR2CMNBINTEST paTests, unsigned cTests, uint16_t fPassthruEfl, \
469 RT_CONCAT(PCBS3CPUINSTR2BIN,a_cBits) paTestData, unsigned cTestData, bool fCarryIn) \
470{ \
471 BS3REGCTX Ctx; \
472 BS3REGCTX CtxExpect; \
473 BS3TRAPFRAME TrapFrame; \
474 unsigned iTest; \
475 \
476 /* Ensure the structures are allocated before we sample the stack pointer. */ \
477 Bs3MemSet(&Ctx, 0, sizeof(Ctx)); \
478 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame)); \
479 \
480 /* \
481 * Create test context. \
482 */ \
483 Bs3RegCtxSaveEx(&Ctx, bMode, 512); \
484 Ctx.rflags.u32 &= ~X86_EFL_RF; \
485 Bs3MemCpy(&CtxExpect, &Ctx, sizeof(CtxExpect)); \
486 if (!BS3_MODE_IS_16BIT_SYS(bMode)) \
487 CtxExpect.rflags.u32 |= X86_EFL_RF; \
488 \
489 /* \
490 * Each test worker. \
491 */ \
492 for (iTest = 0; iTest < cTests; iTest++) \
493 { \
494 uint8_t const cbInstr = ((uint8_t BS3_FAR *)paTests[iTest].pfnWorker)[-1]; /* the function is prefixed by the length */ \
495 unsigned const idxDstReg = paTests[iTest].idxDstReg; \
496 unsigned const idxSrcReg = paTests[iTest].idxSrcReg; \
497 BS3REG const SavedDst = (&Ctx.rax)[idxDstReg & 15]; \
498 BS3REG const SavedSrc = (&Ctx.rax)[idxSrcReg & 15]; \
499 a_UIntType RT_FAR * const puCtxDst = &(&Ctx.rax)[idxDstReg & 15].RT_CONCAT(au,a_cBits)[idxDstReg >> 4]; \
500 a_UIntType RT_FAR * const puCtxSrc = &(&Ctx.rax)[idxSrcReg & 15].RT_CONCAT(au,a_cBits)[idxSrcReg >> 4]; \
501 a_UIntType RT_FAR * const puCtxExpectDst = &(&CtxExpect.rax)[idxDstReg & 15].RT_CONCAT(au,a_cBits)[idxDstReg >> 4]; \
502 a_UIntType RT_FAR * const puCtxExpectSrc = &(&CtxExpect.rax)[idxSrcReg & 15].RT_CONCAT(au,a_cBits)[idxSrcReg >> 4]; \
503 unsigned iTestData; \
504 /*Bs3TestPrintf("pfnWorker=%p\n", paTests[iTest].pfnWorker);*/ \
505 \
506 Bs3RegCtxSetRipCsFromLnkPtr(&Ctx, paTests[iTest].pfnWorker); \
507 CtxExpect.rip.u = Ctx.rip.u + cbInstr; \
508 CtxExpect.cs = Ctx.cs; \
509 \
510 /* \
511 * Loop over the test data and feed it to the worker. \
512 */\
513 for (iTestData = 5; iTestData < cTestData; iTestData++) \
514 { \
515 unsigned iRecompiler; \
516 *puCtxDst = paTestData[iTestData].uSrc1; \
517 *puCtxSrc = paTestData[iTestData].uSrc2; \
518 *puCtxExpectDst = paTestData[iTestData].uResult; \
519 *puCtxExpectSrc = paTestData[iTestData].uSrc2; \
520 CtxExpect.rflags.u16 &= ~X86_EFL_STATUS_BITS; \
521 CtxExpect.rflags.u16 |= paTestData[iTestData].fEflOut & X86_EFL_STATUS_BITS; \
522 \
523 /* \
524 * Do input the eight EFLAGS variations three times, so we're sure to trigger \
525 * native recompilation of the test worker code. \
526 */ \
527 for (iRecompiler = 0; iRecompiler < 2; iRecompiler++) \
528 { \
529 unsigned iEflVar = 0; \
530 for (iEflVar = 0; iEflVar < RT_ELEMENTS(g_auEflStatusBitsVars); iEflVar++) \
531 { \
532 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS; \
533 if (!fCarryIn) \
534 Ctx.rflags.u16 |= g_auEflStatusBitsVars[iEflVar]; \
535 else \
536 Ctx.rflags.u16 |= (g_auEflStatusBitsVars[iEflVar] & ~X86_EFL_CF) \
537 | (paTestData[iTestData].fEflOut >> BS3CPUINSTR2BIN_EFL_CARRY_IN_BIT) & X86_EFL_CF; \
538 if (fPassthruEfl) \
539 CtxExpect.rflags.u16 = (CtxExpect.rflags.u16 & ~fPassthruEfl) | (Ctx.rflags.u16 & fPassthruEfl); \
540 \
541 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame); \
542 if (TrapFrame.bXcpt != X86_XCPT_UD) \
543 { \
544 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt); \
545 Bs3TrapPrintFrame(&TrapFrame); \
546 } \
547 else if (Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &CtxExpect, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, \
548 0 /*fExtraEfl*/, "mode", (iTest << 8) | (iTestData & 0xff))) \
549 continue; \
550 /*else { Bs3RegCtxPrint(&Ctx); Bs3TrapPrintFrame(&TrapFrame); }*/ \
551 Bs3TestPrintf("iTest=%u iData=%u: uSrc1=%" a_szFmt " uSrc2=%" a_szFmt " %s-> %" a_szFmt "\n", \
552 iTest, iTestData, paTestData[iTestData].uSrc1, paTestData[iTestData].uSrc2, \
553 !fCarryIn ? "" : Ctx.rflags.u16 & X86_EFL_CF ? "CF " : "NC ", \
554 paTestData[iTestData].uResult); \
555 /*ASMHalt();*/ \
556 iRecompiler = ~0U - 1; \
557 break; \
558 } \
559 } \
560 } \
561 \
562 (&CtxExpect.rax)[idxDstReg & 15].u = (&Ctx.rax)[idxDstReg & 15].u = SavedDst.u; \
563 (&CtxExpect.rax)[idxSrcReg & 15].u = (&Ctx.rax)[idxSrcReg & 15].u = SavedSrc.u; \
564 } \
565 \
566 return 0; \
567}
568
569BS3CPUINSTR2_COMMON_BINARY_U(8, uint8_t, "RX8")
570BS3CPUINSTR2_COMMON_BINARY_U(16, uint16_t, "RX16")
571BS3CPUINSTR2_COMMON_BINARY_U(32, uint32_t, "RX32")
572#if ARCH_BITS == 64
573BS3CPUINSTR2_COMMON_BINARY_U(64, uint64_t, "RX64")
574#endif
575
576
577BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_and)(uint8_t bMode)
578{
579 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(and) };
580 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(and) };
581 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(and) };
582#if ARCH_BITS == 64
583 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(and) };
584#endif
585 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
586 g_aBs3CpuInstr2_and_TestDataU8, g_cBs3CpuInstr2_and_TestDataU8, false /*fCarryIn*/);
587 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
588 g_aBs3CpuInstr2_and_TestDataU16, g_cBs3CpuInstr2_and_TestDataU16, false /*fCarryIn*/);
589 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
590 g_aBs3CpuInstr2_and_TestDataU32, g_cBs3CpuInstr2_and_TestDataU32, false /*fCarryIn*/);
591#if ARCH_BITS == 64
592 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
593 g_aBs3CpuInstr2_and_TestDataU64, g_cBs3CpuInstr2_and_TestDataU64, false /*fCarryIn*/);
594#endif
595 return 0;
596}
597
598
599BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_or)(uint8_t bMode)
600{
601 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(or) };
602 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(or) };
603 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(or) };
604#if ARCH_BITS == 64
605 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(or) };
606#endif
607 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
608 g_aBs3CpuInstr2_or_TestDataU8, g_cBs3CpuInstr2_or_TestDataU8, false /*fCarryIn*/);
609 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
610 g_aBs3CpuInstr2_or_TestDataU16, g_cBs3CpuInstr2_or_TestDataU16, false /*fCarryIn*/);
611 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
612 g_aBs3CpuInstr2_or_TestDataU32, g_cBs3CpuInstr2_or_TestDataU32, false /*fCarryIn*/);
613#if ARCH_BITS == 64
614 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
615 g_aBs3CpuInstr2_or_TestDataU64, g_cBs3CpuInstr2_or_TestDataU64, false /*fCarryIn*/);
616#endif
617 return 0;
618}
619
620
621BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_xor)(uint8_t bMode)
622{
623 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(xor) };
624 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(xor) };
625 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(xor) };
626#if ARCH_BITS == 64
627 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(xor) };
628#endif
629 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
630 g_aBs3CpuInstr2_xor_TestDataU8, g_cBs3CpuInstr2_xor_TestDataU8, false /*fCarryIn*/);
631 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
632 g_aBs3CpuInstr2_xor_TestDataU16, g_cBs3CpuInstr2_xor_TestDataU16, false /*fCarryIn*/);
633 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
634 g_aBs3CpuInstr2_xor_TestDataU32, g_cBs3CpuInstr2_xor_TestDataU32, false /*fCarryIn*/);
635#if ARCH_BITS == 64
636 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
637 g_aBs3CpuInstr2_xor_TestDataU64, g_cBs3CpuInstr2_xor_TestDataU64, false /*fCarryIn*/);
638#endif
639 return 0;
640}
641
642
643BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_test)(uint8_t bMode)
644{
645 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_8(test) };
646 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(test) };
647 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(test) };
648#if ARCH_BITS == 64
649 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(test) };
650#endif
651 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
652 g_aBs3CpuInstr2_test_TestDataU8, g_cBs3CpuInstr2_test_TestDataU8, false /*fCarryIn*/);
653 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
654 g_aBs3CpuInstr2_test_TestDataU16, g_cBs3CpuInstr2_test_TestDataU16, false /*fCarryIn*/);
655 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
656 g_aBs3CpuInstr2_test_TestDataU32, g_cBs3CpuInstr2_test_TestDataU32, false /*fCarryIn*/);
657#if ARCH_BITS == 64
658 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
659 g_aBs3CpuInstr2_test_TestDataU64, g_cBs3CpuInstr2_test_TestDataU64, false /*fCarryIn*/);
660#endif
661 return 0;
662}
663
664
665BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_add)(uint8_t bMode)
666{
667 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(add) };
668 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(add) };
669 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(add) };
670#if ARCH_BITS == 64
671 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(add) };
672#endif
673 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
674 g_aBs3CpuInstr2_add_TestDataU8, g_cBs3CpuInstr2_add_TestDataU8, false /*fCarryIn*/);
675 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
676 g_aBs3CpuInstr2_add_TestDataU16, g_cBs3CpuInstr2_add_TestDataU16, false /*fCarryIn*/);
677 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
678 g_aBs3CpuInstr2_add_TestDataU32, g_cBs3CpuInstr2_add_TestDataU32, false /*fCarryIn*/);
679#if ARCH_BITS == 64
680 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
681 g_aBs3CpuInstr2_add_TestDataU64, g_cBs3CpuInstr2_add_TestDataU64, false /*fCarryIn*/);
682#endif
683 return 0;
684}
685
686
687BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_adc)(uint8_t bMode)
688{
689 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(adc) };
690 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(adc) };
691 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(adc) };
692#if ARCH_BITS == 64
693 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(adc) };
694#endif
695 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
696 g_aBs3CpuInstr2_adc_TestDataU8, g_cBs3CpuInstr2_adc_TestDataU8, true /*fCarryIn*/);
697 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
698 g_aBs3CpuInstr2_adc_TestDataU16, g_cBs3CpuInstr2_adc_TestDataU16, true /*fCarryIn*/);
699 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
700 g_aBs3CpuInstr2_adc_TestDataU32, g_cBs3CpuInstr2_adc_TestDataU32, true /*fCarryIn*/);
701#if ARCH_BITS == 64
702 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
703 g_aBs3CpuInstr2_adc_TestDataU64, g_cBs3CpuInstr2_adc_TestDataU64, true /*fCarryIn*/);
704#endif
705 return 0;
706}
707
708
709BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sub)(uint8_t bMode)
710{
711 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(sub) };
712 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(sub) };
713 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(sub) };
714#if ARCH_BITS == 64
715 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(sub) };
716#endif
717 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
718 g_aBs3CpuInstr2_sub_TestDataU8, g_cBs3CpuInstr2_sub_TestDataU8, false /*fCarryIn*/);
719 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
720 g_aBs3CpuInstr2_sub_TestDataU16, g_cBs3CpuInstr2_sub_TestDataU16, false /*fCarryIn*/);
721 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
722 g_aBs3CpuInstr2_sub_TestDataU32, g_cBs3CpuInstr2_sub_TestDataU32, false /*fCarryIn*/);
723#if ARCH_BITS == 64
724 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
725 g_aBs3CpuInstr2_sub_TestDataU64, g_cBs3CpuInstr2_sub_TestDataU64, false /*fCarryIn*/);
726#endif
727 return 0;
728}
729
730
731BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sbb)(uint8_t bMode)
732{
733 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(sbb) };
734 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(sbb) };
735 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(sbb) };
736#if ARCH_BITS == 64
737 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(sbb) };
738#endif
739 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
740 g_aBs3CpuInstr2_sbb_TestDataU8, g_cBs3CpuInstr2_sbb_TestDataU8, true /*fCarryIn*/);
741 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
742 g_aBs3CpuInstr2_sbb_TestDataU16, g_cBs3CpuInstr2_sbb_TestDataU16, true /*fCarryIn*/);
743 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
744 g_aBs3CpuInstr2_sbb_TestDataU32, g_cBs3CpuInstr2_sbb_TestDataU32, true /*fCarryIn*/);
745#if ARCH_BITS == 64
746 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
747 g_aBs3CpuInstr2_sbb_TestDataU64, g_cBs3CpuInstr2_sbb_TestDataU64, true /*fCarryIn*/);
748#endif
749 return 0;
750}
751
752
753BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmp)(uint8_t bMode)
754{
755 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(cmp) };
756 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(cmp) };
757 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(cmp) };
758#if ARCH_BITS == 64
759 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(cmp) };
760#endif
761 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
762 g_aBs3CpuInstr2_cmp_TestDataU8, g_cBs3CpuInstr2_cmp_TestDataU8, false /*fCarryIn*/);
763 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
764 g_aBs3CpuInstr2_cmp_TestDataU16, g_cBs3CpuInstr2_cmp_TestDataU16, false /*fCarryIn*/);
765 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
766 g_aBs3CpuInstr2_cmp_TestDataU32, g_cBs3CpuInstr2_cmp_TestDataU32, false /*fCarryIn*/);
767#if ARCH_BITS == 64
768 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
769 g_aBs3CpuInstr2_cmp_TestDataU64, g_cBs3CpuInstr2_cmp_TestDataU64, false /*fCarryIn*/);
770#endif
771 return 0;
772}
773
774
775#define BS3CPUINSTR2_BTx_PASSTHRU_EFL (X86_EFL_ZF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF)
776
777BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bt)(uint8_t bMode)
778{
779 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(bt) };
780 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(bt) };
781#if ARCH_BITS == 64
782 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(bt) };
783#endif
784 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
785 g_aBs3CpuInstr2_bt_TestDataU16, g_cBs3CpuInstr2_bt_TestDataU16, false /*fCarryIn*/);
786 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
787 g_aBs3CpuInstr2_bt_TestDataU32, g_cBs3CpuInstr2_bt_TestDataU32, false /*fCarryIn*/);
788#if ARCH_BITS == 64
789 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
790 g_aBs3CpuInstr2_bt_TestDataU64, g_cBs3CpuInstr2_bt_TestDataU64, false /*fCarryIn*/);
791#endif
792 return 0;
793}
794
795
796BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_btc)(uint8_t bMode)
797{
798 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(btc) };
799 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(btc) };
800#if ARCH_BITS == 64
801 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(btc) };
802#endif
803 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
804 g_aBs3CpuInstr2_btc_TestDataU16, g_cBs3CpuInstr2_btc_TestDataU16, false /*fCarryIn*/);
805 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
806 g_aBs3CpuInstr2_btc_TestDataU32, g_cBs3CpuInstr2_btc_TestDataU32, false /*fCarryIn*/);
807#if ARCH_BITS == 64
808 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
809 g_aBs3CpuInstr2_btc_TestDataU64, g_cBs3CpuInstr2_btc_TestDataU64, false /*fCarryIn*/);
810#endif
811 return 0;
812}
813
814
815BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_btr)(uint8_t bMode)
816{
817 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(btr) };
818 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(btr) };
819#if ARCH_BITS == 64
820 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(btr) };
821#endif
822 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
823 g_aBs3CpuInstr2_btr_TestDataU16, g_cBs3CpuInstr2_btr_TestDataU16, false /*fCarryIn*/);
824 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
825 g_aBs3CpuInstr2_btr_TestDataU32, g_cBs3CpuInstr2_btr_TestDataU32, false /*fCarryIn*/);
826#if ARCH_BITS == 64
827 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
828 g_aBs3CpuInstr2_btr_TestDataU64, g_cBs3CpuInstr2_btr_TestDataU64, false /*fCarryIn*/);
829#endif
830 return 0;
831}
832
833
834BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bts)(uint8_t bMode)
835{
836 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(bts) };
837 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(bts) };
838#if ARCH_BITS == 64
839 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(bts) };
840#endif
841 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
842 g_aBs3CpuInstr2_bts_TestDataU16, g_cBs3CpuInstr2_bts_TestDataU16, false /*fCarryIn*/);
843 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
844 g_aBs3CpuInstr2_bts_TestDataU32, g_cBs3CpuInstr2_bts_TestDataU32, false /*fCarryIn*/);
845#if ARCH_BITS == 64
846 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
847 g_aBs3CpuInstr2_bts_TestDataU64, g_cBs3CpuInstr2_bts_TestDataU64, false /*fCarryIn*/);
848#endif
849 return 0;
850}
851
852
853
854/*
855 * Multiplication
856 */
857
858BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
859{
860#define MUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
861#define MUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
862
863 static const struct
864 {
865 RTCCUINTREG uInAX;
866 RTCCUINTREG uInBX;
867 RTCCUINTREG uOutDX;
868 RTCCUINTREG uOutAX;
869 uint16_t fFlags;
870 } s_aTests[] =
871 {
872 { 1, 1,
873 0, 1, 0 },
874 { 2, 2,
875 0, 4, 0 },
876 { RTCCUINTREG_MAX, RTCCUINTREG_MAX,
877 RTCCUINTREG_MAX-1, 1, X86_EFL_CF | X86_EFL_OF },
878 { RTCCINTREG_MAX, RTCCINTREG_MAX,
879 RTCCINTREG_MAX / 2, 1, X86_EFL_CF | X86_EFL_OF },
880 { 1, RTCCUINTREG_MAX,
881 0, RTCCUINTREG_MAX, X86_EFL_PF | X86_EFL_SF },
882 { 1, RTCCINTREG_MAX,
883 0, RTCCINTREG_MAX, X86_EFL_PF },
884 { 2, RTCCINTREG_MAX,
885 0, RTCCUINTREG_MAX - 1, X86_EFL_SF },
886 { (RTCCUINTREG)RTCCINTREG_MAX + 1, 2,
887 1, 0, X86_EFL_PF | X86_EFL_CF | X86_EFL_OF },
888 { (RTCCUINTREG)RTCCINTREG_MAX / 2 + 1, 3,
889 0, ((RTCCUINTREG)RTCCINTREG_MAX / 2 + 1) * 3, X86_EFL_PF | X86_EFL_SF },
890 };
891
892 BS3REGCTX Ctx;
893 BS3TRAPFRAME TrapFrame;
894 unsigned i, j, k;
895
896 /* Ensure the structures are allocated before we sample the stack pointer. */
897 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
898 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
899
900 /*
901 * Create test context.
902 */
903 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
904 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2));
905 for (k = 0; k < 2; k++)
906 {
907 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
908 for (j = 0; j < 2; j++)
909 {
910 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
911 {
912 if (k == 0)
913 {
914 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
915 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
916 }
917 else
918 {
919 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
920 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
921 }
922 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
923 if (TrapFrame.bXcpt != X86_XCPT_UD)
924 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
925 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
926 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
927 || (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
928 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
929 {
930 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
931 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
932
933 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
934 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
935 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
936 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
937 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
938 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
939 if ( (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
940 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
941 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & MUL_CHECK_EFLAGS,
942 TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO));
943 }
944 }
945 Ctx.rflags.u16 &= ~(MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO);
946 }
947 }
948
949 return 0;
950}
951
952
953BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_imul)(uint8_t bMode)
954{
955#define IMUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
956#define IMUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
957 static const struct
958 {
959 RTCCUINTREG uInAX;
960 RTCCUINTREG uInBX;
961 RTCCUINTREG uOutDX;
962 RTCCUINTREG uOutAX;
963 uint16_t fFlags;
964 } s_aTests[] =
965 {
966 /* two positive values. */
967 { 1, 1,
968 0, 1, 0 },
969 { 2, 2,
970 0, 4, 0 },
971 { RTCCINTREG_MAX, RTCCINTREG_MAX,
972 RTCCINTREG_MAX/2, 1, X86_EFL_CF | X86_EFL_OF },
973 { 1, RTCCINTREG_MAX,
974 0, RTCCINTREG_MAX, X86_EFL_PF },
975 { 2, RTCCINTREG_MAX,
976 0, RTCCUINTREG_MAX - 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF },
977 { 2, RTCCINTREG_MAX / 2,
978 0, RTCCINTREG_MAX - 1U, 0 },
979 { 2, (RTCCINTREG_MAX / 2 + 1),
980 0, (RTCCUINTREG)RTCCINTREG_MAX + 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
981 { 4, (RTCCINTREG_MAX / 2 + 1),
982 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
983
984 /* negative and positive */
985 { -4, 3,
986 -1, -12, X86_EFL_SF },
987 { 32, -127,
988 -1, -4064, X86_EFL_SF },
989 { RTCCINTREG_MIN, 1,
990 -1, RTCCINTREG_MIN, X86_EFL_SF | X86_EFL_PF },
991 { RTCCINTREG_MIN, 2,
992 -1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
993 { RTCCINTREG_MIN, 3,
994 -2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
995 { RTCCINTREG_MIN, 4,
996 -2, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
997 { RTCCINTREG_MIN, RTCCINTREG_MAX,
998 RTCCINTREG_MIN / 2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
999 { RTCCINTREG_MIN, RTCCINTREG_MAX - 1,
1000 RTCCINTREG_MIN / 2 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
1001
1002 /* two negative values. */
1003 { -4, -63,
1004 0, 252, X86_EFL_PF },
1005 { RTCCINTREG_MIN, RTCCINTREG_MIN,
1006 RTCCUINTREG_MAX / 4 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
1007 { RTCCINTREG_MIN, RTCCINTREG_MIN + 1,
1008 RTCCUINTREG_MAX / 4, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF},
1009 { RTCCINTREG_MIN + 1, RTCCINTREG_MIN + 1,
1010 RTCCUINTREG_MAX / 4, 1, X86_EFL_CF | X86_EFL_OF },
1011
1012 };
1013
1014 BS3REGCTX Ctx;
1015 BS3TRAPFRAME TrapFrame;
1016 unsigned i, j, k;
1017
1018 /* Ensure the structures are allocated before we sample the stack pointer. */
1019 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1020 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1021
1022 /*
1023 * Create test context.
1024 */
1025 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1026 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2));
1027
1028 for (k = 0; k < 2; k++)
1029 {
1030 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
1031 for (j = 0; j < 2; j++)
1032 {
1033 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1034 {
1035 if (k == 0)
1036 {
1037 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1038 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1039 }
1040 else
1041 {
1042 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1043 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1044 }
1045 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1046 if (TrapFrame.bXcpt != X86_XCPT_UD)
1047 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
1048 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1049 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1050 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1051 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1052 {
1053 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
1054 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
1055
1056 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
1057 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1058 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1059 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1060 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1061 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1062 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1063 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1064 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
1065 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
1066 }
1067 }
1068 }
1069 }
1070
1071 /*
1072 * Repeat for the truncating two operand version.
1073 */
1074 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2));
1075
1076 for (k = 0; k < 2; k++)
1077 {
1078 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
1079 for (j = 0; j < 2; j++)
1080 {
1081 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1082 {
1083 if (k == 0)
1084 {
1085 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1086 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1087 }
1088 else
1089 {
1090 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1091 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1092 }
1093 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1094 if (TrapFrame.bXcpt != X86_XCPT_UD)
1095 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
1096 else if ( TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1097 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1098 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1099 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1100 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1101 {
1102 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
1103 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
1104
1105 if (TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
1106 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1107 s_aTests[i].uOutAX, TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS));
1108 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1109 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1110 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
1111 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
1112 }
1113 }
1114 }
1115 }
1116
1117 return 0;
1118}
1119
1120
1121BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_div)(uint8_t bMode)
1122{
1123#define DIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1124 static const struct
1125 {
1126 RTCCUINTREG uInDX;
1127 RTCCUINTREG uInAX;
1128 RTCCUINTREG uInBX;
1129 RTCCUINTREG uOutAX;
1130 RTCCUINTREG uOutDX;
1131 uint8_t bXcpt;
1132 } s_aTests[] =
1133 {
1134 { 0, 1, 1,
1135 1, 0, X86_XCPT_UD },
1136 { 0, 5, 2,
1137 2, 1, X86_XCPT_UD },
1138 { 0, 0, 0,
1139 0, 0, X86_XCPT_DE },
1140 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 0,
1141 0, 0, X86_XCPT_DE },
1142 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 1,
1143 0, 0, X86_XCPT_DE },
1144 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
1145 0, 0, X86_XCPT_DE },
1146 { RTCCUINTREG_MAX - 1, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
1147 RTCCUINTREG_MAX, RTCCUINTREG_MAX - 1, X86_XCPT_UD },
1148 };
1149
1150 BS3REGCTX Ctx;
1151 BS3TRAPFRAME TrapFrame;
1152 unsigned i, j;
1153
1154 /* Ensure the structures are allocated before we sample the stack pointer. */
1155 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1156 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1157
1158 /*
1159 * Create test context.
1160 */
1161 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1162 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2));
1163
1164 /*
1165 * Do the tests twice, first with all flags set, then once again with
1166 * flags cleared. The flags are not touched by my intel skylake CPU.
1167 */
1168 Ctx.rflags.u16 |= DIV_CHECK_EFLAGS;
1169 for (j = 0; j < 2; j++)
1170 {
1171 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1172 {
1173 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1174 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
1175 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1176 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1177
1178 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
1179 || ( s_aTests[i].bXcpt == X86_XCPT_UD
1180 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1181 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1182 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS)
1183 : TrapFrame.Ctx.rax.u != Ctx.rax.u
1184 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1185 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS) ) )
1186 {
1187 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
1188 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
1189 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
1190 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
1191 if (s_aTests[i].bXcpt == X86_XCPT_UD)
1192 {
1193 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
1194 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1195 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1196 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1197 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1198 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1199 if ((TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS))
1200 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
1201 Ctx.rflags.u16 & DIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS);
1202 }
1203 }
1204 }
1205 Ctx.rflags.u16 &= ~DIV_CHECK_EFLAGS;
1206 }
1207
1208 return 0;
1209}
1210
1211
1212
1213BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_idiv)(uint8_t bMode)
1214{
1215#define IDIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1216 static const struct
1217 {
1218 RTCCUINTREG uInDX;
1219 RTCCUINTREG uInAX;
1220 RTCCUINTREG uInBX;
1221 RTCCUINTREG uOutAX;
1222 RTCCUINTREG uOutDX;
1223 uint8_t bXcpt;
1224 } s_aTests[] =
1225 {
1226 { 0, 0, 0,
1227 0, 0, X86_XCPT_DE },
1228 { RTCCINTREG_MAX, RTCCINTREG_MAX, 0,
1229 0, 0, X86_XCPT_DE },
1230 /* two positive values. */
1231 { 0, 1, 1,
1232 1, 0, X86_XCPT_UD },
1233 { 0, 5, 2,
1234 2, 1, X86_XCPT_UD },
1235 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2, RTCCINTREG_MAX,
1236 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_UD },
1237 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2 + 1, RTCCINTREG_MAX,
1238 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_DE },
1239 /* negative dividend, positive divisor. */
1240 { -1, -7, 2,
1241 -3, -1, X86_XCPT_UD },
1242 { RTCCINTREG_MIN / 2 + 1, 0, RTCCINTREG_MAX,
1243 RTCCINTREG_MIN + 2, RTCCINTREG_MIN + 2, X86_XCPT_UD },
1244 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MAX,
1245 0, 0, X86_XCPT_DE },
1246 /* positive dividend, negative divisor. */
1247 { 0, 7, -2,
1248 -3, 1, X86_XCPT_UD },
1249 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX, RTCCINTREG_MIN,
1250 RTCCINTREG_MIN, RTCCINTREG_MAX, X86_XCPT_UD },
1251 { RTCCINTREG_MAX / 2 + 1, (RTCCUINTREG)RTCCINTREG_MAX+1, RTCCINTREG_MIN,
1252 0, 0, X86_XCPT_DE },
1253 /* negative dividend, negative divisor. */
1254 { -1, -7, -2,
1255 3, -1, X86_XCPT_UD },
1256 { RTCCINTREG_MIN / 2, 1, RTCCINTREG_MIN,
1257 RTCCINTREG_MAX, RTCCINTREG_MIN + 1, X86_XCPT_UD },
1258 { RTCCINTREG_MIN / 2, 2, RTCCINTREG_MIN,
1259 RTCCINTREG_MAX, RTCCINTREG_MIN + 2, X86_XCPT_UD },
1260 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MIN,
1261 0, 0, X86_XCPT_DE },
1262 };
1263
1264 BS3REGCTX Ctx;
1265 BS3TRAPFRAME TrapFrame;
1266 unsigned i, j;
1267
1268 /* Ensure the structures are allocated before we sample the stack pointer. */
1269 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1270 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1271
1272 /*
1273 * Create test context.
1274 */
1275 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1276 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2));
1277
1278 /*
1279 * Do the tests twice, first with all flags set, then once again with
1280 * flags cleared. The flags are not touched by my intel skylake CPU.
1281 */
1282 Ctx.rflags.u16 |= IDIV_CHECK_EFLAGS;
1283 for (j = 0; j < 2; j++)
1284 {
1285 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1286 {
1287 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1288 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
1289 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1290 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1291
1292 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
1293 || ( s_aTests[i].bXcpt == X86_XCPT_UD
1294 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1295 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1296 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS)
1297 : TrapFrame.Ctx.rax.u != Ctx.rax.u
1298 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1299 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) ) )
1300 {
1301 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
1302 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
1303 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
1304 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
1305 if (s_aTests[i].bXcpt == X86_XCPT_UD)
1306 {
1307 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
1308 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1309 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1310 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1311 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1312 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1313 if ((TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS))
1314 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
1315 Ctx.rflags.u16 & IDIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS);
1316 }
1317 }
1318 }
1319 Ctx.rflags.u16 &= ~IDIV_CHECK_EFLAGS;
1320 }
1321
1322 return 0;
1323}
1324
1325
1326/*
1327 * BSF/BSR (386+) & TZCNT/LZCNT (BMI1,ABM)
1328 */
1329
1330typedef struct BS3CPUINSTR2_SUBTEST_BITSCAN_T
1331{
1332 RTCCUINTXREG uSrc;
1333 RTCCUINTXREG uOut;
1334 bool fOutNotSet;
1335 uint16_t fEflOut;
1336} BS3CPUINSTR2_SUBTEST_BITSCAN_T;
1337
1338typedef struct BS3CPUINSTR2_TEST_BITSCAN_T
1339{
1340 FPFNBS3FAR pfnWorker;
1341 bool fMemSrc;
1342 uint8_t cbInstr;
1343 uint8_t cOpBits;
1344 uint16_t fEflCheck;
1345 uint8_t cSubTests;
1346 BS3CPUINSTR2_SUBTEST_BITSCAN_T const *paSubTests;
1347} BS3CPUINSTR2_TEST_BITSCAN_T;
1348
1349static uint8_t bs3CpuInstr2_BitScan(uint8_t bMode, BS3CPUINSTR2_TEST_BITSCAN_T const *paTests, unsigned cTests)
1350{
1351 BS3REGCTX Ctx;
1352 BS3TRAPFRAME TrapFrame;
1353 unsigned i, j, k;
1354
1355 /* Ensure the structures are allocated before we sample the stack pointer. */
1356 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1357 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1358
1359 /*
1360 * Create test context.
1361 */
1362 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1363
1364 /*
1365 * Do the tests twice, first with all flags set, then once again with
1366 * flags cleared. The flags are not supposed to be touched at all.
1367 */
1368 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1369 for (j = 0; j < 2; j++)
1370 {
1371 for (i = 0; i < cTests; i++)
1372 {
1373 for (k = 0; k < paTests[i].cSubTests; k++)
1374 {
1375 uint64_t uExpectRax, uExpectRip;
1376 RTCCUINTXREG uMemSrc, uMemSrcExpect;
1377
1378 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
1379 if (!paTests[i].fMemSrc)
1380 {
1381 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
1382 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
1383 }
1384 else
1385 {
1386 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
1387 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
1388 }
1389 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
1390 if (paTests[i].paSubTests[k].fOutNotSet)
1391 uExpectRax = Ctx.rax.u;
1392 else if (paTests[i].cOpBits != 16)
1393 uExpectRax = paTests[i].paSubTests[k].uOut;
1394 else
1395 uExpectRax = paTests[i].paSubTests[k].uOut | (Ctx.rax.u & UINT64_C(0xffffffffffff0000));
1396 uExpectRip = Ctx.rip.u + paTests[i].cbInstr;
1397 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1398
1399 if ( TrapFrame.bXcpt != X86_XCPT_UD
1400 || TrapFrame.Ctx.rip.u != uExpectRip
1401 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1402 || TrapFrame.Ctx.rax.u != uExpectRax
1403 || (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
1404 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck)
1405 /* check that nothing else really changed: */
1406 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1407 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1408 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1409 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1410 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1411 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1412 || uMemSrc != uMemSrcExpect
1413 )
1414 {
1415 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
1416 i, k, paTests[i].paSubTests[k].uSrc);
1417 if (TrapFrame.bXcpt != X86_XCPT_UD)
1418 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", X86_XCPT_UD, TrapFrame.bXcpt);
1419 if (TrapFrame.Ctx.rip.u != uExpectRip)
1420 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1421 if (TrapFrame.Ctx.rax.u != uExpectRax)
1422 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
1423 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1424 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1425 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
1426 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
1427 if ( (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
1428 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck))
1429 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
1430 paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck,
1431 TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck);
1432
1433 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1434 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1435 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1436 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1437 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1438 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1439 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1440 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1441 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1442 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1443 if (uMemSrc != uMemSrcExpect)
1444 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
1445 }
1446 }
1447 }
1448 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1449 }
1450
1451 return 0;
1452}
1453
1454
1455BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsf_tzcnt)(uint8_t bMode)
1456{
1457 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf16[] =
1458 {
1459 { 0, /* -> */ 0, true, X86_EFL_ZF },
1460 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
1461 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1462 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1463 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1464 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1465 };
1466 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt16[] =
1467 {
1468 { 0, /* -> */ 16, false, X86_EFL_CF },
1469 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
1470 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1471 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1472 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1473 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1474 };
1475 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf32[] =
1476 {
1477 { 0, /* -> */ 0, true, X86_EFL_ZF },
1478#if ARCH_BITS == 64
1479 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
1480#endif
1481 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1482 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1483 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1484 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1485 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1486 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1487 };
1488 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt32[] =
1489 {
1490 { 0, /* -> */ 32, false, X86_EFL_CF },
1491#if ARCH_BITS == 64
1492 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
1493#endif
1494 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1495 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1496 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1497 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1498 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1499 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1500 };
1501#if ARCH_BITS == 64
1502 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf64[] =
1503 {
1504 { 0, /* -> */ 0, true, X86_EFL_ZF },
1505 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1506 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1507 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1508 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1509 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1510 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1511 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1512 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
1513 };
1514 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt64[] =
1515 {
1516 { 0, /* -> */ 64, false, X86_EFL_CF },
1517 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1518 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1519 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1520 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1521 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1522 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1523 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1524 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
1525 };
1526#endif
1527 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
1528 {
1529 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1530 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1531 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1532 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1533 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1534 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1535 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1536 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1537#if ARCH_BITS == 64
1538 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
1539 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1540 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
1541 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1542#endif
1543 /* f2 prefixed variant: */
1544 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1545 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1546 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1547 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1548 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1549 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1550 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1551 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1552#if ARCH_BITS == 64
1553 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
1554 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1555 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
1556 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1557#endif
1558
1559 /* tzcnt: */
1560 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1561 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1562 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1563 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1564 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1565 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1566 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1567 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1568#if ARCH_BITS == 64
1569 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1570 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1571 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1572 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1573#endif
1574 /* f2 prefixed tzcnt variant (last prefix (f3) should prevail): */
1575 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1576 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1577 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1578 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1579 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1580 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1581 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1582 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1583#if ARCH_BITS == 64
1584 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1585 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1586 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1587 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1588#endif
1589 };
1590
1591 uint32_t uStdExtFeatEbx = 0;
1592 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1593 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1594 if (!(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1))
1595 {
1596 unsigned i = RT_ELEMENTS(s_aTests);
1597 while (i-- > 0)
1598 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1599 {
1600 s_aTests[i].fEflCheck = X86_EFL_ZF;
1601 switch (s_aTests[i].cOpBits)
1602 {
1603 case 16:
1604 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf16);
1605 s_aTests[i].paSubTests = s_aSubTestsBsf16;
1606 break;
1607 case 32:
1608 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf32);
1609 s_aTests[i].paSubTests = s_aSubTestsBsf32;
1610 break;
1611#if ARCH_BITS == 64
1612 case 64:
1613 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf64);
1614 s_aTests[i].paSubTests = s_aSubTestsBsf64;
1615 break;
1616#endif
1617 }
1618 }
1619 Bs3TestPrintf("tzcnt not supported\n");
1620 }
1621
1622 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1623}
1624
1625
1626BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsr_lzcnt)(uint8_t bMode)
1627{
1628 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr16[] =
1629 {
1630 { 0, /* -> */ 0, true, X86_EFL_ZF },
1631 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
1632 { ~(RTCCUINTXREG)0, /* -> */ 15, false, 0 },
1633 { ~(RTCCUINTXREG)1, /* -> */ 15, false, 0 },
1634 { UINT16_C(0x0001), /* -> */ 0, false, 0 },
1635 { UINT16_C(0x0002), /* -> */ 1, false, 0 },
1636 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1637 };
1638 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt16[] =
1639 {
1640 { 0, /* -> */ 16, false, X86_EFL_CF },
1641 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
1642 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1643 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1644 { UINT16_C(0x8000), /* -> */ 0, false, X86_EFL_ZF },
1645 { UINT16_C(0x4560), /* -> */ 1, false, 0 },
1646 { UINT16_C(0x003f), /* -> */ 10, false, 0 },
1647 { UINT16_C(0x0001), /* -> */ 15, false, 0 },
1648 };
1649 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr32[] =
1650 {
1651 { 0, /* -> */ 0, true, X86_EFL_ZF },
1652#if ARCH_BITS == 64
1653 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
1654#endif
1655 { ~(RTCCUINTXREG)0, /* -> */ 31, false, 0 },
1656 { ~(RTCCUINTXREG)1, /* -> */ 31, false, 0 },
1657 { 1, /* -> */ 0, false, 0 },
1658 { 2, /* -> */ 1, false, 0 },
1659 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1660 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1661 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1662 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1663 };
1664 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt32[] =
1665 {
1666 { 0, /* -> */ 32, false, X86_EFL_CF },
1667#if ARCH_BITS == 64
1668 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
1669#endif
1670 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1671 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1672 { 1, /* -> */ 31, false, 0 },
1673 { 2, /* -> */ 30, false, 0},
1674 { UINT16_C(0x8000), /* -> */ 16, false, 0 },
1675 { UINT16_C(0x4560), /* -> */ 17, false, 0 },
1676 { UINT32_C(0x80000000), /* -> */ 0, false, X86_EFL_ZF },
1677 { UINT32_C(0x45600000), /* -> */ 1, false, 0 },
1678 { UINT32_C(0x0000ffff), /* -> */ 16, false, 0 },
1679 };
1680#if ARCH_BITS == 64
1681 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr64[] =
1682 {
1683 { 0, /* -> */ 0, true, X86_EFL_ZF },
1684 { ~(RTCCUINTXREG)0, /* -> */ 63, false, 0 },
1685 { ~(RTCCUINTXREG)1, /* -> */ 63, false, 0 },
1686 { 1, /* -> */ 0, false, 0 },
1687 { 2, /* -> */ 1, false, 0 },
1688 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1689 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1690 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1691 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1692 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1693 { UINT64_C(0x0045600000000000), /* -> */ 54, false, 0 },
1694 };
1695 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt64[] =
1696 {
1697 { 0, /* -> */ 64, false, X86_EFL_CF },
1698 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1699 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1700 { 1, /* -> */ 63, false, 0 },
1701 { 2, /* -> */ 62, false, 0 },
1702 { UINT16_C(0x8000), /* -> */ 48, false, 0 },
1703 { UINT16_C(0x4560), /* -> */ 49, false, 0 },
1704 { UINT32_C(0x80000000), /* -> */ 32, false, 0 },
1705 { UINT32_C(0x45600000), /* -> */ 33, false, 0 },
1706 { UINT64_C(0x8000000000000000), /* -> */ 0, false, X86_EFL_ZF },
1707 { UINT64_C(0x4560000000000000), /* -> */ 1, false, 0 },
1708 { UINT64_C(0x0045600000000000), /* -> */ 9, false, 0 },
1709 };
1710#endif
1711 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
1712 {
1713 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1714 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1715 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1716 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1717 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1718 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1719 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1720 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1721#if ARCH_BITS == 64
1722 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
1723 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1724 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
1725 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1726#endif
1727 /* f2 prefixed variant: */
1728 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1729 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1730 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1731 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1732 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1733 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1734 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1735 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1736#if ARCH_BITS == 64
1737 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
1738 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1739 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
1740 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1741#endif
1742
1743 /* lzcnt: */
1744 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1745 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1746 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1747 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1748 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1749 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1750 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1751 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1752#if ARCH_BITS == 64
1753 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1754 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1755 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1756 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1757#endif
1758 /* f2 prefixed lzcnt variant (last prefix (f3) should prevail): */
1759 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1760 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1761 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1762 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1763 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1764 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1765 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1766 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1767#if ARCH_BITS == 64
1768 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1769 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1770 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1771 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1772#endif
1773 };
1774
1775 uint32_t uExtFeatEcx = 0;
1776 if (g_uBs3CpuDetected & BS3CPU_F_CPUID_EXT_LEAVES)
1777 ASMCpuIdExSlow(UINT32_C(0x80000001), 0, 0, 0, NULL, NULL, &uExtFeatEcx, NULL);
1778 if (!(uExtFeatEcx & X86_CPUID_AMD_FEATURE_ECX_ABM))
1779 {
1780 unsigned i = RT_ELEMENTS(s_aTests);
1781 while (i-- > 0)
1782 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1783 {
1784 s_aTests[i].fEflCheck = X86_EFL_ZF;
1785 switch (s_aTests[i].cOpBits)
1786 {
1787 case 16:
1788 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr16);
1789 s_aTests[i].paSubTests = s_aSubTestsBsr16;
1790 break;
1791 case 32:
1792 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr32);
1793 s_aTests[i].paSubTests = s_aSubTestsBsr32;
1794 break;
1795#if ARCH_BITS == 64
1796 case 64:
1797 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr64);
1798 s_aTests[i].paSubTests = s_aSubTestsBsr64;
1799 break;
1800#endif
1801 }
1802 }
1803 Bs3TestPrintf("lzcnt not supported\n");
1804 }
1805
1806 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1807}
1808
1809
1810/**
1811 * RORX
1812 */
1813BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rorx)(uint8_t bMode)
1814{
1815 static const struct
1816 {
1817 FPFNBS3FAR pfnWorker;
1818 bool fMemSrc;
1819 bool fOkay;
1820 RTCCUINTXREG uIn;
1821 RTCCUINTXREG uOut;
1822 } s_aTests[] =
1823 {
1824 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1825 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #0
1826 0, /* -> */ 0 },
1827 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #1
1828 ~(RTCCUINTXREG)2, /* -> */ ~(RTCCUINTXREG)0 >> 1 },
1829 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #2
1830 0, /* -> */ 0 },
1831 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #3
1832 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG_MAX >> 4) | (~(RTCCUINTXREG)2 << (sizeof(RTCCUINTXREG) * 8 - 4)) },
1833
1834 /* 32 bits register width: */
1835 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #4
1836 0, /* -> */ 0 },
1837 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #5
1838 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)(~(uint32_t)0 >> 1) },
1839 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #6
1840 0, /* -> */ 0 },
1841 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #7
1842 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)UINT32_C(0xdfffffff) },
1843
1844 /* encoding tests: */
1845 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_L1), false, false, // #8
1846 RTCCUINTXREG_MAX, /* -> */ 0 },
1847 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V1), false, false, // #9
1848 RTCCUINTXREG_MAX, /* -> */ 0 },
1849 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V15), false, false, // #10
1850 RTCCUINTXREG_MAX, /* -> */ 0 },
1851# if ARCH_BITS == 64 /* The VEX.X=0 encoding mean LES instruction in 32-bit and 16-bit mode. */
1852 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_X1), false, true, // #11
1853 UINT32_C(0xf1e2d3c5), /* -> */ (RTCCUINTXREG)UINT32_C(0x7c78b4f1) },
1854# endif
1855 };
1856
1857 BS3REGCTX Ctx;
1858 BS3TRAPFRAME TrapFrame;
1859 unsigned i, j;
1860 uint32_t uStdExtFeatEbx = 0;
1861 bool fSupportsRorX;
1862
1863 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1864 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1865 fSupportsRorX = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
1866
1867 /* Ensure the structures are allocated before we sample the stack pointer. */
1868 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1869 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1870
1871 /*
1872 * Create test context.
1873 */
1874 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1875
1876 /*
1877 * Do the tests twice, first with all flags set, then once again with
1878 * flags cleared. The flags are not supposed to be touched at all.
1879 */
1880 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1881 for (j = 0; j < 2; j++)
1882 {
1883 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1884 {
1885 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && s_aTests[i].fOkay && fSupportsRorX;
1886 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1887 uint64_t uExpectRbx, uExpectRip;
1888 RTCCUINTXREG uMemSrc, uMemSrcExpect;
1889 Ctx.rbx.uCcXReg = RTCCUINTXREG_MAX * 1019;
1890 if (!s_aTests[i].fMemSrc)
1891 {
1892 Ctx.rdx.uCcXReg = s_aTests[i].uIn;
1893 uMemSrcExpect = uMemSrc = ~s_aTests[i].uIn;
1894 }
1895 else
1896 {
1897 Ctx.rdx.uCcXReg = ~s_aTests[i].uIn;
1898 uMemSrcExpect = uMemSrc = s_aTests[i].uIn;
1899 Bs3RegCtxSetGrpDsFromCurPtr(&Ctx, &Ctx.rdi, &uMemSrc);
1900 }
1901 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
1902 uExpectRbx = fOkay ? s_aTests[i].uOut : Ctx.rbx.u;
1903 uExpectRip = Ctx.rip.u + (fOkay ? 6 + 1 : 0);
1904 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1905
1906 if ( TrapFrame.bXcpt != bExpectXcpt
1907 || TrapFrame.Ctx.rip.u != uExpectRip
1908 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1909 || TrapFrame.Ctx.rbx.u != uExpectRbx
1910 /* check that nothing else really changed: */
1911 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
1912 || TrapFrame.Ctx.rax.u != Ctx.rax.u
1913 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1914 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1915 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1916 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1917 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1918 || uMemSrc != uMemSrcExpect
1919 )
1920 {
1921 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uIn);
1922 if (TrapFrame.bXcpt != bExpectXcpt)
1923 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
1924 if (TrapFrame.Ctx.rip.u != uExpectRip)
1925 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1926 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1927 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1928 if (TrapFrame.Ctx.rbx.u != uExpectRbx)
1929 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", uExpectRbx, TrapFrame.Ctx.rbx.u);
1930
1931 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
1932 Bs3TestFailedF("Expected EFLAGS = %#06RX64, got %#06RX64",
1933 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
1934 if (TrapFrame.Ctx.rax.u != Ctx.rax.u)
1935 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", Ctx.rax.u, TrapFrame.Ctx.rax.u);
1936 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1937 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1938 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1939 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1940 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1941 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1942 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1943 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1944 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1945 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1946 if (uMemSrc != uMemSrcExpect)
1947 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
1948 }
1949 }
1950 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1951 }
1952
1953 return 0;
1954}
1955
1956
1957BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_andn)(uint8_t bMode)
1958{
1959#define ANDN_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_ZF | X86_EFL_OF | X86_EFL_SF)
1960#define ANDN_IGNORE_EFLAGS (uint16_t)(X86_EFL_AF | X86_EFL_PF) /* undefined, ignoring for now */
1961 static const struct
1962 {
1963 FPFNBS3FAR pfnWorker;
1964 bool fMemSrc;
1965 uint8_t cbInstr;
1966 RTCCUINTXREG uSrc1;
1967 RTCCUINTXREG uSrc2;
1968 RTCCUINTXREG uOut;
1969 uint16_t fEFlags;
1970 } s_aTests[] =
1971 {
1972 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1973 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #0
1974 0, 0, /* -> */ 0, X86_EFL_ZF },
1975 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #1
1976 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1977 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #2
1978 0, 0, /* -> */ 0, X86_EFL_ZF },
1979 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #3
1980 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1981
1982 /* 32-bit register width */
1983 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #4
1984 0, 0, /* -> */ 0, X86_EFL_ZF },
1985 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #5
1986 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1987 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #6
1988 0, 0, /* -> */ 0, X86_EFL_ZF },
1989 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #7
1990 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1991
1992 };
1993
1994 BS3REGCTX Ctx;
1995 BS3TRAPFRAME TrapFrame;
1996 unsigned i, j;
1997 uint32_t uStdExtFeatEbx = 0;
1998 bool fSupportsAndN;
1999
2000 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2001 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2002 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1);
2003
2004 /* Ensure the structures are allocated before we sample the stack pointer. */
2005 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2006 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2007
2008 /*
2009 * Create test context.
2010 */
2011 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2012
2013 /*
2014 * Do the tests twice, first with all flags set, then once again with
2015 * flags cleared. The flags are not supposed to be touched at all.
2016 */
2017 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2018 for (j = 0; j < 2; j++)
2019 {
2020 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2021 {
2022 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
2023 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2024 uint64_t uExpectRax, uExpectRip;
2025 RTCCUINTXREG uMemSrc2, uMemSrc2Expect;
2026
2027 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2028 Ctx.rcx.uCcXReg = s_aTests[i].uSrc1;
2029 if (!s_aTests[i].fMemSrc)
2030 {
2031 Ctx.rbx.uCcXReg = s_aTests[i].uSrc2;
2032 uMemSrc2Expect = uMemSrc2 = ~s_aTests[i].uSrc2;
2033 }
2034 else
2035 {
2036 uMemSrc2Expect = uMemSrc2 = s_aTests[i].uSrc2;
2037 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc2);
2038 }
2039 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2040 uExpectRax = fOkay ? s_aTests[i].uOut : Ctx.rax.u;
2041 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2042 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2043
2044 if ( TrapFrame.bXcpt != bExpectXcpt
2045 || TrapFrame.Ctx.rip.u != uExpectRip
2046 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2047 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2048 || TrapFrame.Ctx.rax.u != uExpectRax
2049 /* check that nothing else really changed: */
2050 || (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
2051 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS)
2052 || (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2053 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2054 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2055 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2056 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2057 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2058 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2059 || uMemSrc2 != uMemSrc2Expect
2060 )
2061 {
2062 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
2063 if (TrapFrame.bXcpt != bExpectXcpt)
2064 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2065 if (TrapFrame.Ctx.rip.u != uExpectRip)
2066 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2067 if (TrapFrame.Ctx.rax.u != uExpectRax)
2068 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2069 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2070 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2071 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2072 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2073 if ( (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
2074 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS))
2075 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2076 (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS);
2077 if ( (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2078 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS))
2079 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2080 Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS,
2081 TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS);
2082
2083 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2084 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2085 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2086 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2087 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2088 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2089 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2090 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2091 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2092 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2093 if (uMemSrc2 != uMemSrc2Expect)
2094 Bs3TestFailedF("Expected uMemSrc2 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc2Expect, (uint64_t)uMemSrc2);
2095 }
2096 }
2097 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2098 }
2099
2100 return 0;
2101}
2102
2103/*
2104 * For testing BEXTR, SHLX SARX & SHRX.
2105 */
2106typedef struct BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T
2107{
2108 RTCCUINTXREG uSrc1;
2109 RTCCUINTXREG uSrc2;
2110 RTCCUINTXREG uOut;
2111 uint16_t fEflOut;
2112} BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T;
2113
2114typedef struct BS3CPUINSTR2_TEST_Gy_Ey_By_T
2115{
2116 FPFNBS3FAR pfnWorker;
2117 bool fMemSrc;
2118 uint8_t cbInstr;
2119 uint8_t cSubTests;
2120 BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const *paSubTests;
2121} BS3CPUINSTR2_TEST_Gy_Ey_By_T;
2122
2123static uint8_t bs3CpuInstr2_Common_Gy_Ey_By(uint8_t bMode, BS3CPUINSTR2_TEST_Gy_Ey_By_T const *paTests, unsigned cTests,
2124 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
2125{
2126 BS3REGCTX Ctx;
2127 BS3TRAPFRAME TrapFrame;
2128 unsigned i, j, k;
2129 uint32_t uStdExtFeatEbx = 0;
2130 bool fSupportsInstr;
2131
2132 fEflCheck &= ~fEflIgnore;
2133
2134 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2135 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2136 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
2137
2138 /* Ensure the structures are allocated before we sample the stack pointer. */
2139 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2140 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2141
2142 /*
2143 * Create test context.
2144 */
2145 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2146
2147 /*
2148 * Do the tests twice, first with all flags set, then once again with
2149 * flags cleared. The flags are not supposed to be touched at all.
2150 */
2151 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2152 for (j = 0; j < 2; j++)
2153 {
2154 for (i = 0; i < cTests; i++)
2155 {
2156 for (k = 0; k < paTests[i].cSubTests; k++)
2157 {
2158 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
2159 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2160 uint64_t uExpectRax, uExpectRip;
2161 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
2162
2163 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2164 Ctx.rcx.uCcXReg = paTests[i].paSubTests[k].uSrc2;
2165 if (!paTests[i].fMemSrc)
2166 {
2167 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc1;
2168 uMemSrc1Expect = uMemSrc1 = ~paTests[i].paSubTests[k].uSrc1;
2169 }
2170 else
2171 {
2172 uMemSrc1Expect = uMemSrc1 = paTests[i].paSubTests[k].uSrc1;
2173 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
2174 }
2175 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
2176 uExpectRax = fOkay ? paTests[i].paSubTests[k].uOut : Ctx.rax.u;
2177 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
2178 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2179
2180 if ( TrapFrame.bXcpt != bExpectXcpt
2181 || TrapFrame.Ctx.rip.u != uExpectRip
2182 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2183 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2184 || TrapFrame.Ctx.rax.u != uExpectRax
2185 /* check that nothing else really changed: */
2186 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2187 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
2188 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2189 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2190 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2191 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2192 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2193 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2194 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2195 || uMemSrc1 != uMemSrc1Expect
2196 )
2197 {
2198 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT,
2199 i, k, paTests[i].paSubTests[k].uSrc1, paTests[i].paSubTests[k].uSrc2);
2200 if (TrapFrame.bXcpt != bExpectXcpt)
2201 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2202 if (TrapFrame.Ctx.rip.u != uExpectRip)
2203 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2204 if (TrapFrame.Ctx.rax.u != uExpectRax)
2205 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2206 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2207 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2208 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2209 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2210 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2211 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
2212 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2213 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
2214 TrapFrame.Ctx.rflags.u16 & fEflCheck);
2215 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2216 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
2217 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2218 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
2219 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
2220
2221 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2222 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2223 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2224 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2225 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2226 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2227 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2228 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2229 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2230 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2231 if (uMemSrc1 != uMemSrc1Expect)
2232 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
2233 }
2234 }
2235 }
2236 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2237 }
2238
2239 return 0;
2240}
2241
2242
2243BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bextr)(uint8_t bMode)
2244{
2245 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2246 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2247 {
2248 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
2249 { 0, RT_MAKE_U16(16, 33), /* -> */ 0, X86_EFL_ZF },
2250 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0},
2251 { ~(RTCCUINTXREG)7, RT_MAKE_U16(40, 8), /* -> */ ARCH_BITS == 64 ? 0xff : 0x00, ARCH_BITS == 64 ? 0 : X86_EFL_ZF },
2252 };
2253
2254 /* 32-bit register width */
2255 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2256 {
2257 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
2258 { 0, RT_MAKE_U16(16, 18), /* -> */ 0, X86_EFL_ZF },
2259 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0 },
2260 { ~(RTCCUINTXREG)7, RT_MAKE_U16(24, 8), /* -> */ 0xff, 0 },
2261 { ~(RTCCUINTXREG)7, RT_MAKE_U16(31, 9), /* -> */ 1, 0 },
2262 { ~(RTCCUINTXREG)7, RT_MAKE_U16(42, 8), /* -> */ 0, X86_EFL_ZF },
2263 };
2264
2265 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2266 {
2267 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2268 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2269 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2270 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2271 };
2272 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2273 X86_EFL_STATUS_BITS, X86_EFL_AF | X86_EFL_SF | X86_EFL_PF);
2274}
2275
2276
2277BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bzhi)(uint8_t bMode)
2278{
2279 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2280 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2281 {
2282 { 0, 0, /* -> */ 0, X86_EFL_ZF },
2283 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
2284 { 0, 64, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2285 { ~(RTCCUINTXREG)0, 64, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
2286 { ~(RTCCUINTXREG)0, 63,
2287 /* -> */ ARCH_BITS >= 64 ? ~(RTCCUINTXREG)0 >> 1 : ~(RTCCUINTXREG)0, ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
2288 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 24, /* -> */ UINT32_C(0x00849607), 0 },
2289 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 33,
2290 /* -> */ ARCH_BITS >= 64 ? UINT64_C(0x1e3849607) : UINT32_C(0xe3849607), ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
2291 };
2292
2293 /* 32-bit register width */
2294 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2295 {
2296 { 0, 0, /* -> */ 0, X86_EFL_ZF },
2297 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
2298 { 0, 32, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2299 { ~(RTCCUINTXREG)0, 32, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
2300 { ~(RTCCUINTXREG)0, 31, /* -> */ UINT32_MAX >> 1, 0 },
2301 { UINT32_C(0x1230fd34), 15, /* -> */ UINT32_C(0x00007d34), 0 },
2302 };
2303
2304 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2305 {
2306 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2307 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2308 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2309 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2310 };
2311 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2,
2312 X86_EFL_STATUS_BITS, 0);
2313}
2314
2315
2316/** @note This is a Gy_By_Ey format instruction, so we're switching the two
2317 * source registers around when calling bs3CpuInstr2_Common_Gy_Ey_By.
2318 * Sorry for the confusion, but it saves some unnecessary code dup. */
2319BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pdep)(uint8_t bMode)
2320{
2321 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2322 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2323 { /* Mask (RBX/[FS:xBX]), source=RCX */
2324 { 0, 0, /* -> */ 0, 0 },
2325 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2326 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2327 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
2328#if ARCH_BITS >= 64
2329 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x3586049947589201), 0 },
2330 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x3586049947588000), 0 },
2331#endif
2332 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
2333 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x47588000), 0 },
2334 };
2335
2336 /* 32-bit register width */
2337 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2338 { /* Mask (EBX/[FS:xBX]), source=ECX */
2339 { 0, 0, /* -> */ 0, 0 },
2340 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2341 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2342 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
2343 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x01010101), 0 },
2344 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x01010000), 0 },
2345 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
2346 };
2347
2348 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2349 {
2350 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2351 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2352 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2353 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2354 };
2355 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
2356}
2357
2358
2359/** @note Same note as for bs3CpuInstr2_pdep */
2360BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pext)(uint8_t bMode)
2361{
2362 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2363 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2364 { /* Mask (RBX/[FS:xBX]), source=RCX */
2365 { 0, 0, /* -> */ 0, 0 },
2366 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2367 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2368 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
2369#if ARCH_BITS >= 64
2370 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x00000000007fffff), 0 },
2371 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x00000000007ffffe), 0 },
2372#endif
2373 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
2374 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
2375 };
2376
2377 /* 32-bit register width */
2378 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2379 { /* Mask (EBX/[FS:xBX]), source=ECX */
2380 { 0, 0, /* -> */ 0, 0 },
2381 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2382 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2383 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
2384 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x0000000f), 0 },
2385 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x0000000e), 0 },
2386 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
2387 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
2388 };
2389
2390 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2391 {
2392 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2393 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2394 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2395 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2396 };
2397 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
2398}
2399
2400
2401BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shlx)(uint8_t bMode)
2402{
2403 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2404 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2405 {
2406 { 0, 0, /* -> */ 0, 0 },
2407 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2408 { ~(RTCCUINTXREG)7, 8, /* -> */ ~(RTCCUINTXREG)0x7ff, 0},
2409 { ~(RTCCUINTXREG)7, 40, /* -> */ ~(RTCCUINTXREG)7 << (ARCH_BITS == 64 ? 40 : 8), 0 },
2410 { ~(RTCCUINTXREG)7, 72, /* -> */ ~(RTCCUINTXREG)7 << 8, 0 },
2411 };
2412
2413 /* 32-bit register width */
2414 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2415 {
2416 { 0, 0, /* -> */ 0, 0 },
2417 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2418 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
2419 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
2420 };
2421
2422 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2423 {
2424 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2425 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2426 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2427 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2428 };
2429 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2430 0, 0);
2431}
2432
2433
2434BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sarx)(uint8_t bMode)
2435{
2436 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2437 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2438 {
2439 { 0, 0, /* -> */ 0, 0 },
2440 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2441 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ ~(RTCCUINTXREG)0, 0 },
2442 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ ~(RTCCUINTXREG)0, 0 },
2443 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
2444 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
2445 };
2446
2447 /* 32-bit register width */
2448 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2449 {
2450 { 0, 0, /* -> */ 0, 0 },
2451 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2452 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0xffffff80), 0 },
2453 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0xffffff80), 0 },
2454 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
2455 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
2456 };
2457
2458 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2459 {
2460 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2461 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2462 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2463 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2464 };
2465 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2466 0, 0);
2467}
2468
2469
2470BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shrx)(uint8_t bMode)
2471{
2472 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2473 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2474 {
2475 { 0, 0, /* -> */ 0, 0 },
2476 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2477 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ 1, 0 },
2478 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ 1, 0 },
2479 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
2480 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
2481 };
2482
2483 /* 32-bit register width */
2484 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2485 {
2486 { 0, 0, /* -> */ 0, 0 },
2487 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2488 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0x80), 0 },
2489 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0x80), 0 },
2490 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
2491 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
2492 };
2493
2494 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2495 {
2496 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2497 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2498 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2499 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2500 };
2501 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2502 0, 0);
2503}
2504
2505
2506/*
2507 * For testing BLSR, BLSMSK, and BLSI.
2508 */
2509typedef struct BS3CPUINSTR2_SUBTEST_By_Ey_T
2510{
2511 RTCCUINTXREG uSrc;
2512 RTCCUINTXREG uDst;
2513 uint16_t fEflOut;
2514} BS3CPUINSTR2_SUBTEST_By_Ey_T;
2515
2516typedef struct BS3CPUINSTR2_TEST_By_Ey_T
2517{
2518 FPFNBS3FAR pfnWorker;
2519 bool fMemSrc;
2520 uint8_t cbInstr;
2521 uint8_t cSubTests;
2522 BS3CPUINSTR2_SUBTEST_By_Ey_T const *paSubTests;
2523} BS3CPUINSTR2_TEST_By_Ey_T;
2524
2525static uint8_t bs3CpuInstr2_Common_By_Ey(uint8_t bMode, BS3CPUINSTR2_TEST_By_Ey_T const *paTests, unsigned cTests,
2526 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
2527{
2528 BS3REGCTX Ctx;
2529 BS3TRAPFRAME TrapFrame;
2530 unsigned i, j, k;
2531 uint32_t uStdExtFeatEbx = 0;
2532 bool fSupportsInstr;
2533
2534 fEflCheck &= ~fEflIgnore;
2535
2536 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2537 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2538 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
2539
2540 /* Ensure the structures are allocated before we sample the stack pointer. */
2541 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2542 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2543
2544 /*
2545 * Create test context.
2546 */
2547 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2548
2549 /*
2550 * Do the tests twice, first with all flags set, then once again with
2551 * flags cleared. The flags are not supposed to be touched at all.
2552 */
2553 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2554 for (j = 0; j < 2; j++)
2555 {
2556 for (i = 0; i < cTests; i++)
2557 {
2558 for (k = 0; k < paTests[i].cSubTests; k++)
2559 {
2560 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
2561 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2562 uint64_t uExpectRax, uExpectRip;
2563 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2564
2565 Ctx.rax.uCcXReg = ~paTests[i].paSubTests[k].uSrc ^ 0x593e7591;
2566 if (!paTests[i].fMemSrc)
2567 {
2568 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
2569 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
2570 }
2571 else
2572 {
2573 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
2574 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2575 }
2576 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
2577 uExpectRax = fOkay ? paTests[i].paSubTests[k].uDst : Ctx.rax.u;
2578 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
2579 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2580
2581 if ( TrapFrame.bXcpt != bExpectXcpt
2582 || TrapFrame.Ctx.rip.u != uExpectRip
2583 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2584 || TrapFrame.Ctx.rax.u != uExpectRax
2585 /* check that nothing else really changed: */
2586 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2587 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
2588 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2589 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2590 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2591 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2592 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2593 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2594 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2595 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2596 || uMemSrc != uMemSrcExpect
2597 )
2598 {
2599 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
2600 i, k, paTests[i].paSubTests[k].uSrc);
2601 if (TrapFrame.bXcpt != bExpectXcpt)
2602 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2603 if (TrapFrame.Ctx.rip.u != uExpectRip)
2604 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2605 if (TrapFrame.Ctx.rax.u != uExpectRax)
2606 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2607 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2608 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2609 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2610 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
2611 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2612 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
2613 TrapFrame.Ctx.rflags.u16 & fEflCheck);
2614 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2615 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
2616 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2617 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
2618 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
2619
2620 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2621 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2622 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2623 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2624 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2625 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2626 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2627 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2628 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2629 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2630 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2631 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2632 if (uMemSrc != uMemSrcExpect)
2633 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2634 }
2635 }
2636 }
2637 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2638 }
2639
2640 return 0;
2641}
2642
2643
2644BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsr)(uint8_t bMode)
2645{
2646 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2647 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2648 {
2649 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2650 { 1, /* -> */ 0, X86_EFL_ZF },
2651 { 2, /* -> */ 0, X86_EFL_ZF },
2652 { 3, /* -> */ 2, 0 },
2653 { 5, /* -> */ 4, 0 },
2654 { 6, /* -> */ 4, 0 },
2655 { 7, /* -> */ 6, 0 },
2656 { 9, /* -> */ 8, 0 },
2657 { 10, /* -> */ 8, 0 },
2658 { ~(RTCCUINTXREG)1, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
2659 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2), X86_EFL_SF },
2660 };
2661
2662 /* 32-bit register width */
2663 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2664 {
2665 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2666 { 1, /* -> */ 0, X86_EFL_ZF },
2667 { ~(RTCCUINTXREG)1, /* -> */ UINT32_C(0xfffffffc), X86_EFL_SF },
2668 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x80000000), X86_EFL_SF },
2669 };
2670
2671 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2672 {
2673 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2674 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2675 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2676 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2677 };
2678 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2679 X86_EFL_STATUS_BITS, 0);
2680}
2681
2682
2683BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsmsk)(uint8_t bMode)
2684{
2685 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2686 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2687 {
2688 { 0, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
2689 { 1, /* -> */ 1, 0 },
2690 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2691 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ ~((RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2)), 0 },
2692 };
2693
2694 /* 32-bit register width */
2695 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2696 {
2697 { 0, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
2698 { 1, /* -> */ 1, 0 },
2699 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2700 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x7fffffff), 0},
2701 };
2702
2703 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2704 {
2705 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2706 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2707 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2708 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2709 };
2710 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2711 X86_EFL_STATUS_BITS, 0);
2712}
2713
2714
2715BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsi)(uint8_t bMode)
2716{
2717 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2718 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2719 {
2720 { 0, /* -> */ 0, X86_EFL_ZF },
2721 { 1, /* -> */ 1, X86_EFL_CF },
2722 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2723 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), X86_EFL_CF },
2724 };
2725
2726 /* 32-bit register width */
2727 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2728 {
2729 { 0, /* -> */ 0, X86_EFL_ZF },
2730 { 1, /* -> */ 1, X86_EFL_CF },
2731 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2732 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x40000000), X86_EFL_CF },
2733 };
2734
2735 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2736 {
2737 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2738 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2739 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2740 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2741 };
2742 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2743 X86_EFL_STATUS_BITS, 0);
2744}
2745
2746
2747/*
2748 * MULX (BMI2) - destination registers (/r & vvvv) = r/m * rDX
2749 */
2750BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mulx)(uint8_t bMode)
2751{
2752 static const struct
2753 {
2754 FPFNBS3FAR pfnWorker;
2755 bool fMemSrc;
2756 bool fSameDst;
2757 uint8_t cbInstr;
2758 RTCCUINTXREG uSrc1;
2759 RTCCUINTXREG uSrc2;
2760 RTCCUINTXREG uDst1;
2761 RTCCUINTXREG uDst2;
2762 } s_aTests[] =
2763 {
2764 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2765 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #0
2766 0, 0, /* -> */ 0, 0 },
2767 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #1
2768 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2769 { BS3_CMN_NM(bs3CpuInstr2_mulx_RCX_RCX_RBX_RDX_icebp), false, true, 5, // #2
2770 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, ~(RTCCUINTXREG)1 },
2771 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #3
2772 2, 2, /* -> */ 0, 4 },
2773 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #4
2774 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2775
2776 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #5
2777 0, 0, /* -> */ 0, 0 },
2778 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #6
2779 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2780 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #7
2781 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2782
2783 /* 32-bit register width */
2784 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #8
2785 0, 0, /* -> */ 0, 0 },
2786 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #9
2787 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2788 { BS3_CMN_NM(bs3CpuInstr2_mulx_ECX_ECX_EBX_EDX_icebp), false, true, 5, // #10
2789 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, ~(uint32_t)1 },
2790 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #11
2791 2, 2, /* -> */ 0, 4 },
2792 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #12
2793 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2794
2795 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #13
2796 0, 0, /* -> */ 0, 0 },
2797 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #14
2798 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2799 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #15
2800 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2801 };
2802
2803 BS3REGCTX Ctx;
2804 BS3TRAPFRAME TrapFrame;
2805 unsigned i, j;
2806 uint32_t uStdExtFeatEbx = 0;
2807 bool fSupportsAndN;
2808
2809 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2810 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2811 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
2812
2813 /* Ensure the structures are allocated before we sample the stack pointer. */
2814 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2815 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2816
2817 /*
2818 * Create test context.
2819 */
2820 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2821
2822 /*
2823 * Do the tests twice, first with all flags set, then once again with
2824 * flags cleared. The flags are not supposed to be touched at all.
2825 */
2826 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2827 for (j = 0; j < 2; j++)
2828 {
2829 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2830 {
2831 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
2832 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2833 uint64_t uExpectRax, uExpectRcx, uExpectRip;
2834 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
2835
2836 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2837 Ctx.rcx.uCcXReg = RTCCUINTXREG_MAX * 4095;
2838 Ctx.rdx.uCcXReg = s_aTests[i].uSrc2;
2839 if (!s_aTests[i].fMemSrc)
2840 {
2841 Ctx.rbx.uCcXReg = s_aTests[i].uSrc1;
2842 uMemSrc1Expect = uMemSrc1 = ~s_aTests[i].uSrc1;
2843 }
2844 else
2845 {
2846 uMemSrc1Expect = uMemSrc1 = s_aTests[i].uSrc1;
2847 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
2848 }
2849 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2850 uExpectRax = fOkay && !s_aTests[i].fSameDst ? s_aTests[i].uDst1 : Ctx.rax.u;
2851 uExpectRcx = fOkay ? s_aTests[i].uDst2 : Ctx.rcx.u;
2852 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2853 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2854
2855 if ( TrapFrame.bXcpt != bExpectXcpt
2856 || TrapFrame.Ctx.rip.u != uExpectRip
2857 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2858 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2859 || TrapFrame.Ctx.rax.u != uExpectRax
2860 || TrapFrame.Ctx.rcx.u != uExpectRcx
2861 /* check that nothing else really changed: */
2862 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
2863 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2864 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2865 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2866 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2867 || uMemSrc1 != uMemSrc1Expect
2868 )
2869 {
2870 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
2871 if (TrapFrame.bXcpt != bExpectXcpt)
2872 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2873 if (TrapFrame.Ctx.rip.u != uExpectRip)
2874 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2875 if (TrapFrame.Ctx.rax.u != uExpectRax)
2876 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2877 if (TrapFrame.Ctx.rcx.u != uExpectRcx)
2878 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", uExpectRcx, TrapFrame.Ctx.rcx.u);
2879 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2880 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2881 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2882 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2883
2884 if ( (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
2885 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2886 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
2887 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2888 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2889 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2890 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2891 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2892 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2893 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2894 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2895 if (uMemSrc1 != uMemSrc1Expect)
2896 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
2897 }
2898 }
2899 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2900 }
2901
2902 return 0;
2903}
2904
2905
2906/*
2907 * POPCNT - Intel: POPCNT; AMD: ABM.
2908 */
2909BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_popcnt)(uint8_t bMode)
2910{
2911 static const struct
2912 {
2913 FPFNBS3FAR pfnWorker;
2914 bool fMemSrc;
2915 uint8_t cWidth;
2916 uint8_t cbInstr;
2917 RTCCUINTXREG uSrc;
2918 RTCCUINTXREG uDst;
2919 uint16_t fEFlags;
2920 } s_aTests[] =
2921 {
2922 /* 16-bit register width */
2923 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #0
2924 0, /* -> */ 0, X86_EFL_ZF },
2925 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #1
2926 ~(RTCCUINTXREG)0, /* -> */ 16, 0 },
2927 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #2
2928 UINT16_C(0xffff), /* -> */ 16, 0 },
2929 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #3
2930 UINT16_C(0x0304), /* -> */ 3, 0 },
2931 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #4
2932 UINT16_C(0xd569), /* -> */ 9, 0},
2933 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #5
2934 0, /* -> */ 0, X86_EFL_ZF },
2935
2936 /* 32-bit register width */
2937 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #6
2938 0, /* -> */ 0, X86_EFL_ZF },
2939 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #7
2940 ~(RTCCUINTXREG)0, /* -> */ 32, 0},
2941 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #8
2942 UINT32_C(0x01020304), /* -> */ 5, 0},
2943 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #9
2944 0, /* -> */ 0, X86_EFL_ZF },
2945 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #10
2946 UINT32_C(0x49760948), /* -> */ 12, 0 },
2947
2948#if ARCH_BITS == 64
2949 /* 64-bit register width */
2950 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #11
2951 0, /* -> */ 0, X86_EFL_ZF },
2952 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #12
2953 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2954 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #13
2955 UINT64_C(0x1234123412341234), /* -> */ 5*4, 0 },
2956 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #14
2957 0, /* -> */ 0, X86_EFL_ZF },
2958 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #15
2959 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2960 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #16
2961 UINT64_C(0x5908760293769087), /* -> */ 26, 0 },
2962#endif
2963 };
2964
2965 BS3REGCTX Ctx;
2966 BS3TRAPFRAME TrapFrame;
2967 unsigned i, j;
2968 bool const fSupportsPopCnt = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2969 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_POPCNT);
2970
2971 /* Ensure the structures are allocated before we sample the stack pointer. */
2972 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2973 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2974
2975 /*
2976 * Create test context.
2977 */
2978 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2979
2980 /*
2981 * Do the tests twice, first with all flags set, then once again with
2982 * flags cleared. The flags are not supposed to be touched at all.
2983 */
2984 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2985 for (j = 0; j < 2; j++)
2986 {
2987 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2988 {
2989 bool const fOkay = fSupportsPopCnt;
2990 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2991 uint64_t uExpectRax, uExpectRip;
2992 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2993
2994 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2995 if (!s_aTests[i].fMemSrc)
2996 {
2997 Ctx.rbx.uCcXReg = s_aTests[i].uSrc;
2998 uMemSrcExpect = uMemSrc = ~s_aTests[i].uSrc;
2999 }
3000 else
3001 {
3002 uMemSrcExpect = uMemSrc = s_aTests[i].uSrc;
3003 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
3004 }
3005 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3006 uExpectRax = fOkay ? s_aTests[i].uDst : Ctx.rax.u;
3007 if (s_aTests[i].cWidth == 16)
3008 uExpectRax = (uExpectRax & UINT16_MAX) | (Ctx.rax.u & ~(uint64_t)UINT16_MAX);
3009
3010 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
3011 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3012
3013 if ( TrapFrame.bXcpt != bExpectXcpt
3014 || TrapFrame.Ctx.rip.u != uExpectRip
3015 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
3016 || TrapFrame.Ctx.rax.u != uExpectRax
3017 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16)
3018 /* check that nothing else really changed: */
3019 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
3020 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
3021 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
3022 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
3023 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
3024 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
3025 || uMemSrc != uMemSrcExpect
3026 )
3027 {
3028 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc);
3029 if (TrapFrame.bXcpt != bExpectXcpt)
3030 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
3031 if (TrapFrame.Ctx.rip.u != uExpectRip)
3032 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
3033 if (TrapFrame.Ctx.rax.u != uExpectRax)
3034 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
3035 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
3036 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
3037 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16))
3038 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32",
3039 fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
3040
3041 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3042 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3043 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3044 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3045 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3046 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3047 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3048 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3049 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3050 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3051 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3052 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3053 if (uMemSrc != uMemSrcExpect)
3054 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3055 }
3056 }
3057 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3058 }
3059
3060 return 0;
3061}
3062
3063/*
3064 * CRC32 - SSE4.2
3065 */
3066BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_crc32)(uint8_t bMode)
3067{
3068 typedef struct BS3CPUINSTR2_CRC32_VALUES_T
3069 {
3070 uint32_t uDstIn;
3071 uint32_t uDstOut;
3072 uint64_t uSrc;
3073 } BS3CPUINSTR2_CRC32_VALUES_T;
3074 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues1[] =
3075 {
3076 { UINT32_C(0000000000), UINT32_C(0000000000), UINT8_C(0000) },
3077 { UINT32_C(0xffffffff), UINT32_C(0x25502c8c), UINT8_C(0xea) },
3078 { UINT32_C(0x25502c8c), UINT32_C(0x474224a6), UINT8_C(0xea) },
3079 { UINT32_C(0x474224a6), UINT32_C(0x0c7f9048), UINT8_C(0xea) },
3080 { UINT32_C(0x0c7f9048), UINT32_C(0x39c5b9e0), UINT8_C(0x01) },
3081 { UINT32_C(0x39c5b9e0), UINT32_C(0x2493fabc), UINT8_C(0x04) },
3082 { UINT32_C(0x2493fabc), UINT32_C(0x0b05c4d6), UINT8_C(0x27) },
3083 { UINT32_C(0x0b05c4d6), UINT32_C(0xbe26a561), UINT8_C(0x2a) },
3084 { UINT32_C(0xbe26a561), UINT32_C(0xe1855652), UINT8_C(0x63) },
3085 { UINT32_C(0xe1855652), UINT32_C(0xc67efe3f), UINT8_C(0xa7) },
3086 { UINT32_C(0xc67efe3f), UINT32_C(0x227028cd), UINT8_C(0xfd) },
3087 { UINT32_C(0x227028cd), UINT32_C(0xf4559a1d), UINT8_C(0xea) },
3088 };
3089 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues2[] =
3090 {
3091 { UINT32_C(0000000000), UINT32_C(0000000000), UINT16_C(000000) },
3092 { UINT32_C(0xffffffff), UINT32_C(0xd550e2a0), UINT16_C(0x04d2) },
3093 { UINT32_C(0xd550e2a0), UINT32_C(0x38e07a0a), UINT16_C(0xe8cc) },
3094 { UINT32_C(0x38e07a0a), UINT32_C(0x60ebd519), UINT16_C(0x82a2) },
3095 { UINT32_C(0x60ebd519), UINT32_C(0xaaa127b5), UINT16_C(0x0fff) },
3096 { UINT32_C(0xaaa127b5), UINT32_C(0xb13175c6), UINT16_C(0x00ff) },
3097 { UINT32_C(0xb13175c6), UINT32_C(0x3a226f1b), UINT16_C(0x0300) },
3098 { UINT32_C(0x3a226f1b), UINT32_C(0xbaedef0c), UINT16_C(0x270f) },
3099 { UINT32_C(0xbaedef0c), UINT32_C(0x2d18866e), UINT16_C(0x3ff6) },
3100 { UINT32_C(0x2d18866e), UINT32_C(0x07e2e954), UINT16_C(0x9316) },
3101 { UINT32_C(0x07e2e954), UINT32_C(0x95f82acb), UINT16_C(0xa59c) },
3102 };
3103 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues4[] =
3104 {
3105 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000) },
3106 { UINT32_C(0xffffffff), UINT32_C(0xc9a7250e), UINT32_C(0x0270fa68) },
3107 { UINT32_C(0xc9a7250e), UINT32_C(0x7340d175), UINT32_C(0x23729736) },
3108 { UINT32_C(0x7340d175), UINT32_C(0x7e17b67d), UINT32_C(0x8bc75d35) },
3109 { UINT32_C(0x7e17b67d), UINT32_C(0x5028eb71), UINT32_C(0x0e9bebf2) },
3110 { UINT32_C(0x5028eb71), UINT32_C(0xc0a7f45a), UINT32_C(0x000001bc) },
3111 { UINT32_C(0xc0a7f45a), UINT32_C(0xa96f4012), UINT32_C(0x0034ba02) },
3112 { UINT32_C(0xa96f4012), UINT32_C(0xb27c0718), UINT32_C(0x0000002a) },
3113 { UINT32_C(0xb27c0718), UINT32_C(0x79fb2d35), UINT32_C(0x0153158e) },
3114 { UINT32_C(0x79fb2d35), UINT32_C(0x23434fc9), UINT32_C(0x02594882) },
3115 { UINT32_C(0x23434fc9), UINT32_C(0x354bf3b6), UINT32_C(0xb230b8f3) },
3116 };
3117#if ARCH_BITS >= 64
3118 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues8[] =
3119 {
3120 { UINT32_C(0000000000), UINT32_C(0000000000), UINT64_C(000000000000000000) },
3121 { UINT32_C(0xffffffff), UINT32_C(0xadc36834), UINT64_C(0x02b0b5e2a975c1cc) },
3122 { UINT32_C(0xadc36834), UINT32_C(0xf0e893c9), UINT64_C(0x823d386bf7517583) },
3123 { UINT32_C(0xf0e893c9), UINT32_C(0x1a22a837), UINT64_C(0x0481f5311fa061d0) },
3124 { UINT32_C(0x1a22a837), UINT32_C(0xcf8b6d61), UINT64_C(0x13fa70f64d52a92d) },
3125 { UINT32_C(0xcf8b6d61), UINT32_C(0xc7dde203), UINT64_C(0x3ccc8b035903d3e1) },
3126 { UINT32_C(0xc7dde203), UINT32_C(0xd42b5823), UINT64_C(0x0000011850ec2fac) },
3127 { UINT32_C(0xd42b5823), UINT32_C(0x8b1ce49e), UINT64_C(0x0000000000001364) },
3128 { UINT32_C(0x8b1ce49e), UINT32_C(0x1af31710), UINT64_C(0x000000057840205a) },
3129 { UINT32_C(0x1af31710), UINT32_C(0xdea35e8b), UINT64_C(0x2e5d93688d9a0bfa) },
3130 { UINT32_C(0xdea35e8b), UINT32_C(0x594c013a), UINT64_C(0x8ac7230489e7ffff) },
3131 { UINT32_C(0x594c013a), UINT32_C(0x27b061e5), UINT64_C(0x6bf037ae325f1c71) },
3132 { UINT32_C(0x27b061e5), UINT32_C(0x3120b5f7), UINT64_C(0x0fffffff34503556) },
3133 };
3134#endif
3135 static const struct
3136 {
3137 FPFNBS3FAR pfnWorker;
3138 bool fMemSrc;
3139 uint8_t cbOp;
3140 uint8_t cValues;
3141 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues;
3142 } s_aTests[] =
3143 {
3144 /* 8-bit register width */
3145 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BL_icebp), false, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
3146 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_byte_FSxBX_icebp), true, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
3147
3148 /* 16-bit register width */
3149 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BX_icebp), false, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
3150 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_word_FSxBX_icebp), true, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
3151
3152 /* 32-bit register width */
3153 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
3154 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
3155#if ARCH_BITS >= 64
3156 /* 32-bit register width */
3157 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
3158 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
3159#endif
3160 };
3161
3162 BS3REGCTX Ctx;
3163 BS3TRAPFRAME TrapFrame;
3164 unsigned i, j;
3165 bool const fSupportsCrc32 = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3166 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_SSE4_2);
3167
3168 /* Ensure the structures are allocated before we sample the stack pointer. */
3169 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3170 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3171
3172 /*
3173 * Create test context.
3174 */
3175 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3176
3177 /*
3178 * Do the tests twice, first with all flags set, then once again with
3179 * flags cleared. The flags are not supposed to be touched at all.
3180 */
3181 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3182 for (j = 0; j < 2; j++)
3183 {
3184 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3185 {
3186 uint8_t const cbOp = s_aTests[i].cbOp;
3187 unsigned const cValues = s_aTests[i].cValues;
3188 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3189 unsigned iValue;
3190 bool const fOkay = fSupportsCrc32;
3191 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3192 uint64_t const uSrcGarbage = ( cbOp == 1 ? UINT64_C(0x03948314d0f03400)
3193 : cbOp == 2 ? UINT64_C(0x03948314d0f00000)
3194 : cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
3195 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
3196 uint64_t uExpectRip;
3197
3198 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3199 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3200
3201 for (iValue = 0; iValue < cValues; iValue++)
3202 {
3203 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3204 uint64_t uMemSrc, uMemSrcExpect;
3205
3206 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
3207 if (!s_aTests[i].fMemSrc)
3208 {
3209 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
3210 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
3211 }
3212 else
3213 {
3214 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
3215 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
3216 }
3217
3218 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3219
3220 if ( TrapFrame.bXcpt != bExpectXcpt
3221 || TrapFrame.Ctx.rip.u != uExpectRip
3222 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
3223 || TrapFrame.Ctx.rax.u != uExpectRax
3224 /* check that nothing else really changed: */
3225 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
3226 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
3227 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
3228 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
3229 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
3230 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
3231 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
3232 || uMemSrc != uMemSrcExpect
3233 )
3234 {
3235 Bs3TestFailedF("test #%i value #%i failed: input %#RX32, %#RX64",
3236 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
3237 if (TrapFrame.bXcpt != bExpectXcpt)
3238 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
3239 if (TrapFrame.Ctx.rip.u != uExpectRip)
3240 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
3241 if (TrapFrame.Ctx.rax.u != uExpectRax)
3242 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
3243 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
3244 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
3245
3246 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
3247 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
3248 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3249 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3250 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3251 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3252 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3253 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3254 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3255 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3256 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3257 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3258 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3259 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3260 if (uMemSrc != uMemSrcExpect)
3261 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3262 }
3263 }
3264 }
3265 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3266 }
3267
3268 return 0;
3269}
3270
3271#if 0 /* Program for generating CRC32 value sets: */
3272#include <stdio.h>
3273#include <stdint.h>
3274#include <stdlib.h>
3275
3276int main(int argc, char **argv)
3277{
3278 int cbOp = atoi(argv[1]);
3279 uint32_t uBefore = atoi(argv[2]);
3280 int i = 3;
3281 while (i < argc)
3282 {
3283 unsigned long long uValue = strtoull(argv[i], NULL, 0);
3284 uint32_t uAfter = uBefore;
3285 switch (cbOp)
3286 {
3287 case 1:
3288 __asm__ __volatile__("crc32b %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint8_t)uValue));
3289 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT8_C(%#04x) },\n",
3290 uBefore, uAfter, (unsigned)(uint8_t)uValue);
3291 break;
3292 case 2:
3293 __asm__ __volatile__("crc32w %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint16_t)uValue));
3294 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT16_C(%#06x) },\n",
3295 uBefore, uAfter, (unsigned)(uint16_t)uValue);
3296 break;
3297 case 4:
3298 __asm__ __volatile__("crc32l %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint32_t)uValue));
3299 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT32_C(%#010x) },\n",
3300 uBefore, uAfter, (uint32_t)uValue);
3301 break;
3302 case 8:
3303 {
3304 uint64_t u64After = uBefore;
3305 __asm__ __volatile__("crc32q %2, %0" : "=r" (u64After) : "0" (u64After), "r" (uValue));
3306 uAfter = (uint32_t)u64After;
3307 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT64_C(%#018llx) },\n", uBefore, uAfter, uValue);
3308 break;
3309 }
3310 }
3311
3312 /* next */
3313 uBefore = uAfter;
3314 i++;
3315 }
3316 return 0;
3317}
3318#endif
3319
3320
3321/*
3322 * ADCX/ADOX - ADX
3323 */
3324BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_adcx_adox)(uint8_t bMode)
3325{
3326 typedef struct BS3CPUINSTR2_ADX_VALUES_T
3327 {
3328 uint64_t uDstOut;
3329 uint64_t uDstIn;
3330 uint64_t uSrc;
3331 bool fFlagIn;
3332 bool fFlagOut;
3333 } BS3CPUINSTR2_ADX_VALUES_T;
3334 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues4[] =
3335 {
3336 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000), false, false },
3337 { UINT32_C(0000000001), UINT32_C(0000000000), UINT32_C(0000000000), true, false },
3338
3339 { UINT32_C(0xfffffffe), UINT32_MAX / 2, UINT32_MAX / 2, false, false },
3340 { UINT32_C(0xffffffff), UINT32_MAX / 2, UINT32_MAX / 2, true, false },
3341
3342 { UINT32_C(0x7ffffffe), UINT32_MAX, UINT32_MAX / 2, false, true },
3343 { UINT32_C(0x7fffffff), UINT32_MAX, UINT32_MAX / 2, true, true },
3344
3345 { UINT32_C(0x7ffffffe), UINT32_MAX / 2, UINT32_MAX, false, true },
3346 { UINT32_C(0x7fffffff), UINT32_MAX / 2, UINT32_MAX, true, true },
3347
3348 { UINT32_C(0xfffffffe), UINT32_MAX, UINT32_MAX, false, true },
3349 { UINT32_C(0xffffffff), UINT32_MAX, UINT32_MAX, true, true },
3350 };
3351#if ARCH_BITS >= 64
3352 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues8[] =
3353 {
3354 { UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), false, false },
3355 { UINT64_C(00000000000000000001), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), true, false },
3356
3357 { UINT64_C(0xfffffffffffffffe), UINT64_MAX / 2, UINT64_MAX / 2, false, false },
3358 { UINT64_C(0xffffffffffffffff), UINT64_MAX / 2, UINT64_MAX / 2, true, false },
3359
3360 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX, UINT64_MAX / 2, false, true },
3361 { UINT64_C(0x7fffffffffffffff), UINT64_MAX, UINT64_MAX / 2, true, true },
3362
3363 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX / 2, UINT64_MAX, false, true },
3364 { UINT64_C(0x7fffffffffffffff), UINT64_MAX / 2, UINT64_MAX, true, true },
3365
3366 { UINT64_C(0xfffffffffffffffe), UINT64_MAX, UINT64_MAX, false, true },
3367 { UINT64_C(0xffffffffffffffff), UINT64_MAX, UINT64_MAX, true, true },
3368 };
3369#endif
3370 static const struct
3371 {
3372 FPFNBS3FAR pfnWorker;
3373 bool fMemSrc;
3374 uint8_t cbOp;
3375 uint8_t cValues;
3376 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues;
3377 uint32_t fEFlagsMod;
3378 } s_aTests[] =
3379 {
3380 /* 32-bit register width */
3381 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
3382 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
3383
3384 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
3385 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
3386#if ARCH_BITS >= 64
3387 /* 64-bit register width */
3388 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
3389 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
3390
3391 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
3392 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
3393#endif
3394 };
3395
3396 BS3REGCTX Ctx;
3397 BS3TRAPFRAME TrapFrame;
3398 unsigned i, j;
3399 bool fSupportsAdx = false;
3400
3401 if ( (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3402 && ASMCpuId_EAX(0) >= 7)
3403 {
3404 uint32_t fEbx = 0;
3405 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &fEbx, NULL, NULL);
3406 fSupportsAdx = RT_BOOL(fEbx & X86_CPUID_STEXT_FEATURE_EBX_ADX);
3407 }
3408
3409 /* Ensure the structures are allocated before we sample the stack pointer. */
3410 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3411 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3412
3413 /*
3414 * Create test context.
3415 */
3416 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3417
3418 /*
3419 * Do the tests twice, first with all flags set, then once again with
3420 * flags cleared. The flags are not supposed to be touched at all except for the one indicated (CF or OF).
3421 */
3422 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3423 for (j = 0; j < 2; j++)
3424 {
3425 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3426 {
3427 uint8_t const cbOp = s_aTests[i].cbOp;
3428 unsigned const cValues = s_aTests[i].cValues;
3429 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3430 uint32_t const fEFlagsMod = s_aTests[i].fEFlagsMod;
3431 unsigned iValue;
3432 bool const fOkay = fSupportsAdx;
3433 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3434 uint64_t const uSrcGarbage = ( cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
3435 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
3436 uint64_t uExpectRip;
3437
3438 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3439 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3440
3441 for (iValue = 0; iValue < cValues; iValue++)
3442 {
3443 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3444 uint64_t uMemSrc, uMemSrcExpect;
3445
3446 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
3447 if (!s_aTests[i].fMemSrc)
3448 {
3449 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
3450 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
3451 }
3452 else
3453 {
3454 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
3455 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
3456 }
3457
3458 Ctx.rflags.u16 &= ~fEFlagsMod;
3459 if (paValues[iValue].fFlagIn)
3460 Ctx.rflags.u16 |= fEFlagsMod;
3461
3462 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3463
3464 if (fOkay)
3465 {
3466 Ctx.rflags.u16 &= ~fEFlagsMod;
3467 if (paValues[iValue].fFlagOut)
3468 Ctx.rflags.u16 |= fEFlagsMod;
3469 }
3470
3471 if ( TrapFrame.bXcpt != bExpectXcpt
3472 || TrapFrame.Ctx.rip.u != uExpectRip
3473 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
3474 || TrapFrame.Ctx.rax.u != uExpectRax
3475 /* check that nothing else really changed: */
3476 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
3477 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
3478 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
3479 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
3480 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
3481 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
3482 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
3483 || uMemSrc != uMemSrcExpect
3484 )
3485 {
3486 Bs3TestFailedF("test #%i value #%i failed: input %#RX64, %#RX64",
3487 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
3488 if (TrapFrame.bXcpt != bExpectXcpt)
3489 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
3490 if (TrapFrame.Ctx.rip.u != uExpectRip)
3491 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
3492 if (TrapFrame.Ctx.rax.u != uExpectRax)
3493 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
3494 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
3495 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
3496
3497 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
3498 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
3499 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3500 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3501 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3502 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3503 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3504 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3505 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3506 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3507 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3508 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3509 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3510 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3511 if (uMemSrc != uMemSrcExpect)
3512 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3513 }
3514 }
3515 }
3516 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3517 }
3518
3519 return 0;
3520}
3521
3522
3523
3524/*
3525 * MOVBE
3526 */
3527BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_movbe)(uint8_t bMode)
3528{
3529 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3530
3531 typedef struct BS3CPUINSTR2_MOVBE_VALUES_T
3532 {
3533 RTCCUINTXREG uDstOut;
3534 RTCCUINTXREG uDstIn;
3535 RTCCUINTXREG uSrc;
3536 } BS3CPUINSTR2_MOVBE_VALUES_T;
3537 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues2[] =
3538 {
3539 { UINT64_C(0xc0dedeaddead3412), UINT64_C(0xc0dedeaddeadc0de), UINT16_C(0x1234) }
3540 };
3541 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues4MemSrc[] =
3542 {
3543 { UINT64_C(0x78563412), UINT64_C(0xc0dedeaddeadc0de), UINT32_C(0x12345678) }
3544 };
3545 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues4MemDst[] =
3546 {
3547 { UINT64_C(0xc0dedead78563412), UINT64_C(0xc0dedeaddeadc0de), UINT32_C(0x12345678) }
3548 };
3549#if ARCH_BITS >= 64
3550 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues8[] =
3551 {
3552 { UINT64_C(0xf0debc9a78563412), UINT64_C(0xc0dedeaddeadc0de), UINT64_C(0x123456789abcdef0) }
3553 };
3554#endif
3555 static const struct
3556 {
3557 FPFNBS3FAR pfnWorker;
3558 bool fMemSrc;
3559 uint8_t offIcebp;
3560 uint8_t cValues;
3561 BS3CPUINSTR2_MOVBE_VALUES_T const BS3_FAR *paValues;
3562 } s_aTests[] =
3563 {
3564 /* 16-bit register width */
3565 { BS3_CMN_NM(bs3CpuInstr2_movbe_AX_word_FSxBX_icebp), true, 6 + (ARCH_BITS != 16), RT_ELEMENTS(s_aValues2), s_aValues2 },
3566 { BS3_CMN_NM(bs3CpuInstr2_movbe_word_FSxBX_AX_icebp), false, 6 + (ARCH_BITS != 16), RT_ELEMENTS(s_aValues2), s_aValues2 },
3567 /* 32-bit register width */
3568 { BS3_CMN_NM(bs3CpuInstr2_movbe_EAX_dword_FSxBX_icebp), true, 6 + (ARCH_BITS == 16), RT_ELEMENTS(s_aValues4MemSrc), s_aValues4MemSrc },
3569 { BS3_CMN_NM(bs3CpuInstr2_movbe_dword_FSxBX_EAX_icebp), false, 6 + (ARCH_BITS == 16), RT_ELEMENTS(s_aValues4MemDst), s_aValues4MemDst },
3570#if ARCH_BITS >= 64
3571 /* 64-bit register width */
3572 { BS3_CMN_NM(bs3CpuInstr2_movbe_RAX_qword_FSxBX_icebp), true, 7, RT_ELEMENTS(s_aValues8), s_aValues8 },
3573 { BS3_CMN_NM(bs3CpuInstr2_movbe_qword_FSxBX_RAX_icebp), false, 7, RT_ELEMENTS(s_aValues8), s_aValues8 },
3574#endif
3575 };
3576
3577 BS3REGCTX Ctx;
3578 BS3REGCTX ExpectCtx;
3579 BS3TRAPFRAME TrapFrame;
3580 unsigned i, j;
3581 bool fSupportsMovBe = false;
3582
3583 if ( (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3584 && ASMCpuId_EAX(0) >= 1)
3585 {
3586 uint32_t fEcx = 0;
3587 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, NULL);
3588 fSupportsMovBe = RT_BOOL(fEcx & X86_CPUID_FEATURE_ECX_MOVBE);
3589 }
3590
3591 /* Ensure the structures are allocated before we sample the stack pointer. */
3592 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3593 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3594 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3595
3596 /*
3597 * Create test context.
3598 */
3599 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3600
3601 /*
3602 * Do the tests twice, first with all flags set, then once again with
3603 * flags cleared. The flags are not supposed to be touched at all.
3604 */
3605 g_usBs3TestStep = 0;
3606 for (j = 0; j < 2; j++)
3607 {
3608 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3609 {
3610 unsigned const cValues = s_aTests[i].cValues;
3611 BS3CPUINSTR2_MOVBE_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3612 unsigned iValue;
3613 bool const fOkay = fSupportsMovBe;
3614 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3615 uint64_t uExpectRip;
3616
3617 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3618 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3619
3620 for (iValue = 0; iValue < cValues; iValue++)
3621 {
3622 //uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3623 uint64_t uMem, uMemExpect;
3624
3625 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3626
3627 if (!s_aTests[i].fMemSrc)
3628 {
3629 /* Memory is destination */
3630 Ctx.rax.u64 = paValues[iValue].uSrc;
3631 ExpectCtx.rax.u64 = paValues[iValue].uSrc;
3632 uMem = paValues[iValue].uDstIn;
3633 uMemExpect = paValues[iValue].uDstOut;
3634 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMem);
3635 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rbx, &ExpectCtx.fs, &uMem);
3636 }
3637 else
3638 {
3639 /* Memory is source */
3640 uMemExpect = uMem = paValues[iValue].uSrc;
3641 Ctx.rax.u64 = paValues[iValue].uDstIn;
3642 ExpectCtx.rax.u64 = paValues[iValue].uDstOut;
3643 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMem);
3644 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rbx, &ExpectCtx.fs, &uMem);
3645 }
3646
3647 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3648 g_usBs3TestStep++;
3649
3650 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, bExpectXcpt == X86_XCPT_DB ? s_aTests[i].offIcebp : 0 /*cbPcAdjust*/,
3651 0 /*cbSpAcjust*/, 0 /*fExtraEfl*/, pszMode, g_usBs3TestStep)
3652 || TrapFrame.bXcpt != bExpectXcpt
3653 || uMem != uMemExpect
3654 )
3655 {
3656 if (TrapFrame.bXcpt != bExpectXcpt)
3657 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3658 if (uMem != uMemExpect)
3659 Bs3TestFailedF("Expected uMem = %#06RX64, got %#06RX64", (uint64_t)uMemExpect, (uint64_t)uMem);
3660 Bs3TestFailedF("^^^ iCfg=%u iWorker=%d iValue=%d\n",
3661 j, i, iValue);
3662 }
3663 }
3664 }
3665 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3666 }
3667
3668 return 0;
3669}
3670
3671
3672
3673/*
3674 * CMPXCHG8B
3675 */
3676BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg8b)(uint8_t bMode)
3677{
3678
3679 BS3REGCTX Ctx;
3680 BS3REGCTX ExpectCtx;
3681 BS3TRAPFRAME TrapFrame;
3682 RTUINT64U au64[3];
3683 PRTUINT64U pau64 = RT_ALIGN_PT(&au64[0], sizeof(RTUINT64U), PRTUINT64U);
3684 bool const fSupportCX8 = RT_BOOL(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_CX8);
3685 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3686 uint8_t bRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
3687 unsigned iFlags;
3688 unsigned offBuf;
3689 unsigned iMatch;
3690 unsigned iWorker;
3691 static struct
3692 {
3693 bool fLocked;
3694 uint8_t offIcebp;
3695 FNBS3FAR *pfnWorker;
3696 } const s_aWorkers[] =
3697 {
3698 { false, 5, BS3_CMN_NM(bs3CpuInstr2_cmpxchg8b_FSxDI_icebp) },
3699#if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PP16
3700 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg8b_FSxDI_icebp) },
3701#else
3702 { false, 6, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg8b_FSxDI_icebp) },
3703#endif
3704 { false, 6, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg8b_FSxDI_icebp) },
3705 { false, 6, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg8b_FSxDI_icebp) },
3706 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg8b_FSxDI_icebp) },
3707 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg8b_FSxDI_icebp) },
3708 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg8b_FSxDI_icebp) },
3709 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg8b_FSxDI_icebp) },
3710 };
3711
3712 /* Ensure the structures are allocated before we sample the stack pointer. */
3713 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3714 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3715 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3716 Bs3MemSet(pau64, 0, sizeof(pau64[0]) * 2);
3717
3718 /*
3719 * Create test context.
3720 */
3721 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3722 if (!fSupportCX8)
3723 Bs3TestPrintf("Note! CMPXCHG8B is not supported by the CPU!\n");
3724
3725 /*
3726 * Run the tests in all rings since alignment issues may behave
3727 * differently in ring-3 compared to ring-0.
3728 */
3729 for (;;)
3730 {
3731 /*
3732 * One loop with alignment checks disabled and one with enabled.
3733 */
3734 unsigned iCfg;
3735 for (iCfg = 0; iCfg < 2; iCfg++)
3736 {
3737 if (iCfg)
3738 {
3739 Ctx.rflags.u32 |= X86_EFL_AC;
3740 Ctx.cr0.u32 |= X86_CR0_AM;
3741 }
3742 else
3743 {
3744 Ctx.rflags.u32 &= ~X86_EFL_AC;
3745 Ctx.cr0.u32 &= ~X86_CR0_AM;
3746 }
3747
3748 /*
3749 * One loop with the normal variant and one with the locked one
3750 */
3751 g_usBs3TestStep = 0;
3752 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
3753 {
3754 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
3755
3756 /*
3757 * One loop with all status flags set, and one with them clear.
3758 */
3759 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3760 for (iFlags = 0; iFlags < 2; iFlags++)
3761 {
3762 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3763
3764 for (offBuf = 0; offBuf < sizeof(RTUINT64U); offBuf++)
3765 {
3766# define CX8_OLD_LO UINT32_C(0xcc9c4bbd)
3767# define CX8_OLD_HI UINT32_C(0x749549ab)
3768# define CX8_MISMATCH_LO UINT32_C(0x90f18981)
3769# define CX8_MISMATCH_HI UINT32_C(0xfd5b4000)
3770# define CX8_STORE_LO UINT32_C(0x51f6559b)
3771# define CX8_STORE_HI UINT32_C(0xd1b54963)
3772
3773 PRTUINT64U pBuf = (PRTUINT64U)&pau64->au8[offBuf];
3774
3775 ExpectCtx.rax.u = Ctx.rax.u = CX8_MISMATCH_LO;
3776 ExpectCtx.rdx.u = Ctx.rdx.u = CX8_MISMATCH_HI;
3777
3778 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rdi, &Ctx.fs, pBuf);
3779 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rdi, &ExpectCtx.fs, pBuf);
3780
3781 for (iMatch = 0; iMatch < 2; iMatch++)
3782 {
3783 uint8_t bExpectXcpt;
3784 pBuf->s.Lo = CX8_OLD_LO;
3785 pBuf->s.Hi = CX8_OLD_HI;
3786
3787 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3788 g_usBs3TestStep++;
3789 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
3790 bExpectXcpt = X86_XCPT_UD;
3791 if (fSupportCX8)
3792 {
3793 if ( offBuf
3794 && bRing == 3
3795 && bMode != BS3_MODE_RM
3796 && !BS3_MODE_IS_V86(bMode)
3797 && iCfg)
3798 {
3799 bExpectXcpt = X86_XCPT_AC;
3800 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
3801 }
3802 else
3803 {
3804 bExpectXcpt = X86_XCPT_DB;
3805
3806 ExpectCtx.rax.u = CX8_OLD_LO;
3807 ExpectCtx.rdx.u = CX8_OLD_HI;
3808
3809 if (iMatch & 1)
3810 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
3811 else
3812 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
3813 }
3814
3815 /* Kludge! Looks like EFLAGS.AC is cleared when raising #GP in real mode on an i7-6700K. WEIRD! */
3816 if (bMode == BS3_MODE_RM && (Ctx.rflags.u32 & X86_EFL_AC))
3817 {
3818 if (TrapFrame.Ctx.rflags.u32 & X86_EFL_AC)
3819 Bs3TestFailedF("Expected EFLAGS.AC to be cleared (bXcpt=%d)", TrapFrame.bXcpt);
3820 TrapFrame.Ctx.rflags.u32 |= X86_EFL_AC;
3821 }
3822 }
3823
3824 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, bExpectXcpt == X86_XCPT_DB ? s_aWorkers[iWorker].offIcebp : 0, 0 /*cbSpAdjust*/,
3825 bExpectXcpt == X86_XCPT_DB || BS3_MODE_IS_16BIT_SYS(bMode) ? 0 : X86_EFL_RF, pszMode, g_usBs3TestStep)
3826 || TrapFrame.bXcpt != bExpectXcpt)
3827 {
3828 if (TrapFrame.bXcpt != bExpectXcpt)
3829 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3830 Bs3TestFailedF("^^^ bRing=%u iCfg=%d iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n",
3831 bRing, iCfg, iWorker, iFlags, offBuf, iMatch);
3832 ASMHalt();
3833 }
3834
3835 ExpectCtx.rax.u = Ctx.rax.u = CX8_OLD_LO;
3836 ExpectCtx.rdx.u = Ctx.rdx.u = CX8_OLD_HI;
3837 }
3838 }
3839 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3840 }
3841 }
3842 } /* for each test config. */
3843
3844 /*
3845 * Next ring.
3846 */
3847 bRing++;
3848 if (bRing > 3 || bMode == BS3_MODE_RM)
3849 break;
3850 Bs3RegCtxConvertToRingX(&Ctx, bRing);
3851 }
3852
3853 return 0;
3854}
3855
3856
3857
3858/*
3859 *
3860 */
3861# if ARCH_BITS == 64
3862
3863BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b)(uint8_t bMode)
3864{
3865 BS3REGCTX Ctx;
3866 BS3REGCTX ExpectCtx;
3867 BS3TRAPFRAME TrapFrame;
3868 RTUINT128U au128[3];
3869 PRTUINT128U pau128 = RT_ALIGN_PT(&au128[0], sizeof(RTUINT128U), PRTUINT128U);
3870 bool const fSupportCX16 = RT_BOOL(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16);
3871 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3872 uint8_t bRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
3873 unsigned iFlags;
3874 unsigned offBuf;
3875 unsigned iMatch;
3876 unsigned iWorker;
3877 static struct
3878 {
3879 bool fLocked;
3880 uint8_t offUd2;
3881 FNBS3FAR *pfnWorker;
3882 } const s_aWorkers[] =
3883 {
3884 { false, 4, BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2) },
3885 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2) },
3886 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2) },
3887 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2) },
3888 { true, 1+4, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2) },
3889 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2) },
3890 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2) },
3891 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2) },
3892 };
3893
3894 /* Ensure the structures are allocated before we sample the stack pointer. */
3895 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3896 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3897 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3898 Bs3MemSet(pau128, 0, sizeof(pau128[0]) * 2);
3899
3900 /*
3901 * Create test context.
3902 */
3903 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3904 if (!fSupportCX16)
3905 Bs3TestPrintf("Note! CMPXCHG16B is not supported by the CPU!\n");
3906
3907
3908 /*
3909 * Run the tests in all rings since alignment issues may behave
3910 * differently in ring-3 compared to ring-0.
3911 */
3912 for (;;)
3913 {
3914 /*
3915 * One loop with alignment checks disabled and one with enabled.
3916 */
3917 unsigned iCfg;
3918 for (iCfg = 0; iCfg < 2; iCfg++)
3919 {
3920 if (iCfg)
3921 {
3922 Ctx.rflags.u32 |= X86_EFL_AC;
3923 Ctx.cr0.u32 |= X86_CR0_AM;
3924 }
3925 else
3926 {
3927 Ctx.rflags.u32 &= ~X86_EFL_AC;
3928 Ctx.cr0.u32 &= ~X86_CR0_AM;
3929 }
3930
3931 /*
3932 * One loop with the normal variant and one with the locked one
3933 */
3934 g_usBs3TestStep = 0;
3935 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
3936 {
3937 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
3938
3939 /*
3940 * One loop with all status flags set, and one with them clear.
3941 */
3942 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3943 for (iFlags = 0; iFlags < 2; iFlags++)
3944 {
3945 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3946
3947 for (offBuf = 0; offBuf < sizeof(RTUINT128U); offBuf++)
3948 {
3949# define CX16_OLD_LO UINT64_C(0xabb6345dcc9c4bbd)
3950# define CX16_OLD_HI UINT64_C(0x7b06ea35749549ab)
3951# define CX16_MISMATCH_LO UINT64_C(0xbace3e3590f18981)
3952# define CX16_MISMATCH_HI UINT64_C(0x9b385e8bfd5b4000)
3953# define CX16_STORE_LO UINT64_C(0x5cbd27d251f6559b)
3954# define CX16_STORE_HI UINT64_C(0x17ff434ed1b54963)
3955
3956 PRTUINT128U pBuf = (PRTUINT128U)&pau128->au8[offBuf];
3957
3958 ExpectCtx.rax.u = Ctx.rax.u = CX16_MISMATCH_LO;
3959 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_MISMATCH_HI;
3960 for (iMatch = 0; iMatch < 2; iMatch++)
3961 {
3962 uint8_t bExpectXcpt;
3963 pBuf->s.Lo = CX16_OLD_LO;
3964 pBuf->s.Hi = CX16_OLD_HI;
3965 ExpectCtx.rdi.u = Ctx.rdi.u = (uintptr_t)pBuf;
3966 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3967 g_usBs3TestStep++;
3968 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
3969 bExpectXcpt = X86_XCPT_UD;
3970 if (fSupportCX16)
3971 {
3972 if (offBuf & 15)
3973 {
3974 bExpectXcpt = X86_XCPT_GP;
3975 ExpectCtx.rip.u = Ctx.rip.u;
3976 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
3977 }
3978 else
3979 {
3980 ExpectCtx.rax.u = CX16_OLD_LO;
3981 ExpectCtx.rdx.u = CX16_OLD_HI;
3982 if (iMatch & 1)
3983 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
3984 else
3985 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
3986 ExpectCtx.rip.u = Ctx.rip.u + s_aWorkers[iWorker].offUd2;
3987 }
3988 ExpectCtx.rflags.u32 |= X86_EFL_RF;
3989 }
3990 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
3991 0 /*fExtraEfl*/, pszMode, 0 /*idTestStep*/)
3992 || TrapFrame.bXcpt != bExpectXcpt)
3993 {
3994 if (TrapFrame.bXcpt != bExpectXcpt)
3995 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3996 Bs3TestFailedF("^^^bRing=%d iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n", bRing, iWorker, iFlags, offBuf, iMatch);
3997 ASMHalt();
3998 }
3999
4000 ExpectCtx.rax.u = Ctx.rax.u = CX16_OLD_LO;
4001 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_OLD_HI;
4002 }
4003 }
4004 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
4005 }
4006 }
4007 } /* for each test config. */
4008
4009 /*
4010 * Next ring.
4011 */
4012 bRing++;
4013 if (bRing > 3 || bMode == BS3_MODE_RM)
4014 break;
4015 Bs3RegCtxConvertToRingX(&Ctx, bRing);
4016 }
4017
4018 return 0;
4019}
4020
4021
4022static void bs3CpuInstr2_fsgsbase_ExpectUD(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame)
4023{
4024 pCtx->rbx.u = 0;
4025 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
4026 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
4027 pExpectCtx->rip.u = pCtx->rip.u;
4028 pExpectCtx->rflags.u32 |= X86_EFL_RF;
4029 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
4030 0 /*idTestStep*/)
4031 || pTrapFrame->bXcpt != X86_XCPT_UD)
4032 {
4033 Bs3TestFailedF("Expected #UD, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
4034 ASMHalt();
4035 }
4036}
4037
4038
4039static bool bs3CpuInstr2_fsgsbase_VerifyWorker(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame,
4040 BS3CI2FSGSBASE const *pFsGsBaseWorker, unsigned *puIter)
4041{
4042 bool fPassed = true;
4043 unsigned iValue = 0;
4044 static const struct
4045 {
4046 bool fGP;
4047 uint64_t u64Base;
4048 } s_aValues64[] =
4049 {
4050 { false, UINT64_C(0x0000000000000000) },
4051 { false, UINT64_C(0x0000000000000001) },
4052 { false, UINT64_C(0x0000000000000010) },
4053 { false, UINT64_C(0x0000000000000123) },
4054 { false, UINT64_C(0x0000000000001234) },
4055 { false, UINT64_C(0x0000000000012345) },
4056 { false, UINT64_C(0x0000000000123456) },
4057 { false, UINT64_C(0x0000000001234567) },
4058 { false, UINT64_C(0x0000000012345678) },
4059 { false, UINT64_C(0x0000000123456789) },
4060 { false, UINT64_C(0x000000123456789a) },
4061 { false, UINT64_C(0x00000123456789ab) },
4062 { false, UINT64_C(0x0000123456789abc) },
4063 { false, UINT64_C(0x00007ffffeefefef) },
4064 { false, UINT64_C(0x00007fffffffffff) },
4065 { true, UINT64_C(0x0000800000000000) },
4066 { true, UINT64_C(0x0000800000000000) },
4067 { true, UINT64_C(0x0000800000000333) },
4068 { true, UINT64_C(0x0001000000000000) },
4069 { true, UINT64_C(0x0012000000000000) },
4070 { true, UINT64_C(0x0123000000000000) },
4071 { true, UINT64_C(0x1234000000000000) },
4072 { true, UINT64_C(0xffff300000000000) },
4073 { true, UINT64_C(0xffff7fffffffffff) },
4074 { true, UINT64_C(0xffff7fffffffffff) },
4075 { false, UINT64_C(0xffff800000000000) },
4076 { false, UINT64_C(0xffffffffffeefefe) },
4077 { false, UINT64_C(0xffffffffffffffff) },
4078 { false, UINT64_C(0xffffffffffffffff) },
4079 { false, UINT64_C(0x00000000efefefef) },
4080 { false, UINT64_C(0x0000000080204060) },
4081 { false, UINT64_C(0x00000000ddeeffaa) },
4082 { false, UINT64_C(0x00000000fdecdbca) },
4083 { false, UINT64_C(0x000000006098456b) },
4084 { false, UINT64_C(0x0000000098506099) },
4085 { false, UINT64_C(0x00000000206950bc) },
4086 { false, UINT64_C(0x000000009740395d) },
4087 { false, UINT64_C(0x0000000064a9455e) },
4088 { false, UINT64_C(0x00000000d20b6eff) },
4089 { false, UINT64_C(0x0000000085296d46) },
4090 { false, UINT64_C(0x0000000007000039) },
4091 { false, UINT64_C(0x000000000007fe00) },
4092 };
4093
4094 Bs3RegCtxSetRipCsFromCurPtr(pCtx, pFsGsBaseWorker->pfnVerifyWorker);
4095 if (pFsGsBaseWorker->f64BitOperand)
4096 {
4097 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
4098 {
4099 bool const fGP = s_aValues64[iValue].fGP;
4100
4101 pCtx->rbx.u = s_aValues64[iValue].u64Base;
4102 pCtx->rcx.u = 0;
4103 pCtx->cr4.u |= X86_CR4_FSGSBASE;
4104 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
4105 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
4106 pExpectCtx->rip.u = pCtx->rip.u + (!fGP ? pFsGsBaseWorker->offVerifyWorkerUd2 : 0);
4107 pExpectCtx->rbx.u = !fGP ? 0 : s_aValues64[iValue].u64Base;
4108 pExpectCtx->rcx.u = !fGP ? s_aValues64[iValue].u64Base : 0;
4109 pExpectCtx->rflags.u32 |= X86_EFL_RF;
4110 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
4111 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/)
4112 || (fGP && pTrapFrame->bXcpt != X86_XCPT_GP))
4113 {
4114 if (fGP && pTrapFrame->bXcpt != X86_XCPT_GP)
4115 Bs3TestFailedF("Expected #GP, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
4116 else
4117 Bs3TestFailedF("iValue=%u\n", iValue);
4118 fPassed = false;
4119 break;
4120 }
4121 }
4122 }
4123 else
4124 {
4125 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
4126 {
4127 pCtx->rbx.u = s_aValues64[iValue].u64Base;
4128 pCtx->rcx.u = ~s_aValues64[iValue].u64Base;
4129 pCtx->cr4.u |= X86_CR4_FSGSBASE;
4130 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
4131 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
4132 pExpectCtx->rip.u = pCtx->rip.u + pFsGsBaseWorker->offVerifyWorkerUd2;
4133 pExpectCtx->rbx.u = 0;
4134 pExpectCtx->rcx.u = s_aValues64[iValue].u64Base & UINT64_C(0x00000000ffffffff);
4135 pExpectCtx->rflags.u32 |= X86_EFL_RF;
4136 if (!Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
4137 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/))
4138 {
4139 Bs3TestFailedF("iValue=%u\n", iValue);
4140 fPassed = false;
4141 break;
4142 }
4143 }
4144 }
4145
4146 *puIter = iValue;
4147 return fPassed;
4148}
4149
4150
4151static void bs3CpuInstr2_rdfsbase_rdgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
4152 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
4153{
4154 BS3REGCTX Ctx;
4155 BS3REGCTX ExpectCtx;
4156 BS3TRAPFRAME TrapFrame;
4157 unsigned iWorker;
4158 unsigned iIter;
4159 uint32_t uDummy;
4160 uint32_t uStdExtFeatEbx;
4161 bool fSupportsFsGsBase;
4162
4163 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
4164 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
4165
4166 /* Ensure the structures are allocated before we sample the stack pointer. */
4167 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
4168 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
4169 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
4170
4171 /*
4172 * Create test context.
4173 */
4174 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
4175
4176 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
4177 {
4178 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
4179 if (fSupportsFsGsBase)
4180 {
4181 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
4182
4183 /* CR4.FSGSBASE disabled -> #UD. */
4184 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
4185 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4186
4187 /* Read and verify existing base address. */
4188 Ctx.rbx.u = 0;
4189 Ctx.cr4.u |= X86_CR4_FSGSBASE;
4190 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
4191 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
4192 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
4193 ExpectCtx.rbx.u = uBaseAddr;
4194 ExpectCtx.rflags.u32 |= X86_EFL_RF;
4195 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
4196 0 /*idTestStep*/))
4197 {
4198 ASMHalt();
4199 }
4200
4201 /* Write, read and verify series of base addresses. */
4202 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
4203 {
4204 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
4205 ASMHalt();
4206 }
4207
4208 /* Restore original base address. */
4209 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
4210
4211 /* Clean used GPRs. */
4212 Ctx.rbx.u = 0;
4213 Ctx.rcx.u = 0;
4214 }
4215 else
4216 {
4217 /* Unsupported by CPUID -> #UD. */
4218 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
4219 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4220 }
4221 }
4222}
4223
4224
4225static void bs3CpuInstr2_wrfsbase_wrgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
4226 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
4227{
4228 BS3REGCTX Ctx;
4229 BS3REGCTX ExpectCtx;
4230 BS3TRAPFRAME TrapFrame;
4231 unsigned iWorker;
4232 unsigned iIter;
4233 uint32_t uDummy;
4234 uint32_t uStdExtFeatEbx;
4235 bool fSupportsFsGsBase;
4236
4237 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
4238 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
4239
4240 /* Ensure the structures are allocated before we sample the stack pointer. */
4241 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
4242 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
4243 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
4244
4245 /*
4246 * Create test context.
4247 */
4248 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
4249
4250 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
4251 {
4252 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
4253 if (fSupportsFsGsBase)
4254 {
4255 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
4256
4257 /* CR4.FSGSBASE disabled -> #UD. */
4258 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
4259 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4260
4261 /* Write a base address. */
4262 Ctx.rbx.u = 0xa0000;
4263 Ctx.cr4.u |= X86_CR4_FSGSBASE;
4264 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
4265 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
4266 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
4267 ExpectCtx.rflags.u32 |= X86_EFL_RF;
4268 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
4269 0 /*idTestStep*/))
4270 {
4271 ASMHalt();
4272 }
4273
4274 /* Write and read back series of base addresses. */
4275 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
4276 {
4277 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
4278 ASMHalt();
4279 }
4280
4281 /* Restore original base address. */
4282 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
4283
4284 /* Clean used GPRs. */
4285 Ctx.rbx.u = 0;
4286 Ctx.rcx.u = 0;
4287 }
4288 else
4289 {
4290 /* Unsupported by CPUID -> #UD. */
4291 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
4292 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4293 }
4294 }
4295}
4296
4297
4298BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrfsbase)(uint8_t bMode)
4299{
4300 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrFsBaseWorkers, RT_ELEMENTS(s_aWrFsBaseWorkers), MSR_K8_FS_BASE);
4301 return 0;
4302}
4303
4304
4305BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrgsbase)(uint8_t bMode)
4306{
4307 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrGsBaseWorkers, RT_ELEMENTS(s_aWrGsBaseWorkers), MSR_K8_GS_BASE);
4308 return 0;
4309}
4310
4311
4312BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdfsbase)(uint8_t bMode)
4313{
4314 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdFsBaseWorkers, RT_ELEMENTS(s_aRdFsBaseWorkers), MSR_K8_FS_BASE);
4315 return 0;
4316}
4317
4318
4319BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdgsbase)(uint8_t bMode)
4320{
4321 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdGsBaseWorkers, RT_ELEMENTS(s_aRdGsBaseWorkers), MSR_K8_GS_BASE);
4322 return 0;
4323}
4324
4325# endif /* ARCH_BITS == 64 */
4326
4327#endif /* BS3_INSTANTIATING_CMN */
4328
4329
4330
4331/*
4332 * Mode specific code.
4333 * Mode specific code.
4334 * Mode specific code.
4335 */
4336#ifdef BS3_INSTANTIATING_MODE
4337
4338
4339#endif /* BS3_INSTANTIATING_MODE */
4340
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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