VirtualBox

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

Last change on this file since 101672 was 98828, checked in by vboxsync, 21 months ago

ValidationKit/bs3-cpu-instr-2: Add adcx/adox testcase, bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 171.6 KB
Line 
1/* $Id: bs3-cpu-instr-2-template.c 98828 2023-03-03 12:03:11Z 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.virtualbox.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
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48#ifdef BS3_INSTANTIATING_CMN
49# if ARCH_BITS == 64
50typedef struct BS3CI2FSGSBASE
51{
52 const char *pszDesc;
53 bool f64BitOperand;
54 FPFNBS3FAR pfnWorker;
55 uint8_t offWorkerUd2;
56 FPFNBS3FAR pfnVerifyWorker;
57 uint8_t offVerifyWorkerUd2;
58} BS3CI2FSGSBASE;
59# endif
60#endif
61
62
63/*********************************************************************************************************************************
64* External Symbols *
65*********************************************************************************************************************************/
66#ifdef BS3_INSTANTIATING_CMN
67extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2);
68
69extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2);
70extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2);
71
72extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2);
73extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2);
74
75extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_AX_BX_ud2);
76extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_EBX_ud2);
77extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_RBX_ud2);
78extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_AX_FSxBX_ud2);
79extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_FSxBX_ud2);
80extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_FSxBX_ud2);
81
82extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_BX_ud2);
83extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_EBX_ud2);
84extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_RBX_ud2);
85extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_FSxBX_ud2);
86extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_FSxBX_ud2);
87extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_FSxBX_ud2);
88
89extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_BX_ud2);
90extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_EBX_ud2);
91extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_RBX_ud2);
92extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_FSxBX_ud2);
93extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_FSxBX_ud2);
94extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_FSxBX_ud2);
95
96extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_BX_ud2);
97extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_EBX_ud2);
98extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_RBX_ud2);
99extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_FSxBX_ud2);
100extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_FSxBX_ud2);
101extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_FSxBX_ud2);
102
103extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_AX_BX_ud2);
104extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_EBX_ud2);
105extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_RBX_ud2);
106extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_AX_FSxBX_ud2);
107extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_FSxBX_ud2);
108extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_FSxBX_ud2);
109
110extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_BX_ud2);
111extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_EBX_ud2);
112extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_RBX_ud2);
113extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_FSxBX_ud2);
114extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_FSxBX_ud2);
115extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_FSxBX_ud2);
116
117extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_BX_ud2);
118extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_EBX_ud2);
119extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_RBX_ud2);
120extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_FSxBX_ud2);
121extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_FSxBX_ud2);
122extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_FSxBX_ud2);
123
124extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_BX_ud2);
125extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_EBX_ud2);
126extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_RBX_ud2);
127extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_FSxBX_ud2);
128extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_FSxBX_ud2);
129extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_FSxBX_ud2);
130
131extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp);
132extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp);
133extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_L1);
134# if ARCH_BITS == 64
135extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_X1);
136# endif
137extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V1);
138extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V15);
139extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp);
140extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp);
141
142extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp);
143extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp);
144extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp);
145extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp);
146
147extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_RBX_RCX_icebp);
148extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_FSxBX_RCX_icebp);
149extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_EBX_ECX_icebp);
150extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_FSxBX_ECX_icebp);
151
152extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_RBX_RCX_icebp);
153extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_FSxBX_RCX_icebp);
154extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_EBX_ECX_icebp);
155extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_FSxBX_ECX_icebp);
156
157extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_RBX_icebp);
158extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_FSxBX_icebp);
159extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_EBX_icebp);
160extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_FSxBX_icebp);
161
162extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_RBX_icebp);
163extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_FSxBX_icebp);
164extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_EBX_icebp);
165extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_FSxBX_icebp);
166
167extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_RBX_RCX_icebp);
168extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_FSxBX_RCX_icebp);
169extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_EBX_ECX_icebp);
170extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_FSxBX_ECX_icebp);
171
172extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_RBX_RCX_icebp);
173extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_FSxBX_RCX_icebp);
174extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_EBX_ECX_icebp);
175extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_FSxBX_ECX_icebp);
176
177extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_RBX_RCX_icebp);
178extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_FSxBX_RCX_icebp);
179extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_EBX_ECX_icebp);
180extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_FSxBX_ECX_icebp);
181
182extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_RBX_icebp);
183extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_FSxBX_icebp);
184extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_EBX_icebp);
185extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_FSxBX_icebp);
186
187extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_RBX_icebp);
188extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_FSxBX_icebp);
189extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_EBX_icebp);
190extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_FSxBX_icebp);
191
192extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_RBX_icebp);
193extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_FSxBX_icebp);
194extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_EBX_icebp);
195extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_FSxBX_icebp);
196
197extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp);
198extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RCX_RCX_RBX_RDX_icebp);
199extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp);
200extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp);
201extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_ECX_ECX_EBX_EDX_icebp);
202extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp);
203
204extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp);
205extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp);
206extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp);
207extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp);
208extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp);
209extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp);
210
211extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BL_icebp);
212extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_byte_FSxBX_icebp);
213extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BX_icebp);
214extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_word_FSxBX_icebp);
215extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_EBX_icebp);
216extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_dword_FSxBX_icebp);
217extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_RBX_icebp);
218extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_qword_FSxBX_icebp);
219
220extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_EBX_icebp);
221extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_dword_FSxBX_icebp);
222extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_RBX_icebp);
223extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_qword_FSxBX_icebp);
224extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_EAX_EBX_icebp);
225extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_EAX_dword_FSxBX_icebp);
226extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_RAX_RBX_icebp);
227extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_adox_RAX_qword_FSxBX_icebp);
228
229# if ARCH_BITS == 64
230extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2);
231extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2);
232extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2);
233extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2);
234extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2);
235extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2);
236extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2);
237extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2);
238
239extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_ud2);
240extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_ud2);
241extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2);
242extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2);
243
244extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_ud2);
245extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_ud2);
246extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2);
247extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2);
248
249extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdfsbase_rbx_ud2);
250extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdfsbase_ebx_ud2);
251extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdgsbase_rbx_ud2);
252extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_rdgsbase_ebx_ud2);
253# endif
254#endif
255
256
257/*********************************************************************************************************************************
258* Global Variables *
259*********************************************************************************************************************************/
260#ifdef BS3_INSTANTIATING_CMN
261# if ARCH_BITS == 64
262static BS3CI2FSGSBASE const s_aWrFsBaseWorkers[] =
263{
264 { "wrfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
265 { "wrfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
266};
267
268static BS3CI2FSGSBASE const s_aWrGsBaseWorkers[] =
269{
270 { "wrgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
271 { "wrgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
272};
273
274static BS3CI2FSGSBASE const s_aRdFsBaseWorkers[] =
275{
276 { "rdfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
277 { "rdfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
278};
279
280static BS3CI2FSGSBASE const s_aRdGsBaseWorkers[] =
281{
282 { "rdgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
283 { "rdgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
284};
285# endif
286#endif /* BS3_INSTANTIATING_CMN - global */
287
288
289/*
290 * Common code.
291 * Common code.
292 * Common code.
293 */
294#ifdef BS3_INSTANTIATING_CMN
295
296BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
297{
298#define MUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
299#define MUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
300
301 static const struct
302 {
303 RTCCUINTREG uInAX;
304 RTCCUINTREG uInBX;
305 RTCCUINTREG uOutDX;
306 RTCCUINTREG uOutAX;
307 uint16_t fFlags;
308 } s_aTests[] =
309 {
310 { 1, 1,
311 0, 1, 0 },
312 { 2, 2,
313 0, 4, 0 },
314 { RTCCUINTREG_MAX, RTCCUINTREG_MAX,
315 RTCCUINTREG_MAX-1, 1, X86_EFL_CF | X86_EFL_OF },
316 { RTCCINTREG_MAX, RTCCINTREG_MAX,
317 RTCCINTREG_MAX / 2, 1, X86_EFL_CF | X86_EFL_OF },
318 { 1, RTCCUINTREG_MAX,
319 0, RTCCUINTREG_MAX, X86_EFL_PF | X86_EFL_SF },
320 { 1, RTCCINTREG_MAX,
321 0, RTCCINTREG_MAX, X86_EFL_PF },
322 { 2, RTCCINTREG_MAX,
323 0, RTCCUINTREG_MAX - 1, X86_EFL_SF },
324 { (RTCCUINTREG)RTCCINTREG_MAX + 1, 2,
325 1, 0, X86_EFL_PF | X86_EFL_CF | X86_EFL_OF },
326 { (RTCCUINTREG)RTCCINTREG_MAX / 2 + 1, 3,
327 0, ((RTCCUINTREG)RTCCINTREG_MAX / 2 + 1) * 3, X86_EFL_PF | X86_EFL_SF },
328 };
329
330 BS3REGCTX Ctx;
331 BS3TRAPFRAME TrapFrame;
332 unsigned i, j, k;
333
334 /* Ensure the structures are allocated before we sample the stack pointer. */
335 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
336 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
337
338 /*
339 * Create test context.
340 */
341 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
342 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2));
343 for (k = 0; k < 2; k++)
344 {
345 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
346 for (j = 0; j < 2; j++)
347 {
348 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
349 {
350 if (k == 0)
351 {
352 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
353 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
354 }
355 else
356 {
357 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
358 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
359 }
360 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
361 if (TrapFrame.bXcpt != X86_XCPT_UD)
362 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
363 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
364 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
365 || (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
366 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
367 {
368 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
369 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
370
371 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
372 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
373 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
374 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
375 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
376 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
377 if ( (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
378 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
379 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & MUL_CHECK_EFLAGS,
380 TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO));
381 }
382 }
383 Ctx.rflags.u16 &= ~(MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO);
384 }
385 }
386
387 return 0;
388}
389
390
391BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_imul)(uint8_t bMode)
392{
393#define IMUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
394#define IMUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
395 static const struct
396 {
397 RTCCUINTREG uInAX;
398 RTCCUINTREG uInBX;
399 RTCCUINTREG uOutDX;
400 RTCCUINTREG uOutAX;
401 uint16_t fFlags;
402 } s_aTests[] =
403 {
404 /* two positive values. */
405 { 1, 1,
406 0, 1, 0 },
407 { 2, 2,
408 0, 4, 0 },
409 { RTCCINTREG_MAX, RTCCINTREG_MAX,
410 RTCCINTREG_MAX/2, 1, X86_EFL_CF | X86_EFL_OF },
411 { 1, RTCCINTREG_MAX,
412 0, RTCCINTREG_MAX, X86_EFL_PF },
413 { 2, RTCCINTREG_MAX,
414 0, RTCCUINTREG_MAX - 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF },
415 { 2, RTCCINTREG_MAX / 2,
416 0, RTCCINTREG_MAX - 1U, 0 },
417 { 2, (RTCCINTREG_MAX / 2 + 1),
418 0, (RTCCUINTREG)RTCCINTREG_MAX + 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
419 { 4, (RTCCINTREG_MAX / 2 + 1),
420 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
421
422 /* negative and positive */
423 { -4, 3,
424 -1, -12, X86_EFL_SF },
425 { 32, -127,
426 -1, -4064, X86_EFL_SF },
427 { RTCCINTREG_MIN, 1,
428 -1, RTCCINTREG_MIN, X86_EFL_SF | X86_EFL_PF },
429 { RTCCINTREG_MIN, 2,
430 -1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
431 { RTCCINTREG_MIN, 3,
432 -2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
433 { RTCCINTREG_MIN, 4,
434 -2, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
435 { RTCCINTREG_MIN, RTCCINTREG_MAX,
436 RTCCINTREG_MIN / 2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
437 { RTCCINTREG_MIN, RTCCINTREG_MAX - 1,
438 RTCCINTREG_MIN / 2 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
439
440 /* two negative values. */
441 { -4, -63,
442 0, 252, X86_EFL_PF },
443 { RTCCINTREG_MIN, RTCCINTREG_MIN,
444 RTCCUINTREG_MAX / 4 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
445 { RTCCINTREG_MIN, RTCCINTREG_MIN + 1,
446 RTCCUINTREG_MAX / 4, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF},
447 { RTCCINTREG_MIN + 1, RTCCINTREG_MIN + 1,
448 RTCCUINTREG_MAX / 4, 1, X86_EFL_CF | X86_EFL_OF },
449
450 };
451
452 BS3REGCTX Ctx;
453 BS3TRAPFRAME TrapFrame;
454 unsigned i, j, k;
455
456 /* Ensure the structures are allocated before we sample the stack pointer. */
457 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
458 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
459
460 /*
461 * Create test context.
462 */
463 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
464 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2));
465
466 for (k = 0; k < 2; k++)
467 {
468 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
469 for (j = 0; j < 2; j++)
470 {
471 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
472 {
473 if (k == 0)
474 {
475 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
476 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
477 }
478 else
479 {
480 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
481 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
482 }
483 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
484 if (TrapFrame.bXcpt != X86_XCPT_UD)
485 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
486 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
487 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
488 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
489 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
490 {
491 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
492 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
493
494 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
495 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
496 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
497 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
498 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
499 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
500 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
501 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
502 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
503 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
504 }
505 }
506 }
507 }
508
509 /*
510 * Repeat for the truncating two operand version.
511 */
512 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2));
513
514 for (k = 0; k < 2; k++)
515 {
516 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
517 for (j = 0; j < 2; j++)
518 {
519 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
520 {
521 if (k == 0)
522 {
523 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
524 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
525 }
526 else
527 {
528 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
529 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
530 }
531 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
532 if (TrapFrame.bXcpt != X86_XCPT_UD)
533 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
534 else if ( TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
535 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
536 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
537 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
538 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
539 {
540 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
541 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
542
543 if (TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
544 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
545 s_aTests[i].uOutAX, TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS));
546 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
547 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
548 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
549 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
550 }
551 }
552 }
553 }
554
555 return 0;
556}
557
558
559BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_div)(uint8_t bMode)
560{
561#define DIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
562 static const struct
563 {
564 RTCCUINTREG uInDX;
565 RTCCUINTREG uInAX;
566 RTCCUINTREG uInBX;
567 RTCCUINTREG uOutAX;
568 RTCCUINTREG uOutDX;
569 uint8_t bXcpt;
570 } s_aTests[] =
571 {
572 { 0, 1, 1,
573 1, 0, X86_XCPT_UD },
574 { 0, 5, 2,
575 2, 1, X86_XCPT_UD },
576 { 0, 0, 0,
577 0, 0, X86_XCPT_DE },
578 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 0,
579 0, 0, X86_XCPT_DE },
580 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 1,
581 0, 0, X86_XCPT_DE },
582 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
583 0, 0, X86_XCPT_DE },
584 { RTCCUINTREG_MAX - 1, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
585 RTCCUINTREG_MAX, RTCCUINTREG_MAX - 1, X86_XCPT_UD },
586 };
587
588 BS3REGCTX Ctx;
589 BS3TRAPFRAME TrapFrame;
590 unsigned i, j;
591
592 /* Ensure the structures are allocated before we sample the stack pointer. */
593 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
594 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
595
596 /*
597 * Create test context.
598 */
599 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
600 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2));
601
602 /*
603 * Do the tests twice, first with all flags set, then once again with
604 * flags cleared. The flags are not touched by my intel skylake CPU.
605 */
606 Ctx.rflags.u16 |= DIV_CHECK_EFLAGS;
607 for (j = 0; j < 2; j++)
608 {
609 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
610 {
611 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
612 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
613 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
614 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
615
616 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
617 || ( s_aTests[i].bXcpt == X86_XCPT_UD
618 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
619 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
620 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS)
621 : TrapFrame.Ctx.rax.u != Ctx.rax.u
622 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
623 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS) ) )
624 {
625 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
626 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
627 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
628 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
629 if (s_aTests[i].bXcpt == X86_XCPT_UD)
630 {
631 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
632 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
633 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
634 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
635 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
636 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
637 if ((TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS))
638 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
639 Ctx.rflags.u16 & DIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS);
640 }
641 }
642 }
643 Ctx.rflags.u16 &= ~DIV_CHECK_EFLAGS;
644 }
645
646 return 0;
647}
648
649
650
651BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_idiv)(uint8_t bMode)
652{
653#define IDIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
654 static const struct
655 {
656 RTCCUINTREG uInDX;
657 RTCCUINTREG uInAX;
658 RTCCUINTREG uInBX;
659 RTCCUINTREG uOutAX;
660 RTCCUINTREG uOutDX;
661 uint8_t bXcpt;
662 } s_aTests[] =
663 {
664 { 0, 0, 0,
665 0, 0, X86_XCPT_DE },
666 { RTCCINTREG_MAX, RTCCINTREG_MAX, 0,
667 0, 0, X86_XCPT_DE },
668 /* two positive values. */
669 { 0, 1, 1,
670 1, 0, X86_XCPT_UD },
671 { 0, 5, 2,
672 2, 1, X86_XCPT_UD },
673 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2, RTCCINTREG_MAX,
674 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_UD },
675 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2 + 1, RTCCINTREG_MAX,
676 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_DE },
677 /* negative dividend, positive divisor. */
678 { -1, -7, 2,
679 -3, -1, X86_XCPT_UD },
680 { RTCCINTREG_MIN / 2 + 1, 0, RTCCINTREG_MAX,
681 RTCCINTREG_MIN + 2, RTCCINTREG_MIN + 2, X86_XCPT_UD },
682 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MAX,
683 0, 0, X86_XCPT_DE },
684 /* positive dividend, negative divisor. */
685 { 0, 7, -2,
686 -3, 1, X86_XCPT_UD },
687 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX, RTCCINTREG_MIN,
688 RTCCINTREG_MIN, RTCCINTREG_MAX, X86_XCPT_UD },
689 { RTCCINTREG_MAX / 2 + 1, (RTCCUINTREG)RTCCINTREG_MAX+1, RTCCINTREG_MIN,
690 0, 0, X86_XCPT_DE },
691 /* negative dividend, negative divisor. */
692 { -1, -7, -2,
693 3, -1, X86_XCPT_UD },
694 { RTCCINTREG_MIN / 2, 1, RTCCINTREG_MIN,
695 RTCCINTREG_MAX, RTCCINTREG_MIN + 1, X86_XCPT_UD },
696 { RTCCINTREG_MIN / 2, 2, RTCCINTREG_MIN,
697 RTCCINTREG_MAX, RTCCINTREG_MIN + 2, X86_XCPT_UD },
698 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MIN,
699 0, 0, X86_XCPT_DE },
700 };
701
702 BS3REGCTX Ctx;
703 BS3TRAPFRAME TrapFrame;
704 unsigned i, j;
705
706 /* Ensure the structures are allocated before we sample the stack pointer. */
707 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
708 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
709
710 /*
711 * Create test context.
712 */
713 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
714 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2));
715
716 /*
717 * Do the tests twice, first with all flags set, then once again with
718 * flags cleared. The flags are not touched by my intel skylake CPU.
719 */
720 Ctx.rflags.u16 |= IDIV_CHECK_EFLAGS;
721 for (j = 0; j < 2; j++)
722 {
723 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
724 {
725 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
726 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
727 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
728 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
729
730 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
731 || ( s_aTests[i].bXcpt == X86_XCPT_UD
732 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
733 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
734 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS)
735 : TrapFrame.Ctx.rax.u != Ctx.rax.u
736 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
737 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) ) )
738 {
739 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
740 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
741 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
742 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
743 if (s_aTests[i].bXcpt == X86_XCPT_UD)
744 {
745 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
746 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
747 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
748 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
749 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
750 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
751 if ((TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS))
752 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
753 Ctx.rflags.u16 & IDIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS);
754 }
755 }
756 }
757 Ctx.rflags.u16 &= ~IDIV_CHECK_EFLAGS;
758 }
759
760 return 0;
761}
762
763
764/*
765 * BSF/BSR (386+) & TZCNT/LZCNT (BMI1,ABM)
766 */
767
768typedef struct BS3CPUINSTR2_SUBTEST_BITSCAN_T
769{
770 RTCCUINTXREG uSrc;
771 RTCCUINTXREG uOut;
772 bool fOutNotSet;
773 uint16_t fEflOut;
774} BS3CPUINSTR2_SUBTEST_BITSCAN_T;
775
776typedef struct BS3CPUINSTR2_TEST_BITSCAN_T
777{
778 FPFNBS3FAR pfnWorker;
779 bool fMemSrc;
780 uint8_t cbInstr;
781 uint8_t cOpBits;
782 uint16_t fEflCheck;
783 uint8_t cSubTests;
784 BS3CPUINSTR2_SUBTEST_BITSCAN_T const *paSubTests;
785} BS3CPUINSTR2_TEST_BITSCAN_T;
786
787static uint8_t bs3CpuInstr2_BitScan(uint8_t bMode, BS3CPUINSTR2_TEST_BITSCAN_T const *paTests, unsigned cTests)
788{
789 BS3REGCTX Ctx;
790 BS3TRAPFRAME TrapFrame;
791 unsigned i, j, k;
792
793 /* Ensure the structures are allocated before we sample the stack pointer. */
794 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
795 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
796
797 /*
798 * Create test context.
799 */
800 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
801
802 /*
803 * Do the tests twice, first with all flags set, then once again with
804 * flags cleared. The flags are not supposed to be touched at all.
805 */
806 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
807 for (j = 0; j < 2; j++)
808 {
809 for (i = 0; i < cTests; i++)
810 {
811 for (k = 0; k < paTests[i].cSubTests; k++)
812 {
813 uint64_t uExpectRax, uExpectRip;
814 RTCCUINTXREG uMemSrc, uMemSrcExpect;
815
816 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
817 if (!paTests[i].fMemSrc)
818 {
819 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
820 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
821 }
822 else
823 {
824 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
825 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
826 }
827 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
828 if (paTests[i].paSubTests[k].fOutNotSet)
829 uExpectRax = Ctx.rax.u;
830 else if (paTests[i].cOpBits != 16)
831 uExpectRax = paTests[i].paSubTests[k].uOut;
832 else
833 uExpectRax = paTests[i].paSubTests[k].uOut | (Ctx.rax.u & UINT64_C(0xffffffffffff0000));
834 uExpectRip = Ctx.rip.u + paTests[i].cbInstr;
835 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
836
837 if ( TrapFrame.bXcpt != X86_XCPT_UD
838 || TrapFrame.Ctx.rip.u != uExpectRip
839 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
840 || TrapFrame.Ctx.rax.u != uExpectRax
841 || (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
842 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck)
843 /* check that nothing else really changed: */
844 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
845 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
846 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
847 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
848 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
849 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
850 || uMemSrc != uMemSrcExpect
851 )
852 {
853 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
854 i, k, paTests[i].paSubTests[k].uSrc);
855 if (TrapFrame.bXcpt != X86_XCPT_UD)
856 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", X86_XCPT_UD, TrapFrame.bXcpt);
857 if (TrapFrame.Ctx.rip.u != uExpectRip)
858 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
859 if (TrapFrame.Ctx.rax.u != uExpectRax)
860 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
861 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
862 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
863 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
864 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
865 if ( (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
866 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck))
867 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
868 paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck,
869 TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck);
870
871 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
872 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
873 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
874 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
875 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
876 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
877 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
878 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
879 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
880 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
881 if (uMemSrc != uMemSrcExpect)
882 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
883 }
884 }
885 }
886 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
887 }
888
889 return 0;
890}
891
892
893BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsf_tzcnt)(uint8_t bMode)
894{
895 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf16[] =
896 {
897 { 0, /* -> */ 0, true, X86_EFL_ZF },
898 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
899 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
900 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
901 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
902 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
903 };
904 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt16[] =
905 {
906 { 0, /* -> */ 16, false, X86_EFL_CF },
907 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
908 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
909 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
910 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
911 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
912 };
913 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf32[] =
914 {
915 { 0, /* -> */ 0, true, X86_EFL_ZF },
916#if ARCH_BITS == 64
917 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
918#endif
919 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
920 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
921 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
922 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
923 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
924 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
925 };
926 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt32[] =
927 {
928 { 0, /* -> */ 32, false, X86_EFL_CF },
929#if ARCH_BITS == 64
930 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
931#endif
932 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
933 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
934 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
935 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
936 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
937 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
938 };
939#if ARCH_BITS == 64
940 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf64[] =
941 {
942 { 0, /* -> */ 0, true, X86_EFL_ZF },
943 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
944 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
945 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
946 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
947 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
948 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
949 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
950 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
951 };
952 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt64[] =
953 {
954 { 0, /* -> */ 64, false, X86_EFL_CF },
955 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
956 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
957 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
958 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
959 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
960 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
961 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
962 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
963 };
964#endif
965 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
966 {
967 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
968 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
969 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
970 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
971 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
972 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
973 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
974 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
975#if ARCH_BITS == 64
976 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
977 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
978 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
979 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
980#endif
981 /* f2 prefixed variant: */
982 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
983 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
984 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
985 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
986 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
987 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
988 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
989 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
990#if ARCH_BITS == 64
991 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
992 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
993 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
994 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
995#endif
996
997 /* tzcnt: */
998 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
999 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1000 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1001 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1002 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1003 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1004 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1005 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1006#if ARCH_BITS == 64
1007 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1008 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1009 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1010 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1011#endif
1012 /* f2 prefixed tzcnt variant (last prefix (f3) should prevail): */
1013 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1014 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1015 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1016 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1017 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1018 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1019 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1020 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1021#if ARCH_BITS == 64
1022 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1023 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1024 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1025 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1026#endif
1027 };
1028
1029 uint32_t uStdExtFeatEbx = 0;
1030 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1031 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1032 if (!(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1))
1033 {
1034 unsigned i = RT_ELEMENTS(s_aTests);
1035 while (i-- > 0)
1036 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1037 {
1038 s_aTests[i].fEflCheck = X86_EFL_ZF;
1039 switch (s_aTests[i].cOpBits)
1040 {
1041 case 16:
1042 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf16);
1043 s_aTests[i].paSubTests = s_aSubTestsBsf16;
1044 break;
1045 case 32:
1046 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf32);
1047 s_aTests[i].paSubTests = s_aSubTestsBsf32;
1048 break;
1049#if ARCH_BITS == 64
1050 case 64:
1051 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf64);
1052 s_aTests[i].paSubTests = s_aSubTestsBsf64;
1053 break;
1054#endif
1055 }
1056 }
1057 Bs3TestPrintf("tzcnt not supported\n");
1058 }
1059
1060 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1061}
1062
1063
1064BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsr_lzcnt)(uint8_t bMode)
1065{
1066 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr16[] =
1067 {
1068 { 0, /* -> */ 0, true, X86_EFL_ZF },
1069 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
1070 { ~(RTCCUINTXREG)0, /* -> */ 15, false, 0 },
1071 { ~(RTCCUINTXREG)1, /* -> */ 15, false, 0 },
1072 { UINT16_C(0x0001), /* -> */ 0, false, 0 },
1073 { UINT16_C(0x0002), /* -> */ 1, false, 0 },
1074 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1075 };
1076 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt16[] =
1077 {
1078 { 0, /* -> */ 16, false, X86_EFL_CF },
1079 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
1080 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1081 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1082 { UINT16_C(0x8000), /* -> */ 0, false, X86_EFL_ZF },
1083 { UINT16_C(0x4560), /* -> */ 1, false, 0 },
1084 { UINT16_C(0x003f), /* -> */ 10, false, 0 },
1085 { UINT16_C(0x0001), /* -> */ 15, false, 0 },
1086 };
1087 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr32[] =
1088 {
1089 { 0, /* -> */ 0, true, X86_EFL_ZF },
1090#if ARCH_BITS == 64
1091 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
1092#endif
1093 { ~(RTCCUINTXREG)0, /* -> */ 31, false, 0 },
1094 { ~(RTCCUINTXREG)1, /* -> */ 31, false, 0 },
1095 { 1, /* -> */ 0, false, 0 },
1096 { 2, /* -> */ 1, false, 0 },
1097 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1098 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1099 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1100 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1101 };
1102 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt32[] =
1103 {
1104 { 0, /* -> */ 32, false, X86_EFL_CF },
1105#if ARCH_BITS == 64
1106 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
1107#endif
1108 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1109 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1110 { 1, /* -> */ 31, false, 0 },
1111 { 2, /* -> */ 30, false, 0},
1112 { UINT16_C(0x8000), /* -> */ 16, false, 0 },
1113 { UINT16_C(0x4560), /* -> */ 17, false, 0 },
1114 { UINT32_C(0x80000000), /* -> */ 0, false, X86_EFL_ZF },
1115 { UINT32_C(0x45600000), /* -> */ 1, false, 0 },
1116 { UINT32_C(0x0000ffff), /* -> */ 16, false, 0 },
1117 };
1118#if ARCH_BITS == 64
1119 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr64[] =
1120 {
1121 { 0, /* -> */ 0, true, X86_EFL_ZF },
1122 { ~(RTCCUINTXREG)0, /* -> */ 63, false, 0 },
1123 { ~(RTCCUINTXREG)1, /* -> */ 63, false, 0 },
1124 { 1, /* -> */ 0, false, 0 },
1125 { 2, /* -> */ 1, false, 0 },
1126 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1127 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1128 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1129 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1130 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1131 { UINT64_C(0x0045600000000000), /* -> */ 54, false, 0 },
1132 };
1133 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt64[] =
1134 {
1135 { 0, /* -> */ 64, false, X86_EFL_CF },
1136 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1137 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1138 { 1, /* -> */ 63, false, 0 },
1139 { 2, /* -> */ 62, false, 0 },
1140 { UINT16_C(0x8000), /* -> */ 48, false, 0 },
1141 { UINT16_C(0x4560), /* -> */ 49, false, 0 },
1142 { UINT32_C(0x80000000), /* -> */ 32, false, 0 },
1143 { UINT32_C(0x45600000), /* -> */ 33, false, 0 },
1144 { UINT64_C(0x8000000000000000), /* -> */ 0, false, X86_EFL_ZF },
1145 { UINT64_C(0x4560000000000000), /* -> */ 1, false, 0 },
1146 { UINT64_C(0x0045600000000000), /* -> */ 9, false, 0 },
1147 };
1148#endif
1149 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
1150 {
1151 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1152 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1153 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1154 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1155 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1156 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1157 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1158 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1159#if ARCH_BITS == 64
1160 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
1161 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1162 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
1163 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1164#endif
1165 /* f2 prefixed variant: */
1166 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1167 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1168 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1169 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1170 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1171 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1172 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1173 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1174#if ARCH_BITS == 64
1175 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
1176 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1177 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
1178 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1179#endif
1180
1181 /* lzcnt: */
1182 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1183 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1184 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1185 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1186 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1187 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1188 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1189 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1190#if ARCH_BITS == 64
1191 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1192 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1193 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1194 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1195#endif
1196 /* f2 prefixed lzcnt variant (last prefix (f3) should prevail): */
1197 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1198 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1199 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1200 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1201 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1202 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1203 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1204 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1205#if ARCH_BITS == 64
1206 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1207 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1208 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1209 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1210#endif
1211 };
1212
1213 uint32_t uExtFeatEcx = 0;
1214 if (g_uBs3CpuDetected & BS3CPU_F_CPUID_EXT_LEAVES)
1215 ASMCpuIdExSlow(UINT32_C(0x80000001), 0, 0, 0, NULL, NULL, &uExtFeatEcx, NULL);
1216 if (!(uExtFeatEcx & X86_CPUID_AMD_FEATURE_ECX_ABM))
1217 {
1218 unsigned i = RT_ELEMENTS(s_aTests);
1219 while (i-- > 0)
1220 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1221 {
1222 s_aTests[i].fEflCheck = X86_EFL_ZF;
1223 switch (s_aTests[i].cOpBits)
1224 {
1225 case 16:
1226 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr16);
1227 s_aTests[i].paSubTests = s_aSubTestsBsr16;
1228 break;
1229 case 32:
1230 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr32);
1231 s_aTests[i].paSubTests = s_aSubTestsBsr32;
1232 break;
1233#if ARCH_BITS == 64
1234 case 64:
1235 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr64);
1236 s_aTests[i].paSubTests = s_aSubTestsBsr64;
1237 break;
1238#endif
1239 }
1240 }
1241 Bs3TestPrintf("lzcnt not supported\n");
1242 }
1243
1244 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1245}
1246
1247
1248/**
1249 * RORX
1250 */
1251BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rorx)(uint8_t bMode)
1252{
1253 static const struct
1254 {
1255 FPFNBS3FAR pfnWorker;
1256 bool fMemSrc;
1257 bool fOkay;
1258 RTCCUINTXREG uIn;
1259 RTCCUINTXREG uOut;
1260 } s_aTests[] =
1261 {
1262 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1263 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #0
1264 0, /* -> */ 0 },
1265 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #1
1266 ~(RTCCUINTXREG)2, /* -> */ ~(RTCCUINTXREG)0 >> 1 },
1267 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #2
1268 0, /* -> */ 0 },
1269 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #3
1270 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG_MAX >> 4) | (~(RTCCUINTXREG)2 << (sizeof(RTCCUINTXREG) * 8 - 4)) },
1271
1272 /* 32 bits register width: */
1273 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #4
1274 0, /* -> */ 0 },
1275 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #5
1276 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)(~(uint32_t)0 >> 1) },
1277 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #6
1278 0, /* -> */ 0 },
1279 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #7
1280 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)UINT32_C(0xdfffffff) },
1281
1282 /* encoding tests: */
1283 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_L1), false, false, // #8
1284 RTCCUINTXREG_MAX, /* -> */ 0 },
1285 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V1), false, false, // #9
1286 RTCCUINTXREG_MAX, /* -> */ 0 },
1287 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V15), false, false, // #10
1288 RTCCUINTXREG_MAX, /* -> */ 0 },
1289# if ARCH_BITS == 64 /* The VEX.X=0 encoding mean LES instruction in 32-bit and 16-bit mode. */
1290 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_X1), false, true, // #11
1291 UINT32_C(0xf1e2d3c5), /* -> */ (RTCCUINTXREG)UINT32_C(0x7c78b4f1) },
1292# endif
1293 };
1294
1295 BS3REGCTX Ctx;
1296 BS3TRAPFRAME TrapFrame;
1297 unsigned i, j;
1298 uint32_t uStdExtFeatEbx = 0;
1299 bool fSupportsRorX;
1300
1301 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1302 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1303 fSupportsRorX = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
1304
1305 /* Ensure the structures are allocated before we sample the stack pointer. */
1306 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1307 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1308
1309 /*
1310 * Create test context.
1311 */
1312 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1313
1314 /*
1315 * Do the tests twice, first with all flags set, then once again with
1316 * flags cleared. The flags are not supposed to be touched at all.
1317 */
1318 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1319 for (j = 0; j < 2; j++)
1320 {
1321 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1322 {
1323 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && s_aTests[i].fOkay && fSupportsRorX;
1324 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1325 uint64_t uExpectRbx, uExpectRip;
1326 RTCCUINTXREG uMemSrc, uMemSrcExpect;
1327 Ctx.rbx.uCcXReg = RTCCUINTXREG_MAX * 1019;
1328 if (!s_aTests[i].fMemSrc)
1329 {
1330 Ctx.rdx.uCcXReg = s_aTests[i].uIn;
1331 uMemSrcExpect = uMemSrc = ~s_aTests[i].uIn;
1332 }
1333 else
1334 {
1335 Ctx.rdx.uCcXReg = ~s_aTests[i].uIn;
1336 uMemSrcExpect = uMemSrc = s_aTests[i].uIn;
1337 Bs3RegCtxSetGrpDsFromCurPtr(&Ctx, &Ctx.rdi, &uMemSrc);
1338 }
1339 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
1340 uExpectRbx = fOkay ? s_aTests[i].uOut : Ctx.rbx.u;
1341 uExpectRip = Ctx.rip.u + (fOkay ? 6 + 1 : 0);
1342 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1343
1344 if ( TrapFrame.bXcpt != bExpectXcpt
1345 || TrapFrame.Ctx.rip.u != uExpectRip
1346 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1347 || TrapFrame.Ctx.rbx.u != uExpectRbx
1348 /* check that nothing else really changed: */
1349 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
1350 || TrapFrame.Ctx.rax.u != Ctx.rax.u
1351 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1352 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1353 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1354 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1355 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1356 || uMemSrc != uMemSrcExpect
1357 )
1358 {
1359 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uIn);
1360 if (TrapFrame.bXcpt != bExpectXcpt)
1361 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
1362 if (TrapFrame.Ctx.rip.u != uExpectRip)
1363 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1364 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1365 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1366 if (TrapFrame.Ctx.rbx.u != uExpectRbx)
1367 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", uExpectRbx, TrapFrame.Ctx.rbx.u);
1368
1369 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
1370 Bs3TestFailedF("Expected EFLAGS = %#06RX64, got %#06RX64",
1371 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
1372 if (TrapFrame.Ctx.rax.u != Ctx.rax.u)
1373 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", Ctx.rax.u, TrapFrame.Ctx.rax.u);
1374 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1375 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1376 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1377 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1378 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1379 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1380 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1381 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1382 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1383 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1384 if (uMemSrc != uMemSrcExpect)
1385 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
1386 }
1387 }
1388 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1389 }
1390
1391 return 0;
1392}
1393
1394
1395BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_andn)(uint8_t bMode)
1396{
1397#define ANDN_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_ZF | X86_EFL_OF | X86_EFL_SF)
1398#define ANDN_IGNORE_EFLAGS (uint16_t)(X86_EFL_AF | X86_EFL_PF) /* undefined, ignoring for now */
1399 static const struct
1400 {
1401 FPFNBS3FAR pfnWorker;
1402 bool fMemSrc;
1403 uint8_t cbInstr;
1404 RTCCUINTXREG uSrc1;
1405 RTCCUINTXREG uSrc2;
1406 RTCCUINTXREG uOut;
1407 uint16_t fEFlags;
1408 } s_aTests[] =
1409 {
1410 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1411 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #0
1412 0, 0, /* -> */ 0, X86_EFL_ZF },
1413 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #1
1414 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1415 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #2
1416 0, 0, /* -> */ 0, X86_EFL_ZF },
1417 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #3
1418 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1419
1420 /* 32-bit register width */
1421 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #4
1422 0, 0, /* -> */ 0, X86_EFL_ZF },
1423 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #5
1424 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1425 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #6
1426 0, 0, /* -> */ 0, X86_EFL_ZF },
1427 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #7
1428 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1429
1430 };
1431
1432 BS3REGCTX Ctx;
1433 BS3TRAPFRAME TrapFrame;
1434 unsigned i, j;
1435 uint32_t uStdExtFeatEbx = 0;
1436 bool fSupportsAndN;
1437
1438 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1439 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1440 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1);
1441
1442 /* Ensure the structures are allocated before we sample the stack pointer. */
1443 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1444 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1445
1446 /*
1447 * Create test context.
1448 */
1449 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1450
1451 /*
1452 * Do the tests twice, first with all flags set, then once again with
1453 * flags cleared. The flags are not supposed to be touched at all.
1454 */
1455 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1456 for (j = 0; j < 2; j++)
1457 {
1458 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1459 {
1460 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
1461 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1462 uint64_t uExpectRax, uExpectRip;
1463 RTCCUINTXREG uMemSrc2, uMemSrc2Expect;
1464
1465 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
1466 Ctx.rcx.uCcXReg = s_aTests[i].uSrc1;
1467 if (!s_aTests[i].fMemSrc)
1468 {
1469 Ctx.rbx.uCcXReg = s_aTests[i].uSrc2;
1470 uMemSrc2Expect = uMemSrc2 = ~s_aTests[i].uSrc2;
1471 }
1472 else
1473 {
1474 uMemSrc2Expect = uMemSrc2 = s_aTests[i].uSrc2;
1475 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc2);
1476 }
1477 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
1478 uExpectRax = fOkay ? s_aTests[i].uOut : Ctx.rax.u;
1479 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
1480 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1481
1482 if ( TrapFrame.bXcpt != bExpectXcpt
1483 || TrapFrame.Ctx.rip.u != uExpectRip
1484 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1485 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1486 || TrapFrame.Ctx.rax.u != uExpectRax
1487 /* check that nothing else really changed: */
1488 || (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
1489 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS)
1490 || (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
1491 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
1492 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1493 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1494 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1495 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1496 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1497 || uMemSrc2 != uMemSrc2Expect
1498 )
1499 {
1500 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
1501 if (TrapFrame.bXcpt != bExpectXcpt)
1502 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
1503 if (TrapFrame.Ctx.rip.u != uExpectRip)
1504 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1505 if (TrapFrame.Ctx.rax.u != uExpectRax)
1506 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
1507 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1508 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1509 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
1510 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
1511 if ( (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
1512 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS))
1513 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
1514 (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS);
1515 if ( (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
1516 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS))
1517 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
1518 Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS,
1519 TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS);
1520
1521 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1522 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1523 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1524 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1525 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1526 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1527 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1528 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1529 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1530 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1531 if (uMemSrc2 != uMemSrc2Expect)
1532 Bs3TestFailedF("Expected uMemSrc2 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc2Expect, (uint64_t)uMemSrc2);
1533 }
1534 }
1535 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1536 }
1537
1538 return 0;
1539}
1540
1541/*
1542 * For testing BEXTR, SHLX SARX & SHRX.
1543 */
1544typedef struct BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T
1545{
1546 RTCCUINTXREG uSrc1;
1547 RTCCUINTXREG uSrc2;
1548 RTCCUINTXREG uOut;
1549 uint16_t fEflOut;
1550} BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T;
1551
1552typedef struct BS3CPUINSTR2_TEST_Gy_Ey_By_T
1553{
1554 FPFNBS3FAR pfnWorker;
1555 bool fMemSrc;
1556 uint8_t cbInstr;
1557 uint8_t cSubTests;
1558 BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const *paSubTests;
1559} BS3CPUINSTR2_TEST_Gy_Ey_By_T;
1560
1561static uint8_t bs3CpuInstr2_Common_Gy_Ey_By(uint8_t bMode, BS3CPUINSTR2_TEST_Gy_Ey_By_T const *paTests, unsigned cTests,
1562 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
1563{
1564 BS3REGCTX Ctx;
1565 BS3TRAPFRAME TrapFrame;
1566 unsigned i, j, k;
1567 uint32_t uStdExtFeatEbx = 0;
1568 bool fSupportsInstr;
1569
1570 fEflCheck &= ~fEflIgnore;
1571
1572 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1573 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1574 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
1575
1576 /* Ensure the structures are allocated before we sample the stack pointer. */
1577 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1578 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1579
1580 /*
1581 * Create test context.
1582 */
1583 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1584
1585 /*
1586 * Do the tests twice, first with all flags set, then once again with
1587 * flags cleared. The flags are not supposed to be touched at all.
1588 */
1589 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1590 for (j = 0; j < 2; j++)
1591 {
1592 for (i = 0; i < cTests; i++)
1593 {
1594 for (k = 0; k < paTests[i].cSubTests; k++)
1595 {
1596 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
1597 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1598 uint64_t uExpectRax, uExpectRip;
1599 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
1600
1601 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
1602 Ctx.rcx.uCcXReg = paTests[i].paSubTests[k].uSrc2;
1603 if (!paTests[i].fMemSrc)
1604 {
1605 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc1;
1606 uMemSrc1Expect = uMemSrc1 = ~paTests[i].paSubTests[k].uSrc1;
1607 }
1608 else
1609 {
1610 uMemSrc1Expect = uMemSrc1 = paTests[i].paSubTests[k].uSrc1;
1611 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
1612 }
1613 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
1614 uExpectRax = fOkay ? paTests[i].paSubTests[k].uOut : Ctx.rax.u;
1615 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
1616 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1617
1618 if ( TrapFrame.bXcpt != bExpectXcpt
1619 || TrapFrame.Ctx.rip.u != uExpectRip
1620 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1621 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1622 || TrapFrame.Ctx.rax.u != uExpectRax
1623 /* check that nothing else really changed: */
1624 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
1625 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
1626 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
1627 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
1628 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1629 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1630 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1631 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1632 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1633 || uMemSrc1 != uMemSrc1Expect
1634 )
1635 {
1636 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT,
1637 i, k, paTests[i].paSubTests[k].uSrc1, paTests[i].paSubTests[k].uSrc2);
1638 if (TrapFrame.bXcpt != bExpectXcpt)
1639 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
1640 if (TrapFrame.Ctx.rip.u != uExpectRip)
1641 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1642 if (TrapFrame.Ctx.rax.u != uExpectRax)
1643 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
1644 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1645 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1646 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
1647 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
1648 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
1649 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
1650 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
1651 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
1652 TrapFrame.Ctx.rflags.u16 & fEflCheck);
1653 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
1654 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
1655 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
1656 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
1657 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
1658
1659 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1660 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1661 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1662 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1663 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1664 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1665 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1666 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1667 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1668 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1669 if (uMemSrc1 != uMemSrc1Expect)
1670 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
1671 }
1672 }
1673 }
1674 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1675 }
1676
1677 return 0;
1678}
1679
1680
1681BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bextr)(uint8_t bMode)
1682{
1683 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1684 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1685 {
1686 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
1687 { 0, RT_MAKE_U16(16, 33), /* -> */ 0, X86_EFL_ZF },
1688 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0},
1689 { ~(RTCCUINTXREG)7, RT_MAKE_U16(40, 8), /* -> */ ARCH_BITS == 64 ? 0xff : 0x00, ARCH_BITS == 64 ? 0 : X86_EFL_ZF },
1690 };
1691
1692 /* 32-bit register width */
1693 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1694 {
1695 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
1696 { 0, RT_MAKE_U16(16, 18), /* -> */ 0, X86_EFL_ZF },
1697 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0 },
1698 { ~(RTCCUINTXREG)7, RT_MAKE_U16(24, 8), /* -> */ 0xff, 0 },
1699 { ~(RTCCUINTXREG)7, RT_MAKE_U16(31, 9), /* -> */ 1, 0 },
1700 { ~(RTCCUINTXREG)7, RT_MAKE_U16(42, 8), /* -> */ 0, X86_EFL_ZF },
1701 };
1702
1703 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1704 {
1705 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1706 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1707 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1708 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1709 };
1710 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
1711 X86_EFL_STATUS_BITS, X86_EFL_AF | X86_EFL_SF | X86_EFL_PF);
1712}
1713
1714
1715BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bzhi)(uint8_t bMode)
1716{
1717 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1718 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1719 {
1720 { 0, 0, /* -> */ 0, X86_EFL_ZF },
1721 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
1722 { 0, 64, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
1723 { ~(RTCCUINTXREG)0, 64, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
1724 { ~(RTCCUINTXREG)0, 63,
1725 /* -> */ ARCH_BITS >= 64 ? ~(RTCCUINTXREG)0 >> 1 : ~(RTCCUINTXREG)0, ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
1726 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 24, /* -> */ UINT32_C(0x00849607), 0 },
1727 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 33,
1728 /* -> */ ARCH_BITS >= 64 ? UINT64_C(0x1e3849607) : UINT32_C(0xe3849607), ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
1729 };
1730
1731 /* 32-bit register width */
1732 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1733 {
1734 { 0, 0, /* -> */ 0, X86_EFL_ZF },
1735 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
1736 { 0, 32, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
1737 { ~(RTCCUINTXREG)0, 32, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
1738 { ~(RTCCUINTXREG)0, 31, /* -> */ UINT32_MAX >> 1, 0 },
1739 { UINT32_C(0x1230fd34), 15, /* -> */ UINT32_C(0x00007d34), 0 },
1740 };
1741
1742 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1743 {
1744 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1745 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1746 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1747 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1748 };
1749 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2,
1750 X86_EFL_STATUS_BITS, 0);
1751}
1752
1753
1754/** @note This is a Gy_By_Ey format instruction, so we're switching the two
1755 * source registers around when calling bs3CpuInstr2_Common_Gy_Ey_By.
1756 * Sorry for the confusion, but it saves some unnecessary code dup. */
1757BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pdep)(uint8_t bMode)
1758{
1759 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1760 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1761 { /* Mask (RBX/[FS:xBX]), source=RCX */
1762 { 0, 0, /* -> */ 0, 0 },
1763 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
1764 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
1765 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
1766#if ARCH_BITS >= 64
1767 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x3586049947589201), 0 },
1768 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x3586049947588000), 0 },
1769#endif
1770 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
1771 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x47588000), 0 },
1772 };
1773
1774 /* 32-bit register width */
1775 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1776 { /* Mask (EBX/[FS:xBX]), source=ECX */
1777 { 0, 0, /* -> */ 0, 0 },
1778 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
1779 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
1780 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
1781 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x01010101), 0 },
1782 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x01010000), 0 },
1783 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
1784 };
1785
1786 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1787 {
1788 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1789 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1790 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1791 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1792 };
1793 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
1794}
1795
1796
1797/** @note Same note as for bs3CpuInstr2_pdep */
1798BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pext)(uint8_t bMode)
1799{
1800 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1801 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1802 { /* Mask (RBX/[FS:xBX]), source=RCX */
1803 { 0, 0, /* -> */ 0, 0 },
1804 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
1805 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
1806 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
1807#if ARCH_BITS >= 64
1808 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x00000000007fffff), 0 },
1809 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x00000000007ffffe), 0 },
1810#endif
1811 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
1812 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
1813 };
1814
1815 /* 32-bit register width */
1816 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1817 { /* Mask (EBX/[FS:xBX]), source=ECX */
1818 { 0, 0, /* -> */ 0, 0 },
1819 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
1820 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
1821 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
1822 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x0000000f), 0 },
1823 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x0000000e), 0 },
1824 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
1825 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
1826 };
1827
1828 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1829 {
1830 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1831 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1832 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1833 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1834 };
1835 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
1836}
1837
1838
1839BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shlx)(uint8_t bMode)
1840{
1841 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1842 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1843 {
1844 { 0, 0, /* -> */ 0, 0 },
1845 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
1846 { ~(RTCCUINTXREG)7, 8, /* -> */ ~(RTCCUINTXREG)0x7ff, 0},
1847 { ~(RTCCUINTXREG)7, 40, /* -> */ ~(RTCCUINTXREG)7 << (ARCH_BITS == 64 ? 40 : 8), 0 },
1848 { ~(RTCCUINTXREG)7, 72, /* -> */ ~(RTCCUINTXREG)7 << 8, 0 },
1849 };
1850
1851 /* 32-bit register width */
1852 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1853 {
1854 { 0, 0, /* -> */ 0, 0 },
1855 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
1856 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
1857 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
1858 };
1859
1860 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1861 {
1862 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1863 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1864 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1865 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1866 };
1867 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
1868 0, 0);
1869}
1870
1871
1872BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sarx)(uint8_t bMode)
1873{
1874 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1875 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1876 {
1877 { 0, 0, /* -> */ 0, 0 },
1878 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
1879 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ ~(RTCCUINTXREG)0, 0 },
1880 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ ~(RTCCUINTXREG)0, 0 },
1881 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
1882 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
1883 };
1884
1885 /* 32-bit register width */
1886 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1887 {
1888 { 0, 0, /* -> */ 0, 0 },
1889 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
1890 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0xffffff80), 0 },
1891 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0xffffff80), 0 },
1892 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
1893 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
1894 };
1895
1896 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1897 {
1898 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1899 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1900 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1901 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1902 };
1903 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
1904 0, 0);
1905}
1906
1907
1908BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shrx)(uint8_t bMode)
1909{
1910 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1911 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
1912 {
1913 { 0, 0, /* -> */ 0, 0 },
1914 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
1915 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ 1, 0 },
1916 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ 1, 0 },
1917 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
1918 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
1919 };
1920
1921 /* 32-bit register width */
1922 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
1923 {
1924 { 0, 0, /* -> */ 0, 0 },
1925 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
1926 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0x80), 0 },
1927 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0x80), 0 },
1928 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
1929 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
1930 };
1931
1932 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
1933 {
1934 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1935 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
1936 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1937 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
1938 };
1939 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
1940 0, 0);
1941}
1942
1943
1944/*
1945 * For testing BLSR, BLSMSK, and BLSI.
1946 */
1947typedef struct BS3CPUINSTR2_SUBTEST_By_Ey_T
1948{
1949 RTCCUINTXREG uSrc;
1950 RTCCUINTXREG uDst;
1951 uint16_t fEflOut;
1952} BS3CPUINSTR2_SUBTEST_By_Ey_T;
1953
1954typedef struct BS3CPUINSTR2_TEST_By_Ey_T
1955{
1956 FPFNBS3FAR pfnWorker;
1957 bool fMemSrc;
1958 uint8_t cbInstr;
1959 uint8_t cSubTests;
1960 BS3CPUINSTR2_SUBTEST_By_Ey_T const *paSubTests;
1961} BS3CPUINSTR2_TEST_By_Ey_T;
1962
1963static uint8_t bs3CpuInstr2_Common_By_Ey(uint8_t bMode, BS3CPUINSTR2_TEST_By_Ey_T const *paTests, unsigned cTests,
1964 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
1965{
1966 BS3REGCTX Ctx;
1967 BS3TRAPFRAME TrapFrame;
1968 unsigned i, j, k;
1969 uint32_t uStdExtFeatEbx = 0;
1970 bool fSupportsInstr;
1971
1972 fEflCheck &= ~fEflIgnore;
1973
1974 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1975 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1976 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
1977
1978 /* Ensure the structures are allocated before we sample the stack pointer. */
1979 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1980 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1981
1982 /*
1983 * Create test context.
1984 */
1985 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1986
1987 /*
1988 * Do the tests twice, first with all flags set, then once again with
1989 * flags cleared. The flags are not supposed to be touched at all.
1990 */
1991 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1992 for (j = 0; j < 2; j++)
1993 {
1994 for (i = 0; i < cTests; i++)
1995 {
1996 for (k = 0; k < paTests[i].cSubTests; k++)
1997 {
1998 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
1999 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2000 uint64_t uExpectRax, uExpectRip;
2001 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2002
2003 Ctx.rax.uCcXReg = ~paTests[i].paSubTests[k].uSrc ^ 0x593e7591;
2004 if (!paTests[i].fMemSrc)
2005 {
2006 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
2007 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
2008 }
2009 else
2010 {
2011 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
2012 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2013 }
2014 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
2015 uExpectRax = fOkay ? paTests[i].paSubTests[k].uDst : Ctx.rax.u;
2016 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
2017 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2018
2019 if ( TrapFrame.bXcpt != bExpectXcpt
2020 || TrapFrame.Ctx.rip.u != uExpectRip
2021 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2022 || TrapFrame.Ctx.rax.u != uExpectRax
2023 /* check that nothing else really changed: */
2024 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2025 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
2026 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2027 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2028 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2029 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2030 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2031 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2032 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2033 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2034 || uMemSrc != uMemSrcExpect
2035 )
2036 {
2037 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
2038 i, k, paTests[i].paSubTests[k].uSrc);
2039 if (TrapFrame.bXcpt != bExpectXcpt)
2040 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2041 if (TrapFrame.Ctx.rip.u != uExpectRip)
2042 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2043 if (TrapFrame.Ctx.rax.u != uExpectRax)
2044 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2045 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2046 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2047 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2048 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
2049 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2050 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
2051 TrapFrame.Ctx.rflags.u16 & fEflCheck);
2052 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2053 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
2054 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2055 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
2056 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
2057
2058 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2059 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2060 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2061 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2062 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2063 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2064 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2065 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2066 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2067 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2068 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2069 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2070 if (uMemSrc != uMemSrcExpect)
2071 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2072 }
2073 }
2074 }
2075 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2076 }
2077
2078 return 0;
2079}
2080
2081
2082BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsr)(uint8_t bMode)
2083{
2084 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2085 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2086 {
2087 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2088 { 1, /* -> */ 0, X86_EFL_ZF },
2089 { 2, /* -> */ 0, X86_EFL_ZF },
2090 { 3, /* -> */ 2, 0 },
2091 { 5, /* -> */ 4, 0 },
2092 { 6, /* -> */ 4, 0 },
2093 { 7, /* -> */ 6, 0 },
2094 { 9, /* -> */ 8, 0 },
2095 { 10, /* -> */ 8, 0 },
2096 { ~(RTCCUINTXREG)1, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
2097 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2), X86_EFL_SF },
2098 };
2099
2100 /* 32-bit register width */
2101 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2102 {
2103 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2104 { 1, /* -> */ 0, X86_EFL_ZF },
2105 { ~(RTCCUINTXREG)1, /* -> */ UINT32_C(0xfffffffc), X86_EFL_SF },
2106 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x80000000), X86_EFL_SF },
2107 };
2108
2109 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2110 {
2111 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2112 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2113 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2114 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2115 };
2116 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2117 X86_EFL_STATUS_BITS, 0);
2118}
2119
2120
2121BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsmsk)(uint8_t bMode)
2122{
2123 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2124 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2125 {
2126 { 0, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
2127 { 1, /* -> */ 1, 0 },
2128 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2129 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ ~((RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2)), 0 },
2130 };
2131
2132 /* 32-bit register width */
2133 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2134 {
2135 { 0, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
2136 { 1, /* -> */ 1, 0 },
2137 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2138 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x7fffffff), 0},
2139 };
2140
2141 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2142 {
2143 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2144 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2145 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2146 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2147 };
2148 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2149 X86_EFL_STATUS_BITS, 0);
2150}
2151
2152
2153BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsi)(uint8_t bMode)
2154{
2155 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2156 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2157 {
2158 { 0, /* -> */ 0, X86_EFL_ZF },
2159 { 1, /* -> */ 1, X86_EFL_CF },
2160 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2161 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), X86_EFL_CF },
2162 };
2163
2164 /* 32-bit register width */
2165 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2166 {
2167 { 0, /* -> */ 0, X86_EFL_ZF },
2168 { 1, /* -> */ 1, X86_EFL_CF },
2169 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2170 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x40000000), X86_EFL_CF },
2171 };
2172
2173 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2174 {
2175 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2176 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2177 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2178 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2179 };
2180 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2181 X86_EFL_STATUS_BITS, 0);
2182}
2183
2184
2185/*
2186 * MULX (BMI2) - destination registers (/r & vvvv) = r/m * rDX
2187 */
2188BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mulx)(uint8_t bMode)
2189{
2190 static const struct
2191 {
2192 FPFNBS3FAR pfnWorker;
2193 bool fMemSrc;
2194 bool fSameDst;
2195 uint8_t cbInstr;
2196 RTCCUINTXREG uSrc1;
2197 RTCCUINTXREG uSrc2;
2198 RTCCUINTXREG uDst1;
2199 RTCCUINTXREG uDst2;
2200 } s_aTests[] =
2201 {
2202 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2203 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #0
2204 0, 0, /* -> */ 0, 0 },
2205 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #1
2206 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2207 { BS3_CMN_NM(bs3CpuInstr2_mulx_RCX_RCX_RBX_RDX_icebp), false, true, 5, // #2
2208 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, ~(RTCCUINTXREG)1 },
2209 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #3
2210 2, 2, /* -> */ 0, 4 },
2211 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #4
2212 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2213
2214 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #5
2215 0, 0, /* -> */ 0, 0 },
2216 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #6
2217 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2218 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #7
2219 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2220
2221 /* 32-bit register width */
2222 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #8
2223 0, 0, /* -> */ 0, 0 },
2224 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #9
2225 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2226 { BS3_CMN_NM(bs3CpuInstr2_mulx_ECX_ECX_EBX_EDX_icebp), false, true, 5, // #10
2227 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, ~(uint32_t)1 },
2228 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #11
2229 2, 2, /* -> */ 0, 4 },
2230 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #12
2231 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2232
2233 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #13
2234 0, 0, /* -> */ 0, 0 },
2235 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #14
2236 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2237 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #15
2238 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2239 };
2240
2241 BS3REGCTX Ctx;
2242 BS3TRAPFRAME TrapFrame;
2243 unsigned i, j;
2244 uint32_t uStdExtFeatEbx = 0;
2245 bool fSupportsAndN;
2246
2247 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2248 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2249 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
2250
2251 /* Ensure the structures are allocated before we sample the stack pointer. */
2252 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2253 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2254
2255 /*
2256 * Create test context.
2257 */
2258 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2259
2260 /*
2261 * Do the tests twice, first with all flags set, then once again with
2262 * flags cleared. The flags are not supposed to be touched at all.
2263 */
2264 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2265 for (j = 0; j < 2; j++)
2266 {
2267 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2268 {
2269 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
2270 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2271 uint64_t uExpectRax, uExpectRcx, uExpectRip;
2272 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
2273
2274 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2275 Ctx.rcx.uCcXReg = RTCCUINTXREG_MAX * 4095;
2276 Ctx.rdx.uCcXReg = s_aTests[i].uSrc2;
2277 if (!s_aTests[i].fMemSrc)
2278 {
2279 Ctx.rbx.uCcXReg = s_aTests[i].uSrc1;
2280 uMemSrc1Expect = uMemSrc1 = ~s_aTests[i].uSrc1;
2281 }
2282 else
2283 {
2284 uMemSrc1Expect = uMemSrc1 = s_aTests[i].uSrc1;
2285 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
2286 }
2287 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2288 uExpectRax = fOkay && !s_aTests[i].fSameDst ? s_aTests[i].uDst1 : Ctx.rax.u;
2289 uExpectRcx = fOkay ? s_aTests[i].uDst2 : Ctx.rcx.u;
2290 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2291 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2292
2293 if ( TrapFrame.bXcpt != bExpectXcpt
2294 || TrapFrame.Ctx.rip.u != uExpectRip
2295 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2296 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2297 || TrapFrame.Ctx.rax.u != uExpectRax
2298 || TrapFrame.Ctx.rcx.u != uExpectRcx
2299 /* check that nothing else really changed: */
2300 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
2301 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2302 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2303 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2304 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2305 || uMemSrc1 != uMemSrc1Expect
2306 )
2307 {
2308 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
2309 if (TrapFrame.bXcpt != bExpectXcpt)
2310 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2311 if (TrapFrame.Ctx.rip.u != uExpectRip)
2312 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2313 if (TrapFrame.Ctx.rax.u != uExpectRax)
2314 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2315 if (TrapFrame.Ctx.rcx.u != uExpectRcx)
2316 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", uExpectRcx, TrapFrame.Ctx.rcx.u);
2317 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2318 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2319 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2320 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2321
2322 if ( (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
2323 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2324 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
2325 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2326 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2327 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2328 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2329 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2330 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2331 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2332 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2333 if (uMemSrc1 != uMemSrc1Expect)
2334 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
2335 }
2336 }
2337 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2338 }
2339
2340 return 0;
2341}
2342
2343
2344/*
2345 * POPCNT - Intel: POPCNT; AMD: ABM.
2346 */
2347BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_popcnt)(uint8_t bMode)
2348{
2349 static const struct
2350 {
2351 FPFNBS3FAR pfnWorker;
2352 bool fMemSrc;
2353 uint8_t cWidth;
2354 uint8_t cbInstr;
2355 RTCCUINTXREG uSrc;
2356 RTCCUINTXREG uDst;
2357 uint16_t fEFlags;
2358 } s_aTests[] =
2359 {
2360 /* 16-bit register width */
2361 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #0
2362 0, /* -> */ 0, X86_EFL_ZF },
2363 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #1
2364 ~(RTCCUINTXREG)0, /* -> */ 16, 0 },
2365 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #2
2366 UINT16_C(0xffff), /* -> */ 16, 0 },
2367 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #3
2368 UINT16_C(0x0304), /* -> */ 3, 0 },
2369 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #4
2370 UINT16_C(0xd569), /* -> */ 9, 0},
2371 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #5
2372 0, /* -> */ 0, X86_EFL_ZF },
2373
2374 /* 32-bit register width */
2375 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #6
2376 0, /* -> */ 0, X86_EFL_ZF },
2377 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #7
2378 ~(RTCCUINTXREG)0, /* -> */ 32, 0},
2379 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #8
2380 UINT32_C(0x01020304), /* -> */ 5, 0},
2381 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #9
2382 0, /* -> */ 0, X86_EFL_ZF },
2383 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #10
2384 UINT32_C(0x49760948), /* -> */ 12, 0 },
2385
2386#if ARCH_BITS == 64
2387 /* 64-bit register width */
2388 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #11
2389 0, /* -> */ 0, X86_EFL_ZF },
2390 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #12
2391 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2392 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #13
2393 UINT64_C(0x1234123412341234), /* -> */ 5*4, 0 },
2394 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #14
2395 0, /* -> */ 0, X86_EFL_ZF },
2396 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #15
2397 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2398 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #16
2399 UINT64_C(0x5908760293769087), /* -> */ 26, 0 },
2400#endif
2401 };
2402
2403 BS3REGCTX Ctx;
2404 BS3TRAPFRAME TrapFrame;
2405 unsigned i, j;
2406 bool const fSupportsPopCnt = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2407 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_POPCNT);
2408
2409 /* Ensure the structures are allocated before we sample the stack pointer. */
2410 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2411 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2412
2413 /*
2414 * Create test context.
2415 */
2416 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2417
2418 /*
2419 * Do the tests twice, first with all flags set, then once again with
2420 * flags cleared. The flags are not supposed to be touched at all.
2421 */
2422 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2423 for (j = 0; j < 2; j++)
2424 {
2425 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2426 {
2427 bool const fOkay = fSupportsPopCnt;
2428 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2429 uint64_t uExpectRax, uExpectRip;
2430 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2431
2432 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2433 if (!s_aTests[i].fMemSrc)
2434 {
2435 Ctx.rbx.uCcXReg = s_aTests[i].uSrc;
2436 uMemSrcExpect = uMemSrc = ~s_aTests[i].uSrc;
2437 }
2438 else
2439 {
2440 uMemSrcExpect = uMemSrc = s_aTests[i].uSrc;
2441 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2442 }
2443 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2444 uExpectRax = fOkay ? s_aTests[i].uDst : Ctx.rax.u;
2445 if (s_aTests[i].cWidth == 16)
2446 uExpectRax = (uExpectRax & UINT16_MAX) | (Ctx.rax.u & ~(uint64_t)UINT16_MAX);
2447
2448 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2449 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2450
2451 if ( TrapFrame.bXcpt != bExpectXcpt
2452 || TrapFrame.Ctx.rip.u != uExpectRip
2453 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2454 || TrapFrame.Ctx.rax.u != uExpectRax
2455 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16)
2456 /* check that nothing else really changed: */
2457 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2458 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2459 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2460 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2461 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2462 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2463 || uMemSrc != uMemSrcExpect
2464 )
2465 {
2466 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc);
2467 if (TrapFrame.bXcpt != bExpectXcpt)
2468 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2469 if (TrapFrame.Ctx.rip.u != uExpectRip)
2470 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2471 if (TrapFrame.Ctx.rax.u != uExpectRax)
2472 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2473 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2474 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2475 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16))
2476 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32",
2477 fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
2478
2479 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2480 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2481 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2482 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2483 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2484 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2485 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2486 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2487 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2488 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2489 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2490 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2491 if (uMemSrc != uMemSrcExpect)
2492 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2493 }
2494 }
2495 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2496 }
2497
2498 return 0;
2499}
2500
2501/*
2502 * CRC32 - SSE4.2
2503 */
2504BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_crc32)(uint8_t bMode)
2505{
2506 typedef struct BS3CPUINSTR2_CRC32_VALUES_T
2507 {
2508 uint32_t uDstIn;
2509 uint32_t uDstOut;
2510 uint64_t uSrc;
2511 } BS3CPUINSTR2_CRC32_VALUES_T;
2512 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues1[] =
2513 {
2514 { UINT32_C(0000000000), UINT32_C(0000000000), UINT8_C(0000) },
2515 { UINT32_C(0xffffffff), UINT32_C(0x25502c8c), UINT8_C(0xea) },
2516 { UINT32_C(0x25502c8c), UINT32_C(0x474224a6), UINT8_C(0xea) },
2517 { UINT32_C(0x474224a6), UINT32_C(0x0c7f9048), UINT8_C(0xea) },
2518 { UINT32_C(0x0c7f9048), UINT32_C(0x39c5b9e0), UINT8_C(0x01) },
2519 { UINT32_C(0x39c5b9e0), UINT32_C(0x2493fabc), UINT8_C(0x04) },
2520 { UINT32_C(0x2493fabc), UINT32_C(0x0b05c4d6), UINT8_C(0x27) },
2521 { UINT32_C(0x0b05c4d6), UINT32_C(0xbe26a561), UINT8_C(0x2a) },
2522 { UINT32_C(0xbe26a561), UINT32_C(0xe1855652), UINT8_C(0x63) },
2523 { UINT32_C(0xe1855652), UINT32_C(0xc67efe3f), UINT8_C(0xa7) },
2524 { UINT32_C(0xc67efe3f), UINT32_C(0x227028cd), UINT8_C(0xfd) },
2525 { UINT32_C(0x227028cd), UINT32_C(0xf4559a1d), UINT8_C(0xea) },
2526 };
2527 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues2[] =
2528 {
2529 { UINT32_C(0000000000), UINT32_C(0000000000), UINT16_C(000000) },
2530 { UINT32_C(0xffffffff), UINT32_C(0xd550e2a0), UINT16_C(0x04d2) },
2531 { UINT32_C(0xd550e2a0), UINT32_C(0x38e07a0a), UINT16_C(0xe8cc) },
2532 { UINT32_C(0x38e07a0a), UINT32_C(0x60ebd519), UINT16_C(0x82a2) },
2533 { UINT32_C(0x60ebd519), UINT32_C(0xaaa127b5), UINT16_C(0x0fff) },
2534 { UINT32_C(0xaaa127b5), UINT32_C(0xb13175c6), UINT16_C(0x00ff) },
2535 { UINT32_C(0xb13175c6), UINT32_C(0x3a226f1b), UINT16_C(0x0300) },
2536 { UINT32_C(0x3a226f1b), UINT32_C(0xbaedef0c), UINT16_C(0x270f) },
2537 { UINT32_C(0xbaedef0c), UINT32_C(0x2d18866e), UINT16_C(0x3ff6) },
2538 { UINT32_C(0x2d18866e), UINT32_C(0x07e2e954), UINT16_C(0x9316) },
2539 { UINT32_C(0x07e2e954), UINT32_C(0x95f82acb), UINT16_C(0xa59c) },
2540 };
2541 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues4[] =
2542 {
2543 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000) },
2544 { UINT32_C(0xffffffff), UINT32_C(0xc9a7250e), UINT32_C(0x0270fa68) },
2545 { UINT32_C(0xc9a7250e), UINT32_C(0x7340d175), UINT32_C(0x23729736) },
2546 { UINT32_C(0x7340d175), UINT32_C(0x7e17b67d), UINT32_C(0x8bc75d35) },
2547 { UINT32_C(0x7e17b67d), UINT32_C(0x5028eb71), UINT32_C(0x0e9bebf2) },
2548 { UINT32_C(0x5028eb71), UINT32_C(0xc0a7f45a), UINT32_C(0x000001bc) },
2549 { UINT32_C(0xc0a7f45a), UINT32_C(0xa96f4012), UINT32_C(0x0034ba02) },
2550 { UINT32_C(0xa96f4012), UINT32_C(0xb27c0718), UINT32_C(0x0000002a) },
2551 { UINT32_C(0xb27c0718), UINT32_C(0x79fb2d35), UINT32_C(0x0153158e) },
2552 { UINT32_C(0x79fb2d35), UINT32_C(0x23434fc9), UINT32_C(0x02594882) },
2553 { UINT32_C(0x23434fc9), UINT32_C(0x354bf3b6), UINT32_C(0xb230b8f3) },
2554 };
2555#if ARCH_BITS >= 64
2556 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues8[] =
2557 {
2558 { UINT32_C(0000000000), UINT32_C(0000000000), UINT64_C(000000000000000000) },
2559 { UINT32_C(0xffffffff), UINT32_C(0xadc36834), UINT64_C(0x02b0b5e2a975c1cc) },
2560 { UINT32_C(0xadc36834), UINT32_C(0xf0e893c9), UINT64_C(0x823d386bf7517583) },
2561 { UINT32_C(0xf0e893c9), UINT32_C(0x1a22a837), UINT64_C(0x0481f5311fa061d0) },
2562 { UINT32_C(0x1a22a837), UINT32_C(0xcf8b6d61), UINT64_C(0x13fa70f64d52a92d) },
2563 { UINT32_C(0xcf8b6d61), UINT32_C(0xc7dde203), UINT64_C(0x3ccc8b035903d3e1) },
2564 { UINT32_C(0xc7dde203), UINT32_C(0xd42b5823), UINT64_C(0x0000011850ec2fac) },
2565 { UINT32_C(0xd42b5823), UINT32_C(0x8b1ce49e), UINT64_C(0x0000000000001364) },
2566 { UINT32_C(0x8b1ce49e), UINT32_C(0x1af31710), UINT64_C(0x000000057840205a) },
2567 { UINT32_C(0x1af31710), UINT32_C(0xdea35e8b), UINT64_C(0x2e5d93688d9a0bfa) },
2568 { UINT32_C(0xdea35e8b), UINT32_C(0x594c013a), UINT64_C(0x8ac7230489e7ffff) },
2569 { UINT32_C(0x594c013a), UINT32_C(0x27b061e5), UINT64_C(0x6bf037ae325f1c71) },
2570 { UINT32_C(0x27b061e5), UINT32_C(0x3120b5f7), UINT64_C(0x0fffffff34503556) },
2571 };
2572#endif
2573 static const struct
2574 {
2575 FPFNBS3FAR pfnWorker;
2576 bool fMemSrc;
2577 uint8_t cbOp;
2578 uint8_t cValues;
2579 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues;
2580 } s_aTests[] =
2581 {
2582 /* 8-bit register width */
2583 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BL_icebp), false, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
2584 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_byte_FSxBX_icebp), true, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
2585
2586 /* 16-bit register width */
2587 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BX_icebp), false, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
2588 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_word_FSxBX_icebp), true, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
2589
2590 /* 32-bit register width */
2591 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
2592 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
2593#if ARCH_BITS >= 64
2594 /* 32-bit register width */
2595 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
2596 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
2597#endif
2598 };
2599
2600 BS3REGCTX Ctx;
2601 BS3TRAPFRAME TrapFrame;
2602 unsigned i, j;
2603 bool const fSupportsCrc32 = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2604 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_SSE4_2);
2605
2606 /* Ensure the structures are allocated before we sample the stack pointer. */
2607 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2608 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2609
2610 /*
2611 * Create test context.
2612 */
2613 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2614
2615 /*
2616 * Do the tests twice, first with all flags set, then once again with
2617 * flags cleared. The flags are not supposed to be touched at all.
2618 */
2619 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2620 for (j = 0; j < 2; j++)
2621 {
2622 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2623 {
2624 uint8_t const cbOp = s_aTests[i].cbOp;
2625 unsigned const cValues = s_aTests[i].cValues;
2626 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
2627 unsigned iValue;
2628 bool const fOkay = fSupportsCrc32;
2629 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2630 uint64_t const uSrcGarbage = ( cbOp == 1 ? UINT64_C(0x03948314d0f03400)
2631 : cbOp == 2 ? UINT64_C(0x03948314d0f00000)
2632 : cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
2633 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
2634 uint64_t uExpectRip;
2635
2636 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2637 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
2638
2639 for (iValue = 0; iValue < cValues; iValue++)
2640 {
2641 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
2642 uint64_t uMemSrc, uMemSrcExpect;
2643
2644 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
2645 if (!s_aTests[i].fMemSrc)
2646 {
2647 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
2648 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
2649 }
2650 else
2651 {
2652 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
2653 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2654 }
2655
2656 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2657
2658 if ( TrapFrame.bXcpt != bExpectXcpt
2659 || TrapFrame.Ctx.rip.u != uExpectRip
2660 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2661 || TrapFrame.Ctx.rax.u != uExpectRax
2662 /* check that nothing else really changed: */
2663 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
2664 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2665 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2666 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2667 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2668 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2669 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2670 || uMemSrc != uMemSrcExpect
2671 )
2672 {
2673 Bs3TestFailedF("test #%i value #%i failed: input %#RX32, %#RX64",
2674 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
2675 if (TrapFrame.bXcpt != bExpectXcpt)
2676 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2677 if (TrapFrame.Ctx.rip.u != uExpectRip)
2678 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2679 if (TrapFrame.Ctx.rax.u != uExpectRax)
2680 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2681 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2682 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2683
2684 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
2685 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
2686 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2687 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2688 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2689 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2690 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2691 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2692 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2693 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2694 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2695 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2696 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2697 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2698 if (uMemSrc != uMemSrcExpect)
2699 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2700 }
2701 }
2702 }
2703 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2704 }
2705
2706 return 0;
2707}
2708
2709#if 0 /* Program for generating CRC32 value sets: */
2710#include <stdio.h>
2711#include <stdint.h>
2712#include <stdlib.h>
2713
2714int main(int argc, char **argv)
2715{
2716 int cbOp = atoi(argv[1]);
2717 uint32_t uBefore = atoi(argv[2]);
2718 int i = 3;
2719 while (i < argc)
2720 {
2721 unsigned long long uValue = strtoull(argv[i], NULL, 0);
2722 uint32_t uAfter = uBefore;
2723 switch (cbOp)
2724 {
2725 case 1:
2726 __asm__ __volatile__("crc32b %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint8_t)uValue));
2727 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT8_C(%#04x) },\n",
2728 uBefore, uAfter, (unsigned)(uint8_t)uValue);
2729 break;
2730 case 2:
2731 __asm__ __volatile__("crc32w %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint16_t)uValue));
2732 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT16_C(%#06x) },\n",
2733 uBefore, uAfter, (unsigned)(uint16_t)uValue);
2734 break;
2735 case 4:
2736 __asm__ __volatile__("crc32l %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint32_t)uValue));
2737 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT32_C(%#010x) },\n",
2738 uBefore, uAfter, (uint32_t)uValue);
2739 break;
2740 case 8:
2741 {
2742 uint64_t u64After = uBefore;
2743 __asm__ __volatile__("crc32q %2, %0" : "=r" (u64After) : "0" (u64After), "r" (uValue));
2744 uAfter = (uint32_t)u64After;
2745 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT64_C(%#018llx) },\n", uBefore, uAfter, uValue);
2746 break;
2747 }
2748 }
2749
2750 /* next */
2751 uBefore = uAfter;
2752 i++;
2753 }
2754 return 0;
2755}
2756#endif
2757
2758
2759/*
2760 * ADCX/ADOX - ADX
2761 */
2762BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_adcx_adox)(uint8_t bMode)
2763{
2764 typedef struct BS3CPUINSTR2_ADX_VALUES_T
2765 {
2766 uint64_t uDstOut;
2767 uint64_t uDstIn;
2768 uint64_t uSrc;
2769 bool fFlagIn;
2770 bool fFlagOut;
2771 } BS3CPUINSTR2_ADX_VALUES_T;
2772 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues4[] =
2773 {
2774 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000), false, false },
2775 { UINT32_C(0000000001), UINT32_C(0000000000), UINT32_C(0000000000), true, false },
2776
2777 { UINT32_C(0xfffffffe), UINT32_MAX / 2, UINT32_MAX / 2, false, false },
2778 { UINT32_C(0xffffffff), UINT32_MAX / 2, UINT32_MAX / 2, true, false },
2779
2780 { UINT32_C(0x7ffffffe), UINT32_MAX, UINT32_MAX / 2, false, true },
2781 { UINT32_C(0x7fffffff), UINT32_MAX, UINT32_MAX / 2, true, true },
2782
2783 { UINT32_C(0x7ffffffe), UINT32_MAX / 2, UINT32_MAX, false, true },
2784 { UINT32_C(0x7fffffff), UINT32_MAX / 2, UINT32_MAX, true, true },
2785
2786 { UINT32_C(0xfffffffe), UINT32_MAX, UINT32_MAX, false, true },
2787 { UINT32_C(0xffffffff), UINT32_MAX, UINT32_MAX, true, true },
2788 };
2789#if ARCH_BITS >= 64
2790 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues8[] =
2791 {
2792 { UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), false, false },
2793 { UINT64_C(00000000000000000001), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), true, false },
2794
2795 { UINT64_C(0xfffffffffffffffe), UINT64_MAX / 2, UINT64_MAX / 2, false, false },
2796 { UINT64_C(0xffffffffffffffff), UINT64_MAX / 2, UINT64_MAX / 2, true, false },
2797
2798 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX, UINT64_MAX / 2, false, true },
2799 { UINT64_C(0x7fffffffffffffff), UINT64_MAX, UINT64_MAX / 2, true, true },
2800
2801 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX / 2, UINT64_MAX, false, true },
2802 { UINT64_C(0x7fffffffffffffff), UINT64_MAX / 2, UINT64_MAX, true, true },
2803
2804 { UINT64_C(0xfffffffffffffffe), UINT64_MAX, UINT64_MAX, false, true },
2805 { UINT64_C(0xffffffffffffffff), UINT64_MAX, UINT64_MAX, true, true },
2806 };
2807#endif
2808 static const struct
2809 {
2810 FPFNBS3FAR pfnWorker;
2811 bool fMemSrc;
2812 uint8_t cbOp;
2813 uint8_t cValues;
2814 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues;
2815 uint32_t fEFlagsMod;
2816 } s_aTests[] =
2817 {
2818 /* 32-bit register width */
2819 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
2820 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
2821
2822 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
2823 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
2824#if ARCH_BITS >= 64
2825 /* 64-bit register width */
2826 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
2827 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
2828
2829 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
2830 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
2831#endif
2832 };
2833
2834 BS3REGCTX Ctx;
2835 BS3TRAPFRAME TrapFrame;
2836 unsigned i, j;
2837 bool fSupportsAdx = false;
2838
2839 if ( (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2840 && ASMCpuId_EAX(0) >= 7)
2841 {
2842 uint32_t fEbx = 0;
2843 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &fEbx, NULL, NULL);
2844 fSupportsAdx = RT_BOOL(fEbx & X86_CPUID_STEXT_FEATURE_EBX_ADX);
2845 }
2846
2847 /* Ensure the structures are allocated before we sample the stack pointer. */
2848 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2849 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2850
2851 /*
2852 * Create test context.
2853 */
2854 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2855
2856 /*
2857 * Do the tests twice, first with all flags set, then once again with
2858 * flags cleared. The flags are not supposed to be touched at all except for the one indicated (CF or OF).
2859 */
2860 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2861 for (j = 0; j < 2; j++)
2862 {
2863 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2864 {
2865 uint8_t const cbOp = s_aTests[i].cbOp;
2866 unsigned const cValues = s_aTests[i].cValues;
2867 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
2868 uint32_t const fEFlagsMod = s_aTests[i].fEFlagsMod;
2869 unsigned iValue;
2870 bool const fOkay = fSupportsAdx;
2871 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2872 uint64_t const uSrcGarbage = ( cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
2873 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
2874 uint64_t uExpectRip;
2875
2876 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2877 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
2878
2879 for (iValue = 0; iValue < cValues; iValue++)
2880 {
2881 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
2882 uint64_t uMemSrc, uMemSrcExpect;
2883
2884 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
2885 if (!s_aTests[i].fMemSrc)
2886 {
2887 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
2888 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
2889 }
2890 else
2891 {
2892 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
2893 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2894 }
2895
2896 Ctx.rflags.u16 &= ~fEFlagsMod;
2897 if (paValues[iValue].fFlagIn)
2898 Ctx.rflags.u16 |= fEFlagsMod;
2899
2900 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2901
2902 Ctx.rflags.u16 &= ~fEFlagsMod;
2903 if (paValues[iValue].fFlagOut)
2904 Ctx.rflags.u16 |= fEFlagsMod;
2905
2906 if ( TrapFrame.bXcpt != bExpectXcpt
2907 || TrapFrame.Ctx.rip.u != uExpectRip
2908 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2909 || TrapFrame.Ctx.rax.u != uExpectRax
2910 /* check that nothing else really changed: */
2911 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
2912 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2913 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2914 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2915 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2916 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2917 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2918 || uMemSrc != uMemSrcExpect
2919 )
2920 {
2921 Bs3TestFailedF("test #%i value #%i failed: input %#RX64, %#RX64",
2922 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
2923 if (TrapFrame.bXcpt != bExpectXcpt)
2924 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2925 if (TrapFrame.Ctx.rip.u != uExpectRip)
2926 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2927 if (TrapFrame.Ctx.rax.u != uExpectRax)
2928 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2929 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2930 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2931
2932 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
2933 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
2934 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2935 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2936 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2937 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2938 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2939 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2940 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2941 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2942 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2943 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2944 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2945 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2946 if (uMemSrc != uMemSrcExpect)
2947 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2948 }
2949 }
2950 }
2951 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2952 }
2953
2954 return 0;
2955}
2956
2957
2958
2959/*
2960 *
2961 */
2962# if ARCH_BITS == 64
2963
2964BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b)(uint8_t bMode)
2965{
2966 BS3REGCTX Ctx;
2967 BS3REGCTX ExpectCtx;
2968 BS3TRAPFRAME TrapFrame;
2969 RTUINT128U au128[3];
2970 PRTUINT128U pau128 = RT_ALIGN_PT(&au128[0], sizeof(RTUINT128U), PRTUINT128U);
2971 bool const fSupportCX16 = RT_BOOL(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16);
2972 unsigned iFlags;
2973 unsigned offBuf;
2974 unsigned iMatch;
2975 unsigned iWorker;
2976 static struct
2977 {
2978 bool fLocked;
2979 uint8_t offUd2;
2980 FNBS3FAR *pfnWorker;
2981 } const s_aWorkers[] =
2982 {
2983 { false, 4, BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2) },
2984 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2) },
2985 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2) },
2986 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2) },
2987 { true, 1+4, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2) },
2988 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2) },
2989 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2) },
2990 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2) },
2991 };
2992
2993 /* Ensure the structures are allocated before we sample the stack pointer. */
2994 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2995 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
2996 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2997 Bs3MemSet(pau128, 0, sizeof(pau128[0]) * 2);
2998
2999 /*
3000 * Create test context.
3001 */
3002 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3003 if (!fSupportCX16)
3004 Bs3TestPrintf("Note! CMPXCHG16B is not supported by the CPU!\n");
3005
3006 /*
3007 * One loop with the normal variant and one with the locked one
3008 */
3009 g_usBs3TestStep = 0;
3010 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
3011 {
3012 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
3013
3014 /*
3015 * One loop with all status flags set, and one with them clear.
3016 */
3017 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3018 for (iFlags = 0; iFlags < 2; iFlags++)
3019 {
3020 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3021
3022 for (offBuf = 0; offBuf < sizeof(RTUINT128U); offBuf++)
3023 {
3024# define CX16_OLD_LO UINT64_C(0xabb6345dcc9c4bbd)
3025# define CX16_OLD_HI UINT64_C(0x7b06ea35749549ab)
3026# define CX16_MISMATCH_LO UINT64_C(0xbace3e3590f18981)
3027# define CX16_MISMATCH_HI UINT64_C(0x9b385e8bfd5b4000)
3028# define CX16_STORE_LO UINT64_C(0x5cbd27d251f6559b)
3029# define CX16_STORE_HI UINT64_C(0x17ff434ed1b54963)
3030
3031 PRTUINT128U pBuf = (PRTUINT128U)&pau128->au8[offBuf];
3032
3033 ExpectCtx.rax.u = Ctx.rax.u = CX16_MISMATCH_LO;
3034 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_MISMATCH_HI;
3035 for (iMatch = 0; iMatch < 2; iMatch++)
3036 {
3037 uint8_t bExpectXcpt;
3038 pBuf->s.Lo = CX16_OLD_LO;
3039 pBuf->s.Hi = CX16_OLD_HI;
3040 ExpectCtx.rdi.u = Ctx.rdi.u = (uintptr_t)pBuf;
3041 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3042 g_usBs3TestStep++;
3043 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
3044 bExpectXcpt = X86_XCPT_UD;
3045 if (fSupportCX16)
3046 {
3047 if (offBuf & 15)
3048 {
3049 bExpectXcpt = X86_XCPT_GP;
3050 ExpectCtx.rip.u = Ctx.rip.u;
3051 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
3052 }
3053 else
3054 {
3055 ExpectCtx.rax.u = CX16_OLD_LO;
3056 ExpectCtx.rdx.u = CX16_OLD_HI;
3057 if (iMatch & 1)
3058 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
3059 else
3060 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
3061 ExpectCtx.rip.u = Ctx.rip.u + s_aWorkers[iWorker].offUd2;
3062 }
3063 ExpectCtx.rflags.u32 |= X86_EFL_RF;
3064 }
3065 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
3066 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/)
3067 || TrapFrame.bXcpt != bExpectXcpt)
3068 {
3069 if (TrapFrame.bXcpt != bExpectXcpt)
3070 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3071 Bs3TestFailedF("^^^ iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n", iWorker, iFlags, offBuf, iMatch);
3072 ASMHalt();
3073 }
3074
3075 ExpectCtx.rax.u = Ctx.rax.u = CX16_OLD_LO;
3076 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_OLD_HI;
3077 }
3078 }
3079 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3080 }
3081 }
3082
3083 return 0;
3084}
3085
3086
3087static void bs3CpuInstr2_fsgsbase_ExpectUD(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame)
3088{
3089 pCtx->rbx.u = 0;
3090 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
3091 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
3092 pExpectCtx->rip.u = pCtx->rip.u;
3093 pExpectCtx->rflags.u32 |= X86_EFL_RF;
3094 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
3095 0 /*idTestStep*/)
3096 || pTrapFrame->bXcpt != X86_XCPT_UD)
3097 {
3098 Bs3TestFailedF("Expected #UD, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
3099 ASMHalt();
3100 }
3101}
3102
3103
3104static bool bs3CpuInstr2_fsgsbase_VerifyWorker(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame,
3105 BS3CI2FSGSBASE const *pFsGsBaseWorker, unsigned *puIter)
3106{
3107 bool fPassed = true;
3108 unsigned iValue = 0;
3109 static const struct
3110 {
3111 bool fGP;
3112 uint64_t u64Base;
3113 } s_aValues64[] =
3114 {
3115 { false, UINT64_C(0x0000000000000000) },
3116 { false, UINT64_C(0x0000000000000001) },
3117 { false, UINT64_C(0x0000000000000010) },
3118 { false, UINT64_C(0x0000000000000123) },
3119 { false, UINT64_C(0x0000000000001234) },
3120 { false, UINT64_C(0x0000000000012345) },
3121 { false, UINT64_C(0x0000000000123456) },
3122 { false, UINT64_C(0x0000000001234567) },
3123 { false, UINT64_C(0x0000000012345678) },
3124 { false, UINT64_C(0x0000000123456789) },
3125 { false, UINT64_C(0x000000123456789a) },
3126 { false, UINT64_C(0x00000123456789ab) },
3127 { false, UINT64_C(0x0000123456789abc) },
3128 { false, UINT64_C(0x00007ffffeefefef) },
3129 { false, UINT64_C(0x00007fffffffffff) },
3130 { true, UINT64_C(0x0000800000000000) },
3131 { true, UINT64_C(0x0000800000000000) },
3132 { true, UINT64_C(0x0000800000000333) },
3133 { true, UINT64_C(0x0001000000000000) },
3134 { true, UINT64_C(0x0012000000000000) },
3135 { true, UINT64_C(0x0123000000000000) },
3136 { true, UINT64_C(0x1234000000000000) },
3137 { true, UINT64_C(0xffff300000000000) },
3138 { true, UINT64_C(0xffff7fffffffffff) },
3139 { true, UINT64_C(0xffff7fffffffffff) },
3140 { false, UINT64_C(0xffff800000000000) },
3141 { false, UINT64_C(0xffffffffffeefefe) },
3142 { false, UINT64_C(0xffffffffffffffff) },
3143 { false, UINT64_C(0xffffffffffffffff) },
3144 { false, UINT64_C(0x00000000efefefef) },
3145 { false, UINT64_C(0x0000000080204060) },
3146 { false, UINT64_C(0x00000000ddeeffaa) },
3147 { false, UINT64_C(0x00000000fdecdbca) },
3148 { false, UINT64_C(0x000000006098456b) },
3149 { false, UINT64_C(0x0000000098506099) },
3150 { false, UINT64_C(0x00000000206950bc) },
3151 { false, UINT64_C(0x000000009740395d) },
3152 { false, UINT64_C(0x0000000064a9455e) },
3153 { false, UINT64_C(0x00000000d20b6eff) },
3154 { false, UINT64_C(0x0000000085296d46) },
3155 { false, UINT64_C(0x0000000007000039) },
3156 { false, UINT64_C(0x000000000007fe00) },
3157 };
3158
3159 Bs3RegCtxSetRipCsFromCurPtr(pCtx, pFsGsBaseWorker->pfnVerifyWorker);
3160 if (pFsGsBaseWorker->f64BitOperand)
3161 {
3162 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
3163 {
3164 bool const fGP = s_aValues64[iValue].fGP;
3165
3166 pCtx->rbx.u = s_aValues64[iValue].u64Base;
3167 pCtx->rcx.u = 0;
3168 pCtx->cr4.u |= X86_CR4_FSGSBASE;
3169 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
3170 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
3171 pExpectCtx->rip.u = pCtx->rip.u + (!fGP ? pFsGsBaseWorker->offVerifyWorkerUd2 : 0);
3172 pExpectCtx->rbx.u = !fGP ? 0 : s_aValues64[iValue].u64Base;
3173 pExpectCtx->rcx.u = !fGP ? s_aValues64[iValue].u64Base : 0;
3174 pExpectCtx->rflags.u32 |= X86_EFL_RF;
3175 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
3176 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/)
3177 || (fGP && pTrapFrame->bXcpt != X86_XCPT_GP))
3178 {
3179 if (fGP && pTrapFrame->bXcpt != X86_XCPT_GP)
3180 Bs3TestFailedF("Expected #GP, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
3181 else
3182 Bs3TestFailedF("iValue=%u\n", iValue);
3183 fPassed = false;
3184 break;
3185 }
3186 }
3187 }
3188 else
3189 {
3190 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
3191 {
3192 pCtx->rbx.u = s_aValues64[iValue].u64Base;
3193 pCtx->rcx.u = ~s_aValues64[iValue].u64Base;
3194 pCtx->cr4.u |= X86_CR4_FSGSBASE;
3195 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
3196 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
3197 pExpectCtx->rip.u = pCtx->rip.u + pFsGsBaseWorker->offVerifyWorkerUd2;
3198 pExpectCtx->rbx.u = 0;
3199 pExpectCtx->rcx.u = s_aValues64[iValue].u64Base & UINT64_C(0x00000000ffffffff);
3200 pExpectCtx->rflags.u32 |= X86_EFL_RF;
3201 if (!Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
3202 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/))
3203 {
3204 Bs3TestFailedF("iValue=%u\n", iValue);
3205 fPassed = false;
3206 break;
3207 }
3208 }
3209 }
3210
3211 *puIter = iValue;
3212 return fPassed;
3213}
3214
3215
3216static void bs3CpuInstr2_rdfsbase_rdgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
3217 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
3218{
3219 BS3REGCTX Ctx;
3220 BS3REGCTX ExpectCtx;
3221 BS3TRAPFRAME TrapFrame;
3222 unsigned iWorker;
3223 unsigned iIter;
3224 uint32_t uDummy;
3225 uint32_t uStdExtFeatEbx;
3226 bool fSupportsFsGsBase;
3227
3228 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
3229 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
3230
3231 /* Ensure the structures are allocated before we sample the stack pointer. */
3232 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3233 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3234 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3235
3236 /*
3237 * Create test context.
3238 */
3239 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3240
3241 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
3242 {
3243 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
3244 if (fSupportsFsGsBase)
3245 {
3246 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
3247
3248 /* CR4.FSGSBASE disabled -> #UD. */
3249 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
3250 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
3251
3252 /* Read and verify existing base address. */
3253 Ctx.rbx.u = 0;
3254 Ctx.cr4.u |= X86_CR4_FSGSBASE;
3255 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3256 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3257 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
3258 ExpectCtx.rbx.u = uBaseAddr;
3259 ExpectCtx.rflags.u32 |= X86_EFL_RF;
3260 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
3261 0 /*idTestStep*/))
3262 {
3263 ASMHalt();
3264 }
3265
3266 /* Write, read and verify series of base addresses. */
3267 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
3268 {
3269 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
3270 ASMHalt();
3271 }
3272
3273 /* Restore original base address. */
3274 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
3275
3276 /* Clean used GPRs. */
3277 Ctx.rbx.u = 0;
3278 Ctx.rcx.u = 0;
3279 }
3280 else
3281 {
3282 /* Unsupported by CPUID -> #UD. */
3283 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
3284 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
3285 }
3286 }
3287}
3288
3289
3290static void bs3CpuInstr2_wrfsbase_wrgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
3291 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
3292{
3293 BS3REGCTX Ctx;
3294 BS3REGCTX ExpectCtx;
3295 BS3TRAPFRAME TrapFrame;
3296 unsigned iWorker;
3297 unsigned iIter;
3298 uint32_t uDummy;
3299 uint32_t uStdExtFeatEbx;
3300 bool fSupportsFsGsBase;
3301
3302 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
3303 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
3304
3305 /* Ensure the structures are allocated before we sample the stack pointer. */
3306 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3307 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3308 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3309
3310 /*
3311 * Create test context.
3312 */
3313 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3314
3315 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
3316 {
3317 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
3318 if (fSupportsFsGsBase)
3319 {
3320 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
3321
3322 /* CR4.FSGSBASE disabled -> #UD. */
3323 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
3324 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
3325
3326 /* Write a base address. */
3327 Ctx.rbx.u = 0xa0000;
3328 Ctx.cr4.u |= X86_CR4_FSGSBASE;
3329 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3330 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3331 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
3332 ExpectCtx.rflags.u32 |= X86_EFL_RF;
3333 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
3334 0 /*idTestStep*/))
3335 {
3336 ASMHalt();
3337 }
3338
3339 /* Write and read back series of base addresses. */
3340 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
3341 {
3342 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
3343 ASMHalt();
3344 }
3345
3346 /* Restore original base address. */
3347 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
3348
3349 /* Clean used GPRs. */
3350 Ctx.rbx.u = 0;
3351 Ctx.rcx.u = 0;
3352 }
3353 else
3354 {
3355 /* Unsupported by CPUID -> #UD. */
3356 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
3357 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
3358 }
3359 }
3360}
3361
3362
3363BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrfsbase)(uint8_t bMode)
3364{
3365 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrFsBaseWorkers, RT_ELEMENTS(s_aWrFsBaseWorkers), MSR_K8_FS_BASE);
3366 return 0;
3367}
3368
3369
3370BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrgsbase)(uint8_t bMode)
3371{
3372 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrGsBaseWorkers, RT_ELEMENTS(s_aWrGsBaseWorkers), MSR_K8_GS_BASE);
3373 return 0;
3374}
3375
3376
3377BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdfsbase)(uint8_t bMode)
3378{
3379 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdFsBaseWorkers, RT_ELEMENTS(s_aRdFsBaseWorkers), MSR_K8_FS_BASE);
3380 return 0;
3381}
3382
3383
3384BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdgsbase)(uint8_t bMode)
3385{
3386 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdGsBaseWorkers, RT_ELEMENTS(s_aRdGsBaseWorkers), MSR_K8_GS_BASE);
3387 return 0;
3388}
3389
3390# endif /* ARCH_BITS == 64 */
3391
3392#endif /* BS3_INSTANTIATING_CMN */
3393
3394
3395
3396/*
3397 * Mode specific code.
3398 * Mode specific code.
3399 * Mode specific code.
3400 */
3401#ifdef BS3_INSTANTIATING_MODE
3402
3403
3404#endif /* BS3_INSTANTIATING_MODE */
3405
Note: See TracBrowser for help on using the repository browser.

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