VirtualBox

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

Last change on this file since 98326 was 98103, checked in by vboxsync, 20 months ago

Copyright year updates by scm.

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

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