VirtualBox

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

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

ValKit/bs3-cpu-instr-2: Simple crc32 instruction test. bugref:9898

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