VirtualBox

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

Last change on this file since 95357 was 95357, checked in by vboxsync, 2 years ago

ValKit/bs3-cpu-instr-2: Added simple POPCNT test. bugref:9898

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