VirtualBox

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

最後變更 在這個檔案從103208是 103208,由 vboxsync 提交於 14 月 前

ValidationKit/bootsectors/bs3-cpu-instr-2: A basic compxchg8b testcase, bugref:9898

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

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