VirtualBox

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

Last change on this file since 103795 was 103738, checked in by vboxsync, 14 months ago

ValKit/bs3-cpu-instr-2: Cover binary operations with immediates. bugref:10376

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 225.1 KB
Line 
1/* $Id: bs3-cpu-instr-2-template.c 103738 2024-03-08 15:49:39Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-instr-2, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/asm.h>
42#include <iprt/asm-amd64-x86.h>
43#include "bs3-cpu-instr-2.h"
44#include "bs3-cpu-instr-2-data.h"
45#include "bs3-cpu-instr-2-asm-auto.h"
46
47
48/*********************************************************************************************************************************
49* Structures and Typedefs *
50*********************************************************************************************************************************/
51#ifdef BS3_INSTANTIATING_CMN
52# if ARCH_BITS == 64
53typedef struct BS3CI2FSGSBASE
54{
55 const char *pszDesc;
56 bool f64BitOperand;
57 FPFNBS3FAR pfnWorker;
58 uint8_t offWorkerUd2;
59 FPFNBS3FAR pfnVerifyWorker;
60 uint8_t offVerifyWorkerUd2;
61} BS3CI2FSGSBASE;
62# endif
63#endif
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69#ifdef BS3_INSTANTIATING_CMN
70# if ARCH_BITS == 64
71static BS3CI2FSGSBASE const s_aWrFsBaseWorkers[] =
72{
73 { "wrfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
74 { "wrfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
75};
76
77static BS3CI2FSGSBASE const s_aWrGsBaseWorkers[] =
78{
79 { "wrgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
80 { "wrgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
81};
82
83static BS3CI2FSGSBASE const s_aRdFsBaseWorkers[] =
84{
85 { "rdfsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_rbx_rdfsbase_rcx_ud2), 15 },
86 { "rdfsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdfsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrfsbase_ebx_rdfsbase_ecx_ud2), 13 },
87};
88
89static BS3CI2FSGSBASE const s_aRdGsBaseWorkers[] =
90{
91 { "rdgsbase rbx", true, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_rbx_ud2), 5, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_rbx_rdgsbase_rcx_ud2), 15 },
92 { "rdgsbase ebx", false, BS3_CMN_NM(bs3CpuInstr2_rdgsbase_ebx_ud2), 4, BS3_CMN_NM(bs3CpuInstr2_wrgsbase_ebx_rdgsbase_ecx_ud2), 13 },
93};
94# endif
95#endif /* BS3_INSTANTIATING_CMN - global */
96
97
98/*
99 * Common code.
100 * Common code.
101 * Common code.
102 */
103#ifdef BS3_INSTANTIATING_CMN
104
105/*
106 * Basic binary arithmetic tests.
107 */
108
109# if ARCH_BITS == 64 /* fDstMem cBitsImm */
110# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(a_Ins) \
111 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _sil_dil), X86_GREG_xSI, X86_GREG_xDI, false, false, 0 }, \
112 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9b_r8b), X86_GREG_x9, X86_GREG_x8, false, false, 0 }, \
113 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_r13b), X86_GREG_xAX, X86_GREG_x13, false, false, 0 }, \
114 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx14_r11b), X86_GREG_x14, X86_GREG_x11, true, false, 0 },
115# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8_64BIT(a_Ins) \
116 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8b_Ib), X86_GREG_x8, X86_GREG_x15, false, false, 8 }, \
117 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r14b_Ib), X86_GREG_x14, X86_GREG_x15, false, false, 8 }, \
118 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx13_Ib), X86_GREG_x13, X86_GREG_x15, true, false, 8 },
119# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(a_Ins) \
120 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dl_r14b), X86_GREG_xDX, X86_GREG_x14, false, false, 0 }, \
121 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r8b_bl), X86_GREG_x8, X86_GREG_xBX, false, false, 0 }, \
122 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r11b_DSx12), X86_GREG_x11, X86_GREG_x12, false, true, 0 },
123# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(a_Ins) \
124 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8w_cx), X86_GREG_x8, X86_GREG_xCX, false, false, 0 }, \
125 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r15w_r10w), X86_GREG_x15, X86_GREG_x10, false, false, 0 }, \
126 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx15_r12w), X86_GREG_x15, X86_GREG_x12, true, false, 0 },
127# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B_64BIT(a_Ins) \
128 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8w_Ib), X86_GREG_x8, X86_GREG_xBX, false, false, 8 }, \
129 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r12w_Ib), X86_GREG_x12, X86_GREG_xBX, false, false, 8 }, \
130 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _wDSx14_Ib), X86_GREG_x14, X86_GREG_xBX, true, false, 8 },
131# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W_64BIT(a_Ins) \
132 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8w_Iw), X86_GREG_x8, X86_GREG_xBX, false, false, 16 }, \
133 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r13w_Iw), X86_GREG_x13, X86_GREG_xBX, false, false, 16 }, \
134 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx11_Iw), X86_GREG_x11, X86_GREG_xBX, true, false, 16 },
135# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(a_Ins) \
136 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r13w_ax), X86_GREG_x13, X86_GREG_xAX, false, false, 0 }, \
137 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _si_r9w), X86_GREG_xSI, X86_GREG_x9, false, false, 0 }, \
138 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9w_DSx8), X86_GREG_x9, X86_GREG_x8, false, true, 0 },
139# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins) \
140 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_r8d), X86_GREG_xAX, X86_GREG_x8, false, false, 0 }, \
141 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r9d_ecx), X86_GREG_x9, X86_GREG_xCX, false, false, 0 }, \
142 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r13d_r14d), X86_GREG_x13, X86_GREG_x14, false, false, 0 }, \
143 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx10_r11d), X86_GREG_x10, X86_GREG_x11, true, false, 0 },
144# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B_64BIT(a_Ins) \
145 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8d_Ib), X86_GREG_x8, X86_GREG_xBX, false, false, 8 }, \
146 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r11d_Ib), X86_GREG_x11, X86_GREG_xBX, false, false, 8 }, \
147 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dwDSx15_Ib), X86_GREG_x15, X86_GREG_xBX, true, false, 8 },
148# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW_64BIT(a_Ins) \
149 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8d_Id), X86_GREG_x8, X86_GREG_xBX, false, false, 32 }, \
150 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r14d_Id), X86_GREG_x14, X86_GREG_xBX, false, false, 32 }, \
151 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx12_Id), X86_GREG_x12, X86_GREG_xBX, true, false, 32 },
152# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32_64BIT(a_Ins) \
153 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15d_esi), X86_GREG_x15, X86_GREG_xSI, false, false, 0 }, \
154 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _eax_r10d), X86_GREG_xAX, X86_GREG_x10, false, false, 0 }, \
155 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r14d_DSx12), X86_GREG_x14, X86_GREG_x12, false, true, 0 },
156
157# define BS3CPUINSTR2CMNBINTEST_ENTRIES_64(a_Ins) \
158 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_rbx), X86_GREG_xAX, X86_GREG_xBX, false, false, 0 }, \
159 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_rax), X86_GREG_x8, X86_GREG_xAX, false, false, 0 }, \
160 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rdx_r10), X86_GREG_xDX, X86_GREG_x10, false, false, 0 }, \
161 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxBX_rax), X86_GREG_xBX, X86_GREG_xAX, true, false, 0 }, \
162 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSx12_r8), X86_GREG_x12, X86_GREG_x8, true, false, 0 },
163# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(a_Ins) \
164 BS3CPUINSTR2CMNBINTEST_ENTRIES_64(a_Ins) \
165 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _r15_rsi), X86_GREG_x15, X86_GREG_xSI, false, false, 0 }, \
166 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _rbx_r14), X86_GREG_xBX, X86_GREG_x14, false, false, 0 }, \
167 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_DSxBX), X86_GREG_xAX, X86_GREG_xBX, false, true, 0 }, \
168 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_DSx12), X86_GREG_x8, X86_GREG_x12, false, true, 0 },
169
170# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(a_Ins) \
171 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_Ib), X86_GREG_xAX, X86_GREG_x15, false, false, 8 }, \
172 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rbp_Ib), X86_GREG_xBP, X86_GREG_x15, false, false, 8 }, \
173 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_Ib), X86_GREG_x8, X86_GREG_x15, false, false, 8 }, \
174 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r11_Ib), X86_GREG_x11, X86_GREG_x15, false, false, 8 }, \
175 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _qwDSxSI_Ib), X86_GREG_xSI, X86_GREG_x15, true, false, 8 }, \
176 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _qwDSx8_Ib), X86_GREG_x8, X86_GREG_x15, true, false, 8 },
177
178# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(a_Ins) \
179 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rax_Id), X86_GREG_xAX, X86_GREG_x15, false, false, 32 }, \
180 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r8_Id), X86_GREG_x8, X86_GREG_x15, false, false, 32 }, \
181 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _rbx_Id), X86_GREG_xBX, X86_GREG_x15, false, false, 32 }, \
182 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _r14_Id), X86_GREG_x14, X86_GREG_x15, false, false, 32 }, \
183 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _qwDSx12_Id), X86_GREG_x12, X86_GREG_x15, true, false, 32 },
184
185# else
186# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(aIns)
187# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(aIns)
188# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(aIns)
189# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8_64BIT(aIns)
190# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B_64BIT(aIns)
191# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W_64BIT(aIns)
192# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B_64BIT(aIns)
193# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW_64BIT(aIns)
194# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(aIns)
195# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(aIns)
196# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32_64BIT(aIns)
197# endif
198
199# define BS3CPUINSTR2CMNBINTEST_ENTRIES_8(a_Ins) \
200 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_dl), X86_GREG_xAX, X86_GREG_xDX, false, false, 0 }, \
201 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ch_bh), X86_GREG_xCX+16, X86_GREG_xBX+16, false, false, 0 }, \
202 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dl_ah), X86_GREG_xDX, X86_GREG_xAX+16, false, false, 0 }, \
203 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxBX_ah), X86_GREG_xBX, X86_GREG_xAX+16, true, false, 0 }, \
204 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxDI_bl), X86_GREG_xDI, X86_GREG_xBX, true, false, 0 }, \
205 BS3CPUINSTR2CMNBINTEST_ENTRIES_8_64BIT(a_Ins)
206# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(a_Ins) \
207 BS3CPUINSTR2CMNBINTEST_ENTRIES_8(a_Ins) \
208 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _dh_cl), X86_GREG_xDX+16, X86_GREG_xCX, false, false, 0 }, \
209 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dl_DSxBX), X86_GREG_xDX, X86_GREG_xBX, false, true, 0 }, \
210 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ch_DSxBX), X86_GREG_xCX+16, X86_GREG_xBX, false, true, 0 }, \
211 BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8_64BIT(a_Ins)
212
213# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(a_Ins) \
214 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _al_Ib), X86_GREG_xAX, X86_GREG_x15, false, false, 8 }, \
215 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _cl_Ib), X86_GREG_xCX, X86_GREG_x15, false, false, 8 }, \
216 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dh_Ib), X86_GREG_xDX+16, X86_GREG_x15, false, false, 8 }, \
217 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxDI_Ib), X86_GREG_xDI, X86_GREG_x15, true, false, 8 }, \
218 BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8_64BIT(a_Ins)
219
220# define BS3CPUINSTR2CMNBINTEST_ENTRIES_16(a_Ins) \
221 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _di_si), X86_GREG_xDI, X86_GREG_xSI, false, false, 0 }, \
222 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _cx_bp), X86_GREG_xCX, X86_GREG_xBP, false, false, 0 }, \
223 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxDI_si), X86_GREG_xDI, X86_GREG_xSI, true, false, 0 }, \
224 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxBX_ax), X86_GREG_xBX, X86_GREG_xAX, true, false, 0 }, \
225 BS3CPUINSTR2CMNBINTEST_ENTRIES_16_64BIT(a_Ins)
226# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(a_Ins) \
227 BS3CPUINSTR2CMNBINTEST_ENTRIES_16(a_Ins) \
228 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _bp_bx), X86_GREG_xBP, X86_GREG_xBX, false, false, 0 }, \
229 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _si_DSxDI), X86_GREG_xSI, X86_GREG_xDI, false, true, 0 }, \
230 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ax_DSxBX), X86_GREG_xAX, X86_GREG_xBX, false, true, 0 }, \
231 BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16_64BIT(a_Ins)
232
233# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(a_Ins) \
234 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ax_Ib), X86_GREG_xAX, X86_GREG_x15, false, false, 8 }, \
235 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _si_Ib), X86_GREG_xSI, X86_GREG_x15, false, false, 8 }, \
236 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _wDSxDI_Ib), X86_GREG_xDI, X86_GREG_x15, true, false, 8 }, \
237 BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B_64BIT(a_Ins)
238
239# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(a_Ins) \
240 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ax_Iw), X86_GREG_xAX, X86_GREG_x15, false, false, 16 }, \
241 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _bx_Iw), X86_GREG_xBX, X86_GREG_x15, false, false, 16 }, \
242 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxBX_Iw), X86_GREG_xBX, X86_GREG_x15, true, false, 16 }, \
243 BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W_64BIT(a_Ins)
244
245
246# define BS3CPUINSTR2CMNBINTEST_ENTRIES_32(a_Ins) \
247 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_ebx), X86_GREG_xAX, X86_GREG_xBX, false, false, 0 }, \
248 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ecx_ebp), X86_GREG_xCX, X86_GREG_xBP, false, false, 0 }, \
249 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _edx_edi), X86_GREG_xDX, X86_GREG_xDI, false, false, 0 }, \
250 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxDI_esi), X86_GREG_xDI, X86_GREG_xSI, true, false, 0 }, \
251 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxBX_eax), X86_GREG_xBX, X86_GREG_xAX, true, false, 0 }, \
252 BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins)
253# define BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(a_Ins) \
254 BS3CPUINSTR2CMNBINTEST_ENTRIES_32(a_Ins) \
255 { BS3_CMN_NM(bs3CpuInstr2_alt_ ## a_Ins ## _edi_esi), X86_GREG_xDI, X86_GREG_xSI, false, false, 0 }, \
256 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_DSxBX), X86_GREG_xAX, X86_GREG_xBX, false, true, 0 }, \
257 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ebp_DSxDI), X86_GREG_xBP, X86_GREG_xDI, false, true, 0 }, \
258 BS3CPUINSTR2CMNBINTEST_ENTRIES_32_64BIT(a_Ins)
259
260# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(a_Ins) \
261 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_Ib), X86_GREG_xAX, X86_GREG_x15, false, false, 8 }, \
262 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ecx_Ib), X86_GREG_xCX, X86_GREG_x15, false, false, 8 }, \
263 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _dwDSxDI_Ib), X86_GREG_xDI, X86_GREG_x15, true, false, 8 }, \
264 BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B_64BIT(a_Ins)
265
266# define BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(a_Ins) \
267 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _eax_Id), X86_GREG_xAX, X86_GREG_x15, false, false, 32 }, \
268 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _ebp_Id), X86_GREG_xBP, X86_GREG_x15, false, false, 32 }, \
269 { BS3_CMN_NM(bs3CpuInstr2_ ## a_Ins ## _DSxSI_Id), X86_GREG_xSI, X86_GREG_x15, true, false, 32 }, \
270 BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW_64BIT(a_Ins)
271
272
273typedef struct BS3CPUINSTR2CMNBINTEST
274{
275 FPFNBS3FAR pfnWorker;
276 uint8_t idxDstReg;
277 uint8_t idxSrcReg;
278 bool fDstMem : 1;
279 bool fSrcMem : 1;
280 uint8_t cBitsImm;
281} BS3CPUINSTR2CMNBINTEST;
282typedef BS3CPUINSTR2CMNBINTEST const BS3_FAR_DATA *PCBS3CPUINSTR2CMNBINTEST;
283
284
285static uint16_t const g_auEflStatusBitsVars[] =
286{
287 0,
288 X86_EFL_STATUS_BITS,
289 X86_EFL_CF,
290 X86_EFL_PF,
291 X86_EFL_AF,
292 X86_EFL_ZF,
293 X86_EFL_SF,
294 X86_EFL_OF,
295 X86_EFL_PF | X86_EFL_AF,
296};
297
298
299DECLINLINE(void RT_FAR *) Code2RwPtr(void RT_FAR *pfn)
300{
301#if ARCH_BITS == 16
302 if (!BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode))
303 pfn = BS3_FP_MAKE(BS3_SEL_TILED + 8, BS3_FP_OFF(pfn)); /* ASSUMES CS */
304#endif
305 return pfn;
306}
307
308#define BS3CPUINSTR2_COMMON_BINARY_U(a_cBits, a_UIntType, a_UIntImmType, a_szFmt) \
309static uint8_t \
310RT_CONCAT(bs3CpuInstr2_CommonBinaryU,a_cBits)(uint8_t bMode, PCBS3CPUINSTR2CMNBINTEST paTests, unsigned cTests, uint16_t fPassthruEfl, \
311 RT_CONCAT(PCBS3CPUINSTR2BIN,a_cBits) paTestData, unsigned cTestData, bool fCarryIn, \
312 bool fMaskSrcWhenMemDst, bool fReadOnly) \
313{ \
314 BS3REGCTX Ctx; \
315 BS3REGCTX CtxExpect; \
316 BS3TRAPFRAME TrapFrame; \
317 unsigned iTest; \
318 struct \
319 { \
320 char achPreGuard[8]; \
321 a_UIntType uData; \
322 char achPostGuard[8]; \
323 } Buf = { { '0','1','2','3','4','5','6','7' }, 0, { '8','9','a','b','c','d','e','f'} }; \
324 a_UIntType uMemExpect = 0; \
325 a_UIntType uMemDummy = 0; \
326 \
327 /* Ensure the structures are allocated before we sample the stack pointer. */ \
328 Bs3MemSet(&Ctx, 0, sizeof(Ctx)); \
329 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame)); \
330 \
331 /* \
332 * Create test context. \
333 */ \
334 Bs3RegCtxSaveEx(&Ctx, bMode, 640); \
335 Ctx.rflags.u32 &= ~X86_EFL_RF; \
336 if (ARCH_BITS == 64) \
337 for (iTest = 0; iTest < 16; iTest++) \
338 if (iTest != X86_GREG_xSP) \
339 (&Ctx.rax)[iTest].au32[1] = UINT32_C(0x8572ade) << (iTest & 7); \
340 Bs3MemCpy(&CtxExpect, &Ctx, sizeof(CtxExpect)); \
341 if (!BS3_MODE_IS_16BIT_SYS(bMode)) \
342 CtxExpect.rflags.u32 |= X86_EFL_RF; \
343 \
344 /* \
345 * Each test worker. \
346 */ \
347 for (iTest = 0; iTest < cTests; iTest++) \
348 { \
349 uint8_t const cbInstr = ((uint8_t BS3_FAR *)paTests[iTest].pfnWorker)[-1]; /* the function is prefixed by the length */ \
350 uint8_t RT_FAR * const pbImm = (uint8_t BS3_FAR *)Code2RwPtr(&((uint8_t BS3_FAR *)paTests[iTest].pfnWorker)[cbInstr - 1]); \
351 a_UIntImmType RT_FAR * const puImm = (a_UIntImmType RT_FAR *)Code2RwPtr(&((uint8_t BS3_FAR *)paTests[iTest].pfnWorker)[cbInstr - sizeof(a_UIntImmType)]); \
352 unsigned const idxDstReg = paTests[iTest].idxDstReg; \
353 unsigned const idxSrcReg = paTests[iTest].idxSrcReg; \
354 uint16_t const SavedDs = Ctx.ds; \
355 BS3REG const SavedDst = (&Ctx.rax)[idxDstReg & 15]; /* saves memptr too */ \
356 BS3REG const SavedSrc = (&Ctx.rax)[idxSrcReg & 15]; /* ditto */ \
357 a_UIntType RT_FAR * const puCtxDst = paTests[iTest].fDstMem ? &Buf.uData \
358 : &(&Ctx.rax)[idxDstReg & 15].RT_CONCAT(au,a_cBits)[idxDstReg >> 4]; \
359 a_UIntType RT_FAR * const puCtxSrc = paTests[iTest].fSrcMem ? &Buf.uData \
360 : paTests[iTest].cBitsImm == 0 \
361 ? &(&Ctx.rax)[idxSrcReg & 15].RT_CONCAT(au,a_cBits)[idxSrcReg >> 4] \
362 : &uMemDummy; \
363 a_UIntType RT_FAR * const puCtxExpectDst = paTests[iTest].fDstMem ? &uMemExpect \
364 : &(&CtxExpect.rax)[idxDstReg & 15].RT_CONCAT(au,a_cBits)[idxDstReg >> 4]; \
365 a_UIntType RT_FAR * const puCtxExpectSrc = paTests[iTest].fSrcMem ? &uMemExpect \
366 : paTests[iTest].cBitsImm == 0 \
367 ? &(&CtxExpect.rax)[idxSrcReg & 15].RT_CONCAT(au,a_cBits)[idxSrcReg >> 4] \
368 : &uMemDummy; \
369 uint64_t RT_FAR * const puMemPtrReg = paTests[iTest].fDstMem ? &(&Ctx.rax)[idxDstReg & 15].u \
370 : paTests[iTest].fSrcMem ? &(&Ctx.rax)[idxSrcReg & 15].u : NULL; \
371 uint64_t RT_FAR * const puMemPtrRegExpt= paTests[iTest].fDstMem ? &(&CtxExpect.rax)[idxDstReg & 15].u \
372 : paTests[iTest].fSrcMem ? &(&CtxExpect.rax)[idxSrcReg & 15].u : NULL; \
373 unsigned iTestData; \
374 /*Bs3TestPrintf("pfnWorker=%p\n", paTests[iTest].pfnWorker);*/ \
375 \
376 Bs3RegCtxSetRipCsFromLnkPtr(&Ctx, paTests[iTest].pfnWorker); \
377 CtxExpect.rip.u = Ctx.rip.u + cbInstr; \
378 CtxExpect.cs = Ctx.cs; \
379 \
380 if (puMemPtrReg) \
381 CtxExpect.ds = Ctx.ds = Ctx.ss; \
382 \
383 /* \
384 * Loop over the test data and feed it to the worker. \
385 */\
386 for (iTestData = 5; iTestData < cTestData; iTestData++) \
387 { \
388 unsigned iRecompiler; \
389 a_UIntType const uSrc = !fMaskSrcWhenMemDst | !paTests[iTest].fDstMem \
390 ? paTestData[iTestData].uSrc2 : paTestData[iTestData].uSrc2 & (a_cBits - 1); \
391 if (!paTests[iTest].cBitsImm) \
392 { \
393 *puCtxSrc = uSrc; \
394 *puCtxExpectSrc = uSrc; \
395 } \
396 else if (paTests[iTest].cBitsImm == 8) \
397 { \
398 if ((int8_t)uSrc == (int##a_cBits##_t)uSrc) \
399 *pbImm = (uint8_t)uSrc; \
400 else continue; \
401 } \
402 else if (sizeof(*puImm) == sizeof(*puCtxSrc) || (int32_t)uSrc == (int64_t)uSrc) \
403 *puImm = (a_UIntImmType)uSrc; \
404 else continue; \
405 \
406 *puCtxDst = paTestData[iTestData].uSrc1; \
407 *puCtxExpectDst = paTestData[iTestData].uResult; \
408 if (a_cBits == 32 && !fReadOnly && !paTests[iTest].fDstMem) \
409 puCtxExpectDst[1] = 0; \
410 \
411 if (puMemPtrReg) \
412 { \
413 *puMemPtrReg = BS3_FP_OFF(&Buf.uData); \
414 *puMemPtrRegExpt = BS3_FP_OFF(&Buf.uData); \
415 } \
416 \
417 CtxExpect.rflags.u16 &= ~X86_EFL_STATUS_BITS; \
418 CtxExpect.rflags.u16 |= paTestData[iTestData].fEflOut & X86_EFL_STATUS_BITS; \
419 \
420 /* \
421 * Do input the eight EFLAGS variations three times, so we're sure to trigger \
422 * native recompilation of the test worker code. \
423 */ \
424 for (iRecompiler = 0; iRecompiler < 2; iRecompiler++) \
425 { \
426 unsigned iEflVar = 0; \
427 for (iEflVar = 0; iEflVar < RT_ELEMENTS(g_auEflStatusBitsVars); iEflVar++) \
428 { \
429 if (paTests[iTest].fDstMem) \
430 *puCtxDst = paTestData[iTestData].uSrc1; \
431 \
432 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS; \
433 if (!fCarryIn) \
434 Ctx.rflags.u16 |= g_auEflStatusBitsVars[iEflVar]; \
435 else \
436 Ctx.rflags.u16 |= (g_auEflStatusBitsVars[iEflVar] & ~X86_EFL_CF) \
437 | (paTestData[iTestData].fEflOut >> BS3CPUINSTR2BIN_EFL_CARRY_IN_BIT) & X86_EFL_CF; \
438 if (fPassthruEfl) \
439 CtxExpect.rflags.u16 = (CtxExpect.rflags.u16 & ~fPassthruEfl) | (Ctx.rflags.u16 & fPassthruEfl); \
440 \
441 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame); \
442 if (TrapFrame.bXcpt != X86_XCPT_UD) \
443 { \
444 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt); \
445 Bs3TrapPrintFrame(&TrapFrame); \
446 } \
447 else if (Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &CtxExpect, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, \
448 0 /*fExtraEfl*/, "mode", (iTest << 8) | (iTestData & 0xff))) \
449 { \
450 if (!puMemPtrReg) \
451 continue; \
452 if (paTests[iTest].fDstMem && Buf.uData != uMemExpect) \
453 Bs3TestPrintf("Wrong memory result: %" a_szFmt ", expected %" a_szFmt "\n", Buf.uData, uMemExpect); \
454 else if (!paTests[iTest].fDstMem && Buf.uData != uSrc) \
455 Bs3TestPrintf("Memory input result modified: %" a_szFmt ", expected %" a_szFmt "\n", Buf.uData, uSrc); \
456 else \
457 continue; \
458 } \
459 /*else { Bs3RegCtxPrint(&Ctx); Bs3TrapPrintFrame(&TrapFrame); }*/ \
460 Bs3TestPrintf(#a_cBits ": iTest=%u iData=%u: uSrc1=%" a_szFmt "%s uSrc2=%" a_szFmt "%s %s-> %" a_szFmt "\n", \
461 iTest, iTestData, paTestData[iTestData].uSrc1, paTests[iTest].fDstMem ? " mem" : "", \
462 paTestData[iTestData].uSrc2, paTests[iTest].fSrcMem ? " mem" : "", \
463 !fCarryIn ? "" : Ctx.rflags.u16 & X86_EFL_CF ? "CF " : "NC ", \
464 paTestData[iTestData].uResult); \
465 Bs3RegCtxPrint(&Ctx); Bs3TrapPrintFrame(&TrapFrame); \
466 ASMHalt(); \
467 iRecompiler = ~0U - 1; \
468 break; \
469 } \
470 } \
471 } \
472 \
473 /* Restore modified context registers (except EFLAGS). */ \
474 CtxExpect.ds = Ctx.ds = SavedDs; \
475 (&CtxExpect.rax)[idxDstReg & 15].u = (&Ctx.rax)[idxDstReg & 15].u = SavedDst.u; \
476 (&CtxExpect.rax)[idxSrcReg & 15].u = (&Ctx.rax)[idxSrcReg & 15].u = SavedSrc.u; \
477 } \
478 \
479 return 0; \
480}
481
482BS3CPUINSTR2_COMMON_BINARY_U(8, uint8_t, uint8_t, "RX8")
483BS3CPUINSTR2_COMMON_BINARY_U(16, uint16_t, uint16_t, "RX16")
484BS3CPUINSTR2_COMMON_BINARY_U(32, uint32_t, uint32_t, "RX32")
485#if ARCH_BITS == 64
486BS3CPUINSTR2_COMMON_BINARY_U(64, uint64_t, uint32_t, "RX64")
487#endif
488
489
490BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_and)(uint8_t bMode)
491{
492 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(and) };
493 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(and) };
494 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(and) };
495#if ARCH_BITS == 64
496 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(and) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(and) };
497#endif
498 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
499 g_aBs3CpuInstr2_and_TestDataU8, g_cBs3CpuInstr2_and_TestDataU8,
500 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
501 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
502 g_aBs3CpuInstr2_and_TestDataU16, g_cBs3CpuInstr2_and_TestDataU16,
503 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
504 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
505 g_aBs3CpuInstr2_and_TestDataU32, g_cBs3CpuInstr2_and_TestDataU32,
506 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
507#if ARCH_BITS == 64
508 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
509 g_aBs3CpuInstr2_and_TestDataU64, g_cBs3CpuInstr2_and_TestDataU64,
510 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
511#endif
512 return 0;
513}
514
515
516BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_or)(uint8_t bMode)
517{
518 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(or) };
519 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(or) };
520 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(or) };
521#if ARCH_BITS == 64
522 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(or) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(or) };
523#endif
524 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
525 g_aBs3CpuInstr2_or_TestDataU8, g_cBs3CpuInstr2_or_TestDataU8,
526 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
527 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
528 g_aBs3CpuInstr2_or_TestDataU16, g_cBs3CpuInstr2_or_TestDataU16,
529 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
530 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
531 g_aBs3CpuInstr2_or_TestDataU32, g_cBs3CpuInstr2_or_TestDataU32,
532 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
533#if ARCH_BITS == 64
534 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
535 g_aBs3CpuInstr2_or_TestDataU64, g_cBs3CpuInstr2_or_TestDataU64,
536 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
537#endif
538 return 0;
539}
540
541
542BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_xor)(uint8_t bMode)
543{
544 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(xor) };
545 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(xor) };
546 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(xor) };
547#if ARCH_BITS == 64
548 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(xor) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(xor) };
549#endif
550 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
551 g_aBs3CpuInstr2_xor_TestDataU8, g_cBs3CpuInstr2_xor_TestDataU8,
552 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
553 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
554 g_aBs3CpuInstr2_xor_TestDataU16, g_cBs3CpuInstr2_xor_TestDataU16,
555 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
556 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
557 g_aBs3CpuInstr2_xor_TestDataU32, g_cBs3CpuInstr2_xor_TestDataU32,
558 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
559#if ARCH_BITS == 64
560 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
561 g_aBs3CpuInstr2_xor_TestDataU64, g_cBs3CpuInstr2_xor_TestDataU64,
562 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
563#endif
564 return 0;
565}
566
567
568BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_test)(uint8_t bMode)
569{
570 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_8(test) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(test) };
571 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(test) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(test) };
572 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(test) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(test) };
573#if ARCH_BITS == 64
574 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(test) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(test) };
575#endif
576 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
577 g_aBs3CpuInstr2_test_TestDataU8, g_cBs3CpuInstr2_test_TestDataU8,
578 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
579 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
580 g_aBs3CpuInstr2_test_TestDataU16, g_cBs3CpuInstr2_test_TestDataU16,
581 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
582 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
583 g_aBs3CpuInstr2_test_TestDataU32, g_cBs3CpuInstr2_test_TestDataU32,
584 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
585#if ARCH_BITS == 64
586 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
587 g_aBs3CpuInstr2_test_TestDataU64, g_cBs3CpuInstr2_test_TestDataU64,
588 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
589#endif
590 return 0;
591}
592
593
594BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_add)(uint8_t bMode)
595{
596 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(add) };
597 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(add) };
598 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(add) };
599#if ARCH_BITS == 64
600 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(add) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(add) };
601#endif
602 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
603 g_aBs3CpuInstr2_add_TestDataU8, g_cBs3CpuInstr2_add_TestDataU8,
604 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
605 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
606 g_aBs3CpuInstr2_add_TestDataU16, g_cBs3CpuInstr2_add_TestDataU16,
607 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
608 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
609 g_aBs3CpuInstr2_add_TestDataU32, g_cBs3CpuInstr2_add_TestDataU32,
610 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
611#if ARCH_BITS == 64
612 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
613 g_aBs3CpuInstr2_add_TestDataU64, g_cBs3CpuInstr2_add_TestDataU64,
614 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
615#endif
616 return 0;
617}
618
619
620BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_adc)(uint8_t bMode)
621{
622 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(adc) };
623 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(adc) };
624 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(adc) };
625#if ARCH_BITS == 64
626 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(adc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(adc) };
627#endif
628 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
629 g_aBs3CpuInstr2_adc_TestDataU8, g_cBs3CpuInstr2_adc_TestDataU8,
630 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
631 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
632 g_aBs3CpuInstr2_adc_TestDataU16, g_cBs3CpuInstr2_adc_TestDataU16,
633 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
634 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
635 g_aBs3CpuInstr2_adc_TestDataU32, g_cBs3CpuInstr2_adc_TestDataU32,
636 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
637#if ARCH_BITS == 64
638 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
639 g_aBs3CpuInstr2_adc_TestDataU64, g_cBs3CpuInstr2_adc_TestDataU64,
640 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
641#endif
642 return 0;
643}
644
645
646BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sub)(uint8_t bMode)
647{
648 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(sub) };
649 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(sub) };
650 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(sub) };
651#if ARCH_BITS == 64
652 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(sub) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(sub) };
653#endif
654 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
655 g_aBs3CpuInstr2_sub_TestDataU8, g_cBs3CpuInstr2_sub_TestDataU8,
656 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
657 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
658 g_aBs3CpuInstr2_sub_TestDataU16, g_cBs3CpuInstr2_sub_TestDataU16,
659 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
660 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
661 g_aBs3CpuInstr2_sub_TestDataU32, g_cBs3CpuInstr2_sub_TestDataU32,
662 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
663#if ARCH_BITS == 64
664 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
665 g_aBs3CpuInstr2_sub_TestDataU64, g_cBs3CpuInstr2_sub_TestDataU64,
666 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
667#endif
668 return 0;
669}
670
671
672BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sbb)(uint8_t bMode)
673{
674 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(sbb) };
675 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(sbb) };
676 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(sbb) };
677#if ARCH_BITS == 64
678 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(sbb) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(sbb) };
679#endif
680 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
681 g_aBs3CpuInstr2_sbb_TestDataU8, g_cBs3CpuInstr2_sbb_TestDataU8,
682 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
683 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
684 g_aBs3CpuInstr2_sbb_TestDataU16, g_cBs3CpuInstr2_sbb_TestDataU16,
685 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
686 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
687 g_aBs3CpuInstr2_sbb_TestDataU32, g_cBs3CpuInstr2_sbb_TestDataU32,
688 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
689#if ARCH_BITS == 64
690 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
691 g_aBs3CpuInstr2_sbb_TestDataU64, g_cBs3CpuInstr2_sbb_TestDataU64,
692 true /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
693#endif
694 return 0;
695}
696
697
698BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmp)(uint8_t bMode)
699{
700 static const BS3CPUINSTR2CMNBINTEST s_aTests8[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_8(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_8(cmp) };
701 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_16(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16W(cmp) };
702 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_32(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32DW(cmp) };
703#if ARCH_BITS == 64
704 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_ALT_64(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(cmp) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64DW(cmp) };
705#endif
706 bs3CpuInstr2_CommonBinaryU8(bMode, s_aTests8, RT_ELEMENTS(s_aTests8), 0 /*fPassthruEfl*/,
707 g_aBs3CpuInstr2_cmp_TestDataU8, g_cBs3CpuInstr2_cmp_TestDataU8,
708 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
709 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), 0 /*fPassthruEfl*/,
710 g_aBs3CpuInstr2_cmp_TestDataU16, g_cBs3CpuInstr2_cmp_TestDataU16,
711 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
712 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), 0 /*fPassthruEfl*/,
713 g_aBs3CpuInstr2_cmp_TestDataU32, g_cBs3CpuInstr2_cmp_TestDataU32,
714 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
715#if ARCH_BITS == 64
716 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), 0 /*fPassthruEfl*/,
717 g_aBs3CpuInstr2_cmp_TestDataU64, g_cBs3CpuInstr2_cmp_TestDataU64,
718 false /*fCarryIn*/, false /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
719#endif
720 return 0;
721}
722
723
724#define BS3CPUINSTR2_BTx_PASSTHRU_EFL (X86_EFL_ZF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF)
725
726BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bt)(uint8_t bMode)
727{
728 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(bt) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(bt) };
729 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(bt) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(bt) };
730#if ARCH_BITS == 64
731 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(bt) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(bt) };
732#endif
733 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
734 g_aBs3CpuInstr2_bt_TestDataU16, g_cBs3CpuInstr2_bt_TestDataU16,
735 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
736 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
737 g_aBs3CpuInstr2_bt_TestDataU32, g_cBs3CpuInstr2_bt_TestDataU32,
738 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
739#if ARCH_BITS == 64
740 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
741 g_aBs3CpuInstr2_bt_TestDataU64, g_cBs3CpuInstr2_bt_TestDataU64,
742 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, true /*fReadOnly*/);
743#endif
744 return 0;
745}
746
747
748BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_btc)(uint8_t bMode)
749{
750 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(btc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(btc) };
751 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(btc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(btc) };
752#if ARCH_BITS == 64
753 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(btc) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(btc) };
754#endif
755 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
756 g_aBs3CpuInstr2_btc_TestDataU16, g_cBs3CpuInstr2_btc_TestDataU16,
757 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
758 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
759 g_aBs3CpuInstr2_btc_TestDataU32, g_cBs3CpuInstr2_btc_TestDataU32,
760 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
761#if ARCH_BITS == 64
762 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
763 g_aBs3CpuInstr2_btc_TestDataU64, g_cBs3CpuInstr2_btc_TestDataU64,
764 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
765#endif
766 return 0;
767}
768
769
770BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_btr)(uint8_t bMode)
771{
772 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(btr) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(btr) };
773 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(btr) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(btr) };
774#if ARCH_BITS == 64
775 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(btr) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(btr) };
776#endif
777 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
778 g_aBs3CpuInstr2_btr_TestDataU16, g_cBs3CpuInstr2_btr_TestDataU16,
779 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
780 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
781 g_aBs3CpuInstr2_btr_TestDataU32, g_cBs3CpuInstr2_btr_TestDataU32,
782 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
783#if ARCH_BITS == 64
784 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
785 g_aBs3CpuInstr2_btr_TestDataU64, g_cBs3CpuInstr2_btr_TestDataU64,
786 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
787#endif
788 return 0;
789}
790
791
792BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bts)(uint8_t bMode)
793{
794 static const BS3CPUINSTR2CMNBINTEST s_aTests16[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_16(bts) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_16B(bts) };
795 static const BS3CPUINSTR2CMNBINTEST s_aTests32[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_32(bts) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_32B(bts) };
796#if ARCH_BITS == 64
797 static const BS3CPUINSTR2CMNBINTEST s_aTests64[] = { BS3CPUINSTR2CMNBINTEST_ENTRIES_64(bts) BS3CPUINSTR2CMNBINTEST_ENTRIES_IMM_64B(bts) };
798#endif
799 bs3CpuInstr2_CommonBinaryU16(bMode, s_aTests16, RT_ELEMENTS(s_aTests16), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
800 g_aBs3CpuInstr2_bts_TestDataU16, g_cBs3CpuInstr2_bts_TestDataU16,
801 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
802 bs3CpuInstr2_CommonBinaryU32(bMode, s_aTests32, RT_ELEMENTS(s_aTests32), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
803 g_aBs3CpuInstr2_bts_TestDataU32, g_cBs3CpuInstr2_bts_TestDataU32,
804 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
805#if ARCH_BITS == 64
806 bs3CpuInstr2_CommonBinaryU64(bMode, s_aTests64, RT_ELEMENTS(s_aTests64), BS3CPUINSTR2_BTx_PASSTHRU_EFL,
807 g_aBs3CpuInstr2_bts_TestDataU64, g_cBs3CpuInstr2_bts_TestDataU64,
808 false /*fCarryIn*/, true /*fMaskSrcWhenMemDst*/, false /*fReadOnly*/);
809#endif
810 return 0;
811}
812
813
814
815/*
816 * Multiplication
817 */
818
819BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
820{
821#define MUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
822#define MUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
823
824 static const struct
825 {
826 RTCCUINTREG uInAX;
827 RTCCUINTREG uInBX;
828 RTCCUINTREG uOutDX;
829 RTCCUINTREG uOutAX;
830 uint16_t fFlags;
831 } s_aTests[] =
832 {
833 { 1, 1,
834 0, 1, 0 },
835 { 2, 2,
836 0, 4, 0 },
837 { RTCCUINTREG_MAX, RTCCUINTREG_MAX,
838 RTCCUINTREG_MAX-1, 1, X86_EFL_CF | X86_EFL_OF },
839 { RTCCINTREG_MAX, RTCCINTREG_MAX,
840 RTCCINTREG_MAX / 2, 1, X86_EFL_CF | X86_EFL_OF },
841 { 1, RTCCUINTREG_MAX,
842 0, RTCCUINTREG_MAX, X86_EFL_PF | X86_EFL_SF },
843 { 1, RTCCINTREG_MAX,
844 0, RTCCINTREG_MAX, X86_EFL_PF },
845 { 2, RTCCINTREG_MAX,
846 0, RTCCUINTREG_MAX - 1, X86_EFL_SF },
847 { (RTCCUINTREG)RTCCINTREG_MAX + 1, 2,
848 1, 0, X86_EFL_PF | X86_EFL_CF | X86_EFL_OF },
849 { (RTCCUINTREG)RTCCINTREG_MAX / 2 + 1, 3,
850 0, ((RTCCUINTREG)RTCCINTREG_MAX / 2 + 1) * 3, X86_EFL_PF | X86_EFL_SF },
851 };
852
853 BS3REGCTX Ctx;
854 BS3TRAPFRAME TrapFrame;
855 unsigned i, j, k;
856
857 /* Ensure the structures are allocated before we sample the stack pointer. */
858 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
859 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
860
861 /*
862 * Create test context.
863 */
864 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
865 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2));
866 for (k = 0; k < 2; k++)
867 {
868 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
869 for (j = 0; j < 2; j++)
870 {
871 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
872 {
873 if (k == 0)
874 {
875 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
876 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
877 }
878 else
879 {
880 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
881 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
882 }
883 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
884 if (TrapFrame.bXcpt != X86_XCPT_UD)
885 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
886 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
887 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
888 || (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
889 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
890 {
891 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
892 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
893
894 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
895 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
896 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
897 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
898 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
899 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
900 if ( (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
901 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
902 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & MUL_CHECK_EFLAGS,
903 TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO));
904 }
905 }
906 Ctx.rflags.u16 &= ~(MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO);
907 }
908 }
909
910 return 0;
911}
912
913
914BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_imul)(uint8_t bMode)
915{
916#define IMUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
917#define IMUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
918 static const struct
919 {
920 RTCCUINTREG uInAX;
921 RTCCUINTREG uInBX;
922 RTCCUINTREG uOutDX;
923 RTCCUINTREG uOutAX;
924 uint16_t fFlags;
925 } s_aTests[] =
926 {
927 /* two positive values. */
928 { 1, 1,
929 0, 1, 0 },
930 { 2, 2,
931 0, 4, 0 },
932 { RTCCINTREG_MAX, RTCCINTREG_MAX,
933 RTCCINTREG_MAX/2, 1, X86_EFL_CF | X86_EFL_OF },
934 { 1, RTCCINTREG_MAX,
935 0, RTCCINTREG_MAX, X86_EFL_PF },
936 { 2, RTCCINTREG_MAX,
937 0, RTCCUINTREG_MAX - 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF },
938 { 2, RTCCINTREG_MAX / 2,
939 0, RTCCINTREG_MAX - 1U, 0 },
940 { 2, (RTCCINTREG_MAX / 2 + 1),
941 0, (RTCCUINTREG)RTCCINTREG_MAX + 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
942 { 4, (RTCCINTREG_MAX / 2 + 1),
943 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
944
945 /* negative and positive */
946 { -4, 3,
947 -1, -12, X86_EFL_SF },
948 { 32, -127,
949 -1, -4064, X86_EFL_SF },
950 { RTCCINTREG_MIN, 1,
951 -1, RTCCINTREG_MIN, X86_EFL_SF | X86_EFL_PF },
952 { RTCCINTREG_MIN, 2,
953 -1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
954 { RTCCINTREG_MIN, 3,
955 -2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
956 { RTCCINTREG_MIN, 4,
957 -2, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
958 { RTCCINTREG_MIN, RTCCINTREG_MAX,
959 RTCCINTREG_MIN / 2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
960 { RTCCINTREG_MIN, RTCCINTREG_MAX - 1,
961 RTCCINTREG_MIN / 2 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
962
963 /* two negative values. */
964 { -4, -63,
965 0, 252, X86_EFL_PF },
966 { RTCCINTREG_MIN, RTCCINTREG_MIN,
967 RTCCUINTREG_MAX / 4 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
968 { RTCCINTREG_MIN, RTCCINTREG_MIN + 1,
969 RTCCUINTREG_MAX / 4, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF},
970 { RTCCINTREG_MIN + 1, RTCCINTREG_MIN + 1,
971 RTCCUINTREG_MAX / 4, 1, X86_EFL_CF | X86_EFL_OF },
972
973 };
974
975 BS3REGCTX Ctx;
976 BS3TRAPFRAME TrapFrame;
977 unsigned i, j, k;
978
979 /* Ensure the structures are allocated before we sample the stack pointer. */
980 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
981 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
982
983 /*
984 * Create test context.
985 */
986 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
987 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2));
988
989 for (k = 0; k < 2; k++)
990 {
991 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
992 for (j = 0; j < 2; j++)
993 {
994 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
995 {
996 if (k == 0)
997 {
998 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
999 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1000 }
1001 else
1002 {
1003 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1004 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1005 }
1006 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1007 if (TrapFrame.bXcpt != X86_XCPT_UD)
1008 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
1009 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1010 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1011 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1012 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1013 {
1014 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
1015 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
1016
1017 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
1018 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1019 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1020 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1021 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1022 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1023 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1024 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1025 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
1026 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
1027 }
1028 }
1029 }
1030 }
1031
1032 /*
1033 * Repeat for the truncating two operand version.
1034 */
1035 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2));
1036
1037 for (k = 0; k < 2; k++)
1038 {
1039 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
1040 for (j = 0; j < 2; j++)
1041 {
1042 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1043 {
1044 if (k == 0)
1045 {
1046 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1047 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1048 }
1049 else
1050 {
1051 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1052 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1053 }
1054 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1055 if (TrapFrame.bXcpt != X86_XCPT_UD)
1056 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
1057 else if ( TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1058 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1059 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1060 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1061 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1062 {
1063 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
1064 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
1065
1066 if (TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
1067 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
1068 s_aTests[i].uOutAX, TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS));
1069 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
1070 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
1071 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
1072 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
1073 }
1074 }
1075 }
1076 }
1077
1078 return 0;
1079}
1080
1081
1082BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_div)(uint8_t bMode)
1083{
1084#define DIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1085 static const struct
1086 {
1087 RTCCUINTREG uInDX;
1088 RTCCUINTREG uInAX;
1089 RTCCUINTREG uInBX;
1090 RTCCUINTREG uOutAX;
1091 RTCCUINTREG uOutDX;
1092 uint8_t bXcpt;
1093 } s_aTests[] =
1094 {
1095 { 0, 1, 1,
1096 1, 0, X86_XCPT_UD },
1097 { 0, 5, 2,
1098 2, 1, X86_XCPT_UD },
1099 { 0, 0, 0,
1100 0, 0, X86_XCPT_DE },
1101 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 0,
1102 0, 0, X86_XCPT_DE },
1103 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 1,
1104 0, 0, X86_XCPT_DE },
1105 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
1106 0, 0, X86_XCPT_DE },
1107 { RTCCUINTREG_MAX - 1, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
1108 RTCCUINTREG_MAX, RTCCUINTREG_MAX - 1, X86_XCPT_UD },
1109 };
1110
1111 BS3REGCTX Ctx;
1112 BS3TRAPFRAME TrapFrame;
1113 unsigned i, j;
1114
1115 /* Ensure the structures are allocated before we sample the stack pointer. */
1116 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1117 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1118
1119 /*
1120 * Create test context.
1121 */
1122 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1123 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2));
1124
1125 /*
1126 * Do the tests twice, first with all flags set, then once again with
1127 * flags cleared. The flags are not touched by my intel skylake CPU.
1128 */
1129 Ctx.rflags.u16 |= DIV_CHECK_EFLAGS;
1130 for (j = 0; j < 2; j++)
1131 {
1132 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1133 {
1134 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1135 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
1136 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1137 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1138
1139 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
1140 || ( s_aTests[i].bXcpt == X86_XCPT_UD
1141 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1142 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1143 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS)
1144 : TrapFrame.Ctx.rax.u != Ctx.rax.u
1145 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1146 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS) ) )
1147 {
1148 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
1149 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
1150 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
1151 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
1152 if (s_aTests[i].bXcpt == X86_XCPT_UD)
1153 {
1154 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
1155 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1156 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1157 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1158 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1159 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1160 if ((TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS))
1161 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
1162 Ctx.rflags.u16 & DIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS);
1163 }
1164 }
1165 }
1166 Ctx.rflags.u16 &= ~DIV_CHECK_EFLAGS;
1167 }
1168
1169 return 0;
1170}
1171
1172
1173
1174BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_idiv)(uint8_t bMode)
1175{
1176#define IDIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
1177 static const struct
1178 {
1179 RTCCUINTREG uInDX;
1180 RTCCUINTREG uInAX;
1181 RTCCUINTREG uInBX;
1182 RTCCUINTREG uOutAX;
1183 RTCCUINTREG uOutDX;
1184 uint8_t bXcpt;
1185 } s_aTests[] =
1186 {
1187 { 0, 0, 0,
1188 0, 0, X86_XCPT_DE },
1189 { RTCCINTREG_MAX, RTCCINTREG_MAX, 0,
1190 0, 0, X86_XCPT_DE },
1191 /* two positive values. */
1192 { 0, 1, 1,
1193 1, 0, X86_XCPT_UD },
1194 { 0, 5, 2,
1195 2, 1, X86_XCPT_UD },
1196 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2, RTCCINTREG_MAX,
1197 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_UD },
1198 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2 + 1, RTCCINTREG_MAX,
1199 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_DE },
1200 /* negative dividend, positive divisor. */
1201 { -1, -7, 2,
1202 -3, -1, X86_XCPT_UD },
1203 { RTCCINTREG_MIN / 2 + 1, 0, RTCCINTREG_MAX,
1204 RTCCINTREG_MIN + 2, RTCCINTREG_MIN + 2, X86_XCPT_UD },
1205 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MAX,
1206 0, 0, X86_XCPT_DE },
1207 /* positive dividend, negative divisor. */
1208 { 0, 7, -2,
1209 -3, 1, X86_XCPT_UD },
1210 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX, RTCCINTREG_MIN,
1211 RTCCINTREG_MIN, RTCCINTREG_MAX, X86_XCPT_UD },
1212 { RTCCINTREG_MAX / 2 + 1, (RTCCUINTREG)RTCCINTREG_MAX+1, RTCCINTREG_MIN,
1213 0, 0, X86_XCPT_DE },
1214 /* negative dividend, negative divisor. */
1215 { -1, -7, -2,
1216 3, -1, X86_XCPT_UD },
1217 { RTCCINTREG_MIN / 2, 1, RTCCINTREG_MIN,
1218 RTCCINTREG_MAX, RTCCINTREG_MIN + 1, X86_XCPT_UD },
1219 { RTCCINTREG_MIN / 2, 2, RTCCINTREG_MIN,
1220 RTCCINTREG_MAX, RTCCINTREG_MIN + 2, X86_XCPT_UD },
1221 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MIN,
1222 0, 0, X86_XCPT_DE },
1223 };
1224
1225 BS3REGCTX Ctx;
1226 BS3TRAPFRAME TrapFrame;
1227 unsigned i, j;
1228
1229 /* Ensure the structures are allocated before we sample the stack pointer. */
1230 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1231 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1232
1233 /*
1234 * Create test context.
1235 */
1236 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1237 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2));
1238
1239 /*
1240 * Do the tests twice, first with all flags set, then once again with
1241 * flags cleared. The flags are not touched by my intel skylake CPU.
1242 */
1243 Ctx.rflags.u16 |= IDIV_CHECK_EFLAGS;
1244 for (j = 0; j < 2; j++)
1245 {
1246 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1247 {
1248 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
1249 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
1250 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
1251 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1252
1253 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
1254 || ( s_aTests[i].bXcpt == X86_XCPT_UD
1255 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
1256 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
1257 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS)
1258 : TrapFrame.Ctx.rax.u != Ctx.rax.u
1259 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1260 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) ) )
1261 {
1262 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
1263 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
1264 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
1265 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
1266 if (s_aTests[i].bXcpt == X86_XCPT_UD)
1267 {
1268 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
1269 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1270 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
1271 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
1272 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
1273 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
1274 if ((TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS))
1275 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
1276 Ctx.rflags.u16 & IDIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS);
1277 }
1278 }
1279 }
1280 Ctx.rflags.u16 &= ~IDIV_CHECK_EFLAGS;
1281 }
1282
1283 return 0;
1284}
1285
1286
1287/*
1288 * BSF/BSR (386+) & TZCNT/LZCNT (BMI1,ABM)
1289 */
1290
1291typedef struct BS3CPUINSTR2_SUBTEST_BITSCAN_T
1292{
1293 RTCCUINTXREG uSrc;
1294 RTCCUINTXREG uOut;
1295 bool fOutNotSet;
1296 uint16_t fEflOut;
1297} BS3CPUINSTR2_SUBTEST_BITSCAN_T;
1298
1299typedef struct BS3CPUINSTR2_TEST_BITSCAN_T
1300{
1301 FPFNBS3FAR pfnWorker;
1302 bool fMemSrc;
1303 uint8_t cbInstr;
1304 uint8_t cOpBits;
1305 uint16_t fEflCheck;
1306 uint8_t cSubTests;
1307 BS3CPUINSTR2_SUBTEST_BITSCAN_T const *paSubTests;
1308} BS3CPUINSTR2_TEST_BITSCAN_T;
1309
1310static uint8_t bs3CpuInstr2_BitScan(uint8_t bMode, BS3CPUINSTR2_TEST_BITSCAN_T const *paTests, unsigned cTests)
1311{
1312 BS3REGCTX Ctx;
1313 BS3TRAPFRAME TrapFrame;
1314 unsigned i, j, k;
1315
1316 /* Ensure the structures are allocated before we sample the stack pointer. */
1317 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1318 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1319
1320 /*
1321 * Create test context.
1322 */
1323 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1324
1325 /*
1326 * Do the tests twice, first with all flags set, then once again with
1327 * flags cleared. The flags are not supposed to be touched at all.
1328 */
1329 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1330 for (j = 0; j < 2; j++)
1331 {
1332 for (i = 0; i < cTests; i++)
1333 {
1334 for (k = 0; k < paTests[i].cSubTests; k++)
1335 {
1336 uint64_t uExpectRax, uExpectRip;
1337 RTCCUINTXREG uMemSrc, uMemSrcExpect;
1338
1339 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
1340 if (!paTests[i].fMemSrc)
1341 {
1342 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
1343 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
1344 }
1345 else
1346 {
1347 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
1348 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
1349 }
1350 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
1351 if (paTests[i].paSubTests[k].fOutNotSet)
1352 uExpectRax = Ctx.rax.u;
1353 else if (paTests[i].cOpBits != 16)
1354 uExpectRax = paTests[i].paSubTests[k].uOut;
1355 else
1356 uExpectRax = paTests[i].paSubTests[k].uOut | (Ctx.rax.u & UINT64_C(0xffffffffffff0000));
1357 uExpectRip = Ctx.rip.u + paTests[i].cbInstr;
1358 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1359
1360 if ( TrapFrame.bXcpt != X86_XCPT_UD
1361 || TrapFrame.Ctx.rip.u != uExpectRip
1362 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
1363 || TrapFrame.Ctx.rax.u != uExpectRax
1364 || (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
1365 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck)
1366 /* check that nothing else really changed: */
1367 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1368 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1369 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1370 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1371 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1372 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1373 || uMemSrc != uMemSrcExpect
1374 )
1375 {
1376 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
1377 i, k, paTests[i].paSubTests[k].uSrc);
1378 if (TrapFrame.bXcpt != X86_XCPT_UD)
1379 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", X86_XCPT_UD, TrapFrame.bXcpt);
1380 if (TrapFrame.Ctx.rip.u != uExpectRip)
1381 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1382 if (TrapFrame.Ctx.rax.u != uExpectRax)
1383 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
1384 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1385 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1386 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
1387 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
1388 if ( (TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck)
1389 != (paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck))
1390 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
1391 paTests[i].paSubTests[k].fEflOut & paTests[i].fEflCheck,
1392 TrapFrame.Ctx.rflags.u16 & paTests[i].fEflCheck);
1393
1394 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1395 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1396 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1397 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1398 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1399 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1400 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1401 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1402 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1403 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1404 if (uMemSrc != uMemSrcExpect)
1405 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
1406 }
1407 }
1408 }
1409 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1410 }
1411
1412 return 0;
1413}
1414
1415
1416BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsf_tzcnt)(uint8_t bMode)
1417{
1418 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf16[] =
1419 {
1420 { 0, /* -> */ 0, true, X86_EFL_ZF },
1421 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
1422 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1423 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1424 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1425 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1426 };
1427 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt16[] =
1428 {
1429 { 0, /* -> */ 16, false, X86_EFL_CF },
1430 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
1431 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1432 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1433 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1434 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1435 };
1436 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf32[] =
1437 {
1438 { 0, /* -> */ 0, true, X86_EFL_ZF },
1439#if ARCH_BITS == 64
1440 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
1441#endif
1442 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1443 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1444 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1445 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1446 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1447 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1448 };
1449 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt32[] =
1450 {
1451 { 0, /* -> */ 32, false, X86_EFL_CF },
1452#if ARCH_BITS == 64
1453 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
1454#endif
1455 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1456 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1457 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1458 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1459 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1460 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1461 };
1462#if ARCH_BITS == 64
1463 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsf64[] =
1464 {
1465 { 0, /* -> */ 0, true, X86_EFL_ZF },
1466 { ~(RTCCUINTXREG)0, /* -> */ 0, false, 0 },
1467 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1468 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1469 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1470 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1471 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1472 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1473 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
1474 };
1475 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsTzCnt64[] =
1476 {
1477 { 0, /* -> */ 64, false, X86_EFL_CF },
1478 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1479 { ~(RTCCUINTXREG)1, /* -> */ 1, false, 0 },
1480 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1481 { UINT16_C(0x4560), /* -> */ 5, false, 0 },
1482 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1483 { UINT32_C(0x45600000), /* -> */ 21, false, 0 },
1484 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1485 { UINT64_C(0x4560000000000000), /* -> */ 53, false, 0 },
1486 };
1487#endif
1488 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
1489 {
1490 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1491 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1492 { BS3_CMN_NM(bs3CpuInstr2_bsf_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1493 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1494 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1495 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1496 { BS3_CMN_NM(bs3CpuInstr2_bsf_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1497 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1498#if ARCH_BITS == 64
1499 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
1500 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1501 { BS3_CMN_NM(bs3CpuInstr2_bsf_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
1502 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1503#endif
1504 /* f2 prefixed variant: */
1505 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1506 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1507 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1508 RT_ELEMENTS(s_aSubTestsBsf16), s_aSubTestsBsf16 },
1509 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1510 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1511 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1512 RT_ELEMENTS(s_aSubTestsBsf32), s_aSubTestsBsf32 },
1513#if ARCH_BITS == 64
1514 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
1515 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1516 { BS3_CMN_NM(bs3CpuInstr2_f2_bsf_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
1517 RT_ELEMENTS(s_aSubTestsBsf64), s_aSubTestsBsf64 },
1518#endif
1519
1520 /* tzcnt: */
1521 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1522 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1523 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1524 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1525 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1526 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1527 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1528 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1529#if ARCH_BITS == 64
1530 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1531 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1532 { BS3_CMN_NM(bs3CpuInstr2_tzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1533 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1534#endif
1535 /* f2 prefixed tzcnt variant (last prefix (f3) should prevail): */
1536 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1537 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1538 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1539 RT_ELEMENTS(s_aSubTestsTzCnt16), s_aSubTestsTzCnt16 },
1540 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1541 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1542 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1543 RT_ELEMENTS(s_aSubTestsTzCnt32), s_aSubTestsTzCnt32 },
1544#if ARCH_BITS == 64
1545 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1546 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1547 { BS3_CMN_NM(bs3CpuInstr2_f2_tzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1548 RT_ELEMENTS(s_aSubTestsTzCnt64), s_aSubTestsTzCnt64 },
1549#endif
1550 };
1551
1552 uint32_t uStdExtFeatEbx = 0;
1553 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1554 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1555 if (!(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1))
1556 {
1557 unsigned i = RT_ELEMENTS(s_aTests);
1558 while (i-- > 0)
1559 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1560 {
1561 s_aTests[i].fEflCheck = X86_EFL_ZF;
1562 switch (s_aTests[i].cOpBits)
1563 {
1564 case 16:
1565 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf16);
1566 s_aTests[i].paSubTests = s_aSubTestsBsf16;
1567 break;
1568 case 32:
1569 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf32);
1570 s_aTests[i].paSubTests = s_aSubTestsBsf32;
1571 break;
1572#if ARCH_BITS == 64
1573 case 64:
1574 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsf64);
1575 s_aTests[i].paSubTests = s_aSubTestsBsf64;
1576 break;
1577#endif
1578 }
1579 }
1580 Bs3TestPrintf("tzcnt not supported\n");
1581 }
1582
1583 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1584}
1585
1586
1587BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bsr_lzcnt)(uint8_t bMode)
1588{
1589 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr16[] =
1590 {
1591 { 0, /* -> */ 0, true, X86_EFL_ZF },
1592 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 0, true, X86_EFL_ZF },
1593 { ~(RTCCUINTXREG)0, /* -> */ 15, false, 0 },
1594 { ~(RTCCUINTXREG)1, /* -> */ 15, false, 0 },
1595 { UINT16_C(0x0001), /* -> */ 0, false, 0 },
1596 { UINT16_C(0x0002), /* -> */ 1, false, 0 },
1597 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1598 };
1599 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt16[] =
1600 {
1601 { 0, /* -> */ 16, false, X86_EFL_CF },
1602 { ~(RTCCUINTXREG)UINT16_MAX, /* -> */ 16, false, X86_EFL_CF },
1603 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1604 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1605 { UINT16_C(0x8000), /* -> */ 0, false, X86_EFL_ZF },
1606 { UINT16_C(0x4560), /* -> */ 1, false, 0 },
1607 { UINT16_C(0x003f), /* -> */ 10, false, 0 },
1608 { UINT16_C(0x0001), /* -> */ 15, false, 0 },
1609 };
1610 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr32[] =
1611 {
1612 { 0, /* -> */ 0, true, X86_EFL_ZF },
1613#if ARCH_BITS == 64
1614 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 0, true, X86_EFL_ZF },
1615#endif
1616 { ~(RTCCUINTXREG)0, /* -> */ 31, false, 0 },
1617 { ~(RTCCUINTXREG)1, /* -> */ 31, false, 0 },
1618 { 1, /* -> */ 0, false, 0 },
1619 { 2, /* -> */ 1, false, 0 },
1620 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1621 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1622 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1623 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1624 };
1625 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt32[] =
1626 {
1627 { 0, /* -> */ 32, false, X86_EFL_CF },
1628#if ARCH_BITS == 64
1629 { ~(RTCCUINTXREG)UINT32_MAX, /* -> */ 32, false, X86_EFL_CF },
1630#endif
1631 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1632 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1633 { 1, /* -> */ 31, false, 0 },
1634 { 2, /* -> */ 30, false, 0},
1635 { UINT16_C(0x8000), /* -> */ 16, false, 0 },
1636 { UINT16_C(0x4560), /* -> */ 17, false, 0 },
1637 { UINT32_C(0x80000000), /* -> */ 0, false, X86_EFL_ZF },
1638 { UINT32_C(0x45600000), /* -> */ 1, false, 0 },
1639 { UINT32_C(0x0000ffff), /* -> */ 16, false, 0 },
1640 };
1641#if ARCH_BITS == 64
1642 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsBsr64[] =
1643 {
1644 { 0, /* -> */ 0, true, X86_EFL_ZF },
1645 { ~(RTCCUINTXREG)0, /* -> */ 63, false, 0 },
1646 { ~(RTCCUINTXREG)1, /* -> */ 63, false, 0 },
1647 { 1, /* -> */ 0, false, 0 },
1648 { 2, /* -> */ 1, false, 0 },
1649 { UINT16_C(0x8000), /* -> */ 15, false, 0 },
1650 { UINT16_C(0x4560), /* -> */ 14, false, 0 },
1651 { UINT32_C(0x80000000), /* -> */ 31, false, 0 },
1652 { UINT32_C(0x45600000), /* -> */ 30, false, 0 },
1653 { UINT64_C(0x8000000000000000), /* -> */ 63, false, 0 },
1654 { UINT64_C(0x0045600000000000), /* -> */ 54, false, 0 },
1655 };
1656 static BS3CPUINSTR2_SUBTEST_BITSCAN_T const s_aSubTestsLzCnt64[] =
1657 {
1658 { 0, /* -> */ 64, false, X86_EFL_CF },
1659 { ~(RTCCUINTXREG)0, /* -> */ 0, false, X86_EFL_ZF },
1660 { ~(RTCCUINTXREG)1, /* -> */ 0, false, X86_EFL_ZF },
1661 { 1, /* -> */ 63, false, 0 },
1662 { 2, /* -> */ 62, false, 0 },
1663 { UINT16_C(0x8000), /* -> */ 48, false, 0 },
1664 { UINT16_C(0x4560), /* -> */ 49, false, 0 },
1665 { UINT32_C(0x80000000), /* -> */ 32, false, 0 },
1666 { UINT32_C(0x45600000), /* -> */ 33, false, 0 },
1667 { UINT64_C(0x8000000000000000), /* -> */ 0, false, X86_EFL_ZF },
1668 { UINT64_C(0x4560000000000000), /* -> */ 1, false, 0 },
1669 { UINT64_C(0x0045600000000000), /* -> */ 9, false, 0 },
1670 };
1671#endif
1672 static BS3CPUINSTR2_TEST_BITSCAN_T s_aTests[] =
1673 {
1674 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_BX_ud2), false, 3 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1675 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1676 { BS3_CMN_NM(bs3CpuInstr2_bsr_AX_FSxBX_ud2), true, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1677 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1678 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_EBX_ud2), false, 3 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1679 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1680 { BS3_CMN_NM(bs3CpuInstr2_bsr_EAX_FSxBX_ud2), true, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1681 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1682#if ARCH_BITS == 64
1683 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_RBX_ud2), false, 4, 64, X86_EFL_ZF,
1684 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1685 { BS3_CMN_NM(bs3CpuInstr2_bsr_RAX_FSxBX_ud2), true, 5, 64, X86_EFL_ZF,
1686 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1687#endif
1688 /* f2 prefixed variant: */
1689 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1690 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1691 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF,
1692 RT_ELEMENTS(s_aSubTestsBsr16), s_aSubTestsBsr16 },
1693 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1694 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1695 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF,
1696 RT_ELEMENTS(s_aSubTestsBsr32), s_aSubTestsBsr32 },
1697#if ARCH_BITS == 64
1698 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF,
1699 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1700 { BS3_CMN_NM(bs3CpuInstr2_f2_bsr_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF,
1701 RT_ELEMENTS(s_aSubTestsBsr64), s_aSubTestsBsr64 },
1702#endif
1703
1704 /* lzcnt: */
1705 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_BX_ud2), false, 4 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1706 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1707 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_AX_FSxBX_ud2), true, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1708 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1709 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_EBX_ud2), false, 4 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1710 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1711 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_EAX_FSxBX_ud2), true, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1712 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1713#if ARCH_BITS == 64
1714 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_RBX_ud2), false, 5, 64, X86_EFL_ZF | X86_EFL_CF,
1715 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1716 { BS3_CMN_NM(bs3CpuInstr2_lzcnt_RAX_FSxBX_ud2), true, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1717 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1718#endif
1719 /* f2 prefixed lzcnt variant (last prefix (f3) should prevail): */
1720 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_BX_ud2), false, 5 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1721 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1722 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_AX_FSxBX_ud2), true, 6 + (ARCH_BITS != 16), 16, X86_EFL_ZF | X86_EFL_CF,
1723 RT_ELEMENTS(s_aSubTestsLzCnt16), s_aSubTestsLzCnt16 },
1724 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_EBX_ud2), false, 5 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1725 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1726 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_EAX_FSxBX_ud2),true, 6 + (ARCH_BITS == 16), 32, X86_EFL_ZF | X86_EFL_CF,
1727 RT_ELEMENTS(s_aSubTestsLzCnt32), s_aSubTestsLzCnt32 },
1728#if ARCH_BITS == 64
1729 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_RBX_ud2), false, 6, 64, X86_EFL_ZF | X86_EFL_CF,
1730 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1731 { BS3_CMN_NM(bs3CpuInstr2_f2_lzcnt_RAX_FSxBX_ud2),true, 7, 64, X86_EFL_ZF | X86_EFL_CF,
1732 RT_ELEMENTS(s_aSubTestsLzCnt64), s_aSubTestsLzCnt64 },
1733#endif
1734 };
1735
1736 uint32_t uExtFeatEcx = 0;
1737 if (g_uBs3CpuDetected & BS3CPU_F_CPUID_EXT_LEAVES)
1738 ASMCpuIdExSlow(UINT32_C(0x80000001), 0, 0, 0, NULL, NULL, &uExtFeatEcx, NULL);
1739 if (!(uExtFeatEcx & X86_CPUID_AMD_FEATURE_ECX_ABM))
1740 {
1741 unsigned i = RT_ELEMENTS(s_aTests);
1742 while (i-- > 0)
1743 if (s_aTests[i].fEflCheck & X86_EFL_CF)
1744 {
1745 s_aTests[i].fEflCheck = X86_EFL_ZF;
1746 switch (s_aTests[i].cOpBits)
1747 {
1748 case 16:
1749 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr16);
1750 s_aTests[i].paSubTests = s_aSubTestsBsr16;
1751 break;
1752 case 32:
1753 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr32);
1754 s_aTests[i].paSubTests = s_aSubTestsBsr32;
1755 break;
1756#if ARCH_BITS == 64
1757 case 64:
1758 s_aTests[i].cSubTests = RT_ELEMENTS(s_aSubTestsBsr64);
1759 s_aTests[i].paSubTests = s_aSubTestsBsr64;
1760 break;
1761#endif
1762 }
1763 }
1764 Bs3TestPrintf("lzcnt not supported\n");
1765 }
1766
1767 return bs3CpuInstr2_BitScan(bMode, s_aTests, RT_ELEMENTS(s_aTests));
1768}
1769
1770
1771/**
1772 * RORX
1773 */
1774BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rorx)(uint8_t bMode)
1775{
1776 static const struct
1777 {
1778 FPFNBS3FAR pfnWorker;
1779 bool fMemSrc;
1780 bool fOkay;
1781 RTCCUINTXREG uIn;
1782 RTCCUINTXREG uOut;
1783 } s_aTests[] =
1784 {
1785 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1786 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #0
1787 0, /* -> */ 0 },
1788 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_RDX_2_icebp), false, true, // #1
1789 ~(RTCCUINTXREG)2, /* -> */ ~(RTCCUINTXREG)0 >> 1 },
1790 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #2
1791 0, /* -> */ 0 },
1792 { BS3_CMN_NM(bs3CpuInstr2_rorx_RBX_DSxDI_68_icebp), true, true, // #3
1793 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG_MAX >> 4) | (~(RTCCUINTXREG)2 << (sizeof(RTCCUINTXREG) * 8 - 4)) },
1794
1795 /* 32 bits register width: */
1796 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #4
1797 0, /* -> */ 0 },
1798 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp), false, true, // #5
1799 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)(~(uint32_t)0 >> 1) },
1800 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #6
1801 0, /* -> */ 0 },
1802 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_DSxDI_36_icebp), true, true, // #7
1803 ~(RTCCUINTXREG)2, /* -> */ (RTCCUINTXREG)UINT32_C(0xdfffffff) },
1804
1805 /* encoding tests: */
1806 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_L1), false, false, // #8
1807 RTCCUINTXREG_MAX, /* -> */ 0 },
1808 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V1), false, false, // #9
1809 RTCCUINTXREG_MAX, /* -> */ 0 },
1810 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_V15), false, false, // #10
1811 RTCCUINTXREG_MAX, /* -> */ 0 },
1812# if ARCH_BITS == 64 /* The VEX.X=0 encoding mean LES instruction in 32-bit and 16-bit mode. */
1813 { BS3_CMN_NM(bs3CpuInstr2_rorx_EBX_EDX_2_icebp_X1), false, true, // #11
1814 UINT32_C(0xf1e2d3c5), /* -> */ (RTCCUINTXREG)UINT32_C(0x7c78b4f1) },
1815# endif
1816 };
1817
1818 BS3REGCTX Ctx;
1819 BS3TRAPFRAME TrapFrame;
1820 unsigned i, j;
1821 uint32_t uStdExtFeatEbx = 0;
1822 bool fSupportsRorX;
1823
1824 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1825 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1826 fSupportsRorX = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
1827
1828 /* Ensure the structures are allocated before we sample the stack pointer. */
1829 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1830 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1831
1832 /*
1833 * Create test context.
1834 */
1835 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1836
1837 /*
1838 * Do the tests twice, first with all flags set, then once again with
1839 * flags cleared. The flags are not supposed to be touched at all.
1840 */
1841 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1842 for (j = 0; j < 2; j++)
1843 {
1844 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1845 {
1846 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && s_aTests[i].fOkay && fSupportsRorX;
1847 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1848 uint64_t uExpectRbx, uExpectRip;
1849 RTCCUINTXREG uMemSrc, uMemSrcExpect;
1850 Ctx.rbx.uCcXReg = RTCCUINTXREG_MAX * 1019;
1851 if (!s_aTests[i].fMemSrc)
1852 {
1853 Ctx.rdx.uCcXReg = s_aTests[i].uIn;
1854 uMemSrcExpect = uMemSrc = ~s_aTests[i].uIn;
1855 }
1856 else
1857 {
1858 Ctx.rdx.uCcXReg = ~s_aTests[i].uIn;
1859 uMemSrcExpect = uMemSrc = s_aTests[i].uIn;
1860 Bs3RegCtxSetGrpDsFromCurPtr(&Ctx, &Ctx.rdi, &uMemSrc);
1861 }
1862 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
1863 uExpectRbx = fOkay ? s_aTests[i].uOut : Ctx.rbx.u;
1864 uExpectRip = Ctx.rip.u + (fOkay ? 6 + 1 : 0);
1865 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
1866
1867 if ( TrapFrame.bXcpt != bExpectXcpt
1868 || TrapFrame.Ctx.rip.u != uExpectRip
1869 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
1870 || TrapFrame.Ctx.rbx.u != uExpectRbx
1871 /* check that nothing else really changed: */
1872 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
1873 || TrapFrame.Ctx.rax.u != Ctx.rax.u
1874 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
1875 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
1876 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
1877 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
1878 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
1879 || uMemSrc != uMemSrcExpect
1880 )
1881 {
1882 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uIn);
1883 if (TrapFrame.bXcpt != bExpectXcpt)
1884 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
1885 if (TrapFrame.Ctx.rip.u != uExpectRip)
1886 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
1887 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
1888 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
1889 if (TrapFrame.Ctx.rbx.u != uExpectRbx)
1890 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", uExpectRbx, TrapFrame.Ctx.rbx.u);
1891
1892 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
1893 Bs3TestFailedF("Expected EFLAGS = %#06RX64, got %#06RX64",
1894 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
1895 if (TrapFrame.Ctx.rax.u != Ctx.rax.u)
1896 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", Ctx.rax.u, TrapFrame.Ctx.rax.u);
1897 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
1898 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
1899 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
1900 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
1901 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
1902 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
1903 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
1904 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
1905 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
1906 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
1907 if (uMemSrc != uMemSrcExpect)
1908 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
1909 }
1910 }
1911 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
1912 }
1913
1914 return 0;
1915}
1916
1917
1918BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_andn)(uint8_t bMode)
1919{
1920#define ANDN_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_ZF | X86_EFL_OF | X86_EFL_SF)
1921#define ANDN_IGNORE_EFLAGS (uint16_t)(X86_EFL_AF | X86_EFL_PF) /* undefined, ignoring for now */
1922 static const struct
1923 {
1924 FPFNBS3FAR pfnWorker;
1925 bool fMemSrc;
1926 uint8_t cbInstr;
1927 RTCCUINTXREG uSrc1;
1928 RTCCUINTXREG uSrc2;
1929 RTCCUINTXREG uOut;
1930 uint16_t fEFlags;
1931 } s_aTests[] =
1932 {
1933 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
1934 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #0
1935 0, 0, /* -> */ 0, X86_EFL_ZF },
1936 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_RBX_icebp), false, 5, // #1
1937 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1938 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #2
1939 0, 0, /* -> */ 0, X86_EFL_ZF },
1940 { BS3_CMN_NM(bs3CpuInstr2_andn_RAX_RCX_FSxBX_icebp), true, 6, // #3
1941 2, ~(RTCCUINTXREG)3, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
1942
1943 /* 32-bit register width */
1944 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #4
1945 0, 0, /* -> */ 0, X86_EFL_ZF },
1946 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_EBX_icebp), false, 5, // #5
1947 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1948 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #6
1949 0, 0, /* -> */ 0, X86_EFL_ZF },
1950 { BS3_CMN_NM(bs3CpuInstr2_andn_EAX_ECX_FSxBX_icebp), true, 6, // #7
1951 2, ~(RTCCUINTXREG)7, /* -> */ ~(uint32_t)7, X86_EFL_SF },
1952
1953 };
1954
1955 BS3REGCTX Ctx;
1956 BS3TRAPFRAME TrapFrame;
1957 unsigned i, j;
1958 uint32_t uStdExtFeatEbx = 0;
1959 bool fSupportsAndN;
1960
1961 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
1962 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
1963 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI1);
1964
1965 /* Ensure the structures are allocated before we sample the stack pointer. */
1966 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
1967 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
1968
1969 /*
1970 * Create test context.
1971 */
1972 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
1973
1974 /*
1975 * Do the tests twice, first with all flags set, then once again with
1976 * flags cleared. The flags are not supposed to be touched at all.
1977 */
1978 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
1979 for (j = 0; j < 2; j++)
1980 {
1981 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
1982 {
1983 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
1984 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
1985 uint64_t uExpectRax, uExpectRip;
1986 RTCCUINTXREG uMemSrc2, uMemSrc2Expect;
1987
1988 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
1989 Ctx.rcx.uCcXReg = s_aTests[i].uSrc1;
1990 if (!s_aTests[i].fMemSrc)
1991 {
1992 Ctx.rbx.uCcXReg = s_aTests[i].uSrc2;
1993 uMemSrc2Expect = uMemSrc2 = ~s_aTests[i].uSrc2;
1994 }
1995 else
1996 {
1997 uMemSrc2Expect = uMemSrc2 = s_aTests[i].uSrc2;
1998 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc2);
1999 }
2000 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2001 uExpectRax = fOkay ? s_aTests[i].uOut : Ctx.rax.u;
2002 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2003 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2004
2005 if ( TrapFrame.bXcpt != bExpectXcpt
2006 || TrapFrame.Ctx.rip.u != uExpectRip
2007 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2008 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2009 || TrapFrame.Ctx.rax.u != uExpectRax
2010 /* check that nothing else really changed: */
2011 || (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
2012 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS)
2013 || (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2014 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2015 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2016 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2017 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2018 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2019 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2020 || uMemSrc2 != uMemSrc2Expect
2021 )
2022 {
2023 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
2024 if (TrapFrame.bXcpt != bExpectXcpt)
2025 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2026 if (TrapFrame.Ctx.rip.u != uExpectRip)
2027 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2028 if (TrapFrame.Ctx.rax.u != uExpectRax)
2029 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2030 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2031 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2032 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2033 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2034 if ( (TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS)
2035 != ((fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS))
2036 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2037 (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16) & ANDN_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & ANDN_CHECK_EFLAGS);
2038 if ( (TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS)
2039 != (Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS))
2040 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2041 Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS,
2042 TrapFrame.Ctx.rflags.u16 & ~(ANDN_CHECK_EFLAGS | ANDN_IGNORE_EFLAGS) & X86_EFL_STATUS_BITS);
2043
2044 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2045 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2046 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2047 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2048 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2049 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2050 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2051 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2052 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2053 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2054 if (uMemSrc2 != uMemSrc2Expect)
2055 Bs3TestFailedF("Expected uMemSrc2 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc2Expect, (uint64_t)uMemSrc2);
2056 }
2057 }
2058 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2059 }
2060
2061 return 0;
2062}
2063
2064/*
2065 * For testing BEXTR, SHLX SARX & SHRX.
2066 */
2067typedef struct BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T
2068{
2069 RTCCUINTXREG uSrc1;
2070 RTCCUINTXREG uSrc2;
2071 RTCCUINTXREG uOut;
2072 uint16_t fEflOut;
2073} BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T;
2074
2075typedef struct BS3CPUINSTR2_TEST_Gy_Ey_By_T
2076{
2077 FPFNBS3FAR pfnWorker;
2078 bool fMemSrc;
2079 uint8_t cbInstr;
2080 uint8_t cSubTests;
2081 BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const *paSubTests;
2082} BS3CPUINSTR2_TEST_Gy_Ey_By_T;
2083
2084static uint8_t bs3CpuInstr2_Common_Gy_Ey_By(uint8_t bMode, BS3CPUINSTR2_TEST_Gy_Ey_By_T const *paTests, unsigned cTests,
2085 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
2086{
2087 BS3REGCTX Ctx;
2088 BS3TRAPFRAME TrapFrame;
2089 unsigned i, j, k;
2090 uint32_t uStdExtFeatEbx = 0;
2091 bool fSupportsInstr;
2092
2093 fEflCheck &= ~fEflIgnore;
2094
2095 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2096 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2097 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
2098
2099 /* Ensure the structures are allocated before we sample the stack pointer. */
2100 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2101 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2102
2103 /*
2104 * Create test context.
2105 */
2106 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2107
2108 /*
2109 * Do the tests twice, first with all flags set, then once again with
2110 * flags cleared. The flags are not supposed to be touched at all.
2111 */
2112 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2113 for (j = 0; j < 2; j++)
2114 {
2115 for (i = 0; i < cTests; i++)
2116 {
2117 for (k = 0; k < paTests[i].cSubTests; k++)
2118 {
2119 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
2120 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2121 uint64_t uExpectRax, uExpectRip;
2122 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
2123
2124 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2125 Ctx.rcx.uCcXReg = paTests[i].paSubTests[k].uSrc2;
2126 if (!paTests[i].fMemSrc)
2127 {
2128 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc1;
2129 uMemSrc1Expect = uMemSrc1 = ~paTests[i].paSubTests[k].uSrc1;
2130 }
2131 else
2132 {
2133 uMemSrc1Expect = uMemSrc1 = paTests[i].paSubTests[k].uSrc1;
2134 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
2135 }
2136 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
2137 uExpectRax = fOkay ? paTests[i].paSubTests[k].uOut : Ctx.rax.u;
2138 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
2139 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2140
2141 if ( TrapFrame.bXcpt != bExpectXcpt
2142 || TrapFrame.Ctx.rip.u != uExpectRip
2143 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2144 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2145 || TrapFrame.Ctx.rax.u != uExpectRax
2146 /* check that nothing else really changed: */
2147 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2148 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
2149 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2150 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2151 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2152 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2153 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2154 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2155 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2156 || uMemSrc1 != uMemSrc1Expect
2157 )
2158 {
2159 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT,
2160 i, k, paTests[i].paSubTests[k].uSrc1, paTests[i].paSubTests[k].uSrc2);
2161 if (TrapFrame.bXcpt != bExpectXcpt)
2162 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2163 if (TrapFrame.Ctx.rip.u != uExpectRip)
2164 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2165 if (TrapFrame.Ctx.rax.u != uExpectRax)
2166 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2167 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2168 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2169 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2170 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2171 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2172 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
2173 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2174 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
2175 TrapFrame.Ctx.rflags.u16 & fEflCheck);
2176 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2177 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
2178 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2179 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
2180 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
2181
2182 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2183 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2184 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2185 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2186 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2187 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2188 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2189 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2190 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2191 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2192 if (uMemSrc1 != uMemSrc1Expect)
2193 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
2194 }
2195 }
2196 }
2197 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2198 }
2199
2200 return 0;
2201}
2202
2203
2204BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bextr)(uint8_t bMode)
2205{
2206 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2207 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2208 {
2209 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
2210 { 0, RT_MAKE_U16(16, 33), /* -> */ 0, X86_EFL_ZF },
2211 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0},
2212 { ~(RTCCUINTXREG)7, RT_MAKE_U16(40, 8), /* -> */ ARCH_BITS == 64 ? 0xff : 0x00, ARCH_BITS == 64 ? 0 : X86_EFL_ZF },
2213 };
2214
2215 /* 32-bit register width */
2216 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2217 {
2218 { 0, RT_MAKE_U16(0, 0), /* -> */ 0, X86_EFL_ZF },
2219 { 0, RT_MAKE_U16(16, 18), /* -> */ 0, X86_EFL_ZF },
2220 { ~(RTCCUINTXREG)7, RT_MAKE_U16(2, 4), /* -> */ 0xe, 0 },
2221 { ~(RTCCUINTXREG)7, RT_MAKE_U16(24, 8), /* -> */ 0xff, 0 },
2222 { ~(RTCCUINTXREG)7, RT_MAKE_U16(31, 9), /* -> */ 1, 0 },
2223 { ~(RTCCUINTXREG)7, RT_MAKE_U16(42, 8), /* -> */ 0, X86_EFL_ZF },
2224 };
2225
2226 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2227 {
2228 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2229 { BS3_CMN_NM(bs3CpuInstr2_bextr_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2230 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2231 { BS3_CMN_NM(bs3CpuInstr2_bextr_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2232 };
2233 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2234 X86_EFL_STATUS_BITS, X86_EFL_AF | X86_EFL_SF | X86_EFL_PF);
2235}
2236
2237
2238BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_bzhi)(uint8_t bMode)
2239{
2240 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2241 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2242 {
2243 { 0, 0, /* -> */ 0, X86_EFL_ZF },
2244 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
2245 { 0, 64, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2246 { ~(RTCCUINTXREG)0, 64, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
2247 { ~(RTCCUINTXREG)0, 63,
2248 /* -> */ ARCH_BITS >= 64 ? ~(RTCCUINTXREG)0 >> 1 : ~(RTCCUINTXREG)0, ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
2249 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 24, /* -> */ UINT32_C(0x00849607), 0 },
2250 { ~(RTCCUINTXREG)0 << 31 | UINT32_C(0x63849607), 33,
2251 /* -> */ ARCH_BITS >= 64 ? UINT64_C(0x1e3849607) : UINT32_C(0xe3849607), ARCH_BITS >= 64 ? 0 : X86_EFL_CF | X86_EFL_SF },
2252 };
2253
2254 /* 32-bit register width */
2255 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2256 {
2257 { 0, 0, /* -> */ 0, X86_EFL_ZF },
2258 { 0, ~(RTCCUINTXREG)255, /* -> */ 0, X86_EFL_ZF },
2259 { 0, 32, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2260 { ~(RTCCUINTXREG)0, 32, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
2261 { ~(RTCCUINTXREG)0, 31, /* -> */ UINT32_MAX >> 1, 0 },
2262 { UINT32_C(0x1230fd34), 15, /* -> */ UINT32_C(0x00007d34), 0 },
2263 };
2264
2265 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2266 {
2267 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2268 { BS3_CMN_NM(bs3CpuInstr2_bzhi_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2269 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2270 { BS3_CMN_NM(bs3CpuInstr2_bzhi_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2271 };
2272 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2,
2273 X86_EFL_STATUS_BITS, 0);
2274}
2275
2276
2277/** @note This is a Gy_By_Ey format instruction, so we're switching the two
2278 * source registers around when calling bs3CpuInstr2_Common_Gy_Ey_By.
2279 * Sorry for the confusion, but it saves some unnecessary code dup. */
2280BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pdep)(uint8_t bMode)
2281{
2282 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2283 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2284 { /* Mask (RBX/[FS:xBX]), source=RCX */
2285 { 0, 0, /* -> */ 0, 0 },
2286 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2287 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2288 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
2289#if ARCH_BITS >= 64
2290 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x3586049947589201), 0 },
2291 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x3586049947588000), 0 },
2292#endif
2293 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
2294 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x47588000), 0 },
2295 };
2296
2297 /* 32-bit register width */
2298 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2299 { /* Mask (EBX/[FS:xBX]), source=ECX */
2300 { 0, 0, /* -> */ 0, 0 },
2301 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2302 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2303 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
2304 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x01010101), 0 },
2305 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x01010000), 0 },
2306 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x47589201), 0 },
2307 };
2308
2309 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2310 {
2311 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2312 { BS3_CMN_NM(bs3CpuInstr2_pdep_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2313 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2314 { BS3_CMN_NM(bs3CpuInstr2_pdep_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2315 };
2316 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
2317}
2318
2319
2320/** @note Same note as for bs3CpuInstr2_pdep */
2321BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_pext)(uint8_t bMode)
2322{
2323 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2324 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2325 { /* Mask (RBX/[FS:xBX]), source=RCX */
2326 { 0, 0, /* -> */ 0, 0 },
2327 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2328 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2329 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)0, 0 },
2330#if ARCH_BITS >= 64
2331 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)0, /* -> */ UINT64_C(0x00000000007fffff), 0 },
2332 { UINT64_C(0x3586049947589201), ~(RTCCUINTXREG)7, /* -> */ UINT64_C(0x00000000007ffffe), 0 },
2333#endif
2334 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
2335 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
2336 };
2337
2338 /* 32-bit register width */
2339 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2340 { /* Mask (EBX/[FS:xBX]), source=ECX */
2341 { 0, 0, /* -> */ 0, 0 },
2342 { 0, ~(RTCCUINTXREG)0, /* -> */ 0, 0 },
2343 { ~(RTCCUINTXREG)0, 0, /* -> */ 0, 0 },
2344 { ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ UINT32_MAX, 0 },
2345 { UINT32_C(0x01010101), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x0000000f), 0 },
2346 { UINT32_C(0x01010101), ~(RTCCUINTXREG)3, /* -> */ UINT32_C(0x0000000e), 0 },
2347 { UINT32_C(0x47589201), ~(RTCCUINTXREG)0, /* -> */ UINT32_C(0x000007ff), 0 },
2348 { UINT32_C(0x47589201), ~(RTCCUINTXREG)7, /* -> */ UINT32_C(0x000007fe), 0 },
2349 };
2350
2351 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2352 {
2353 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2354 { BS3_CMN_NM(bs3CpuInstr2_pext_RAX_RCX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2355 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2356 { BS3_CMN_NM(bs3CpuInstr2_pext_EAX_ECX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2357 };
2358 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI2, 0, 0);
2359}
2360
2361
2362BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shlx)(uint8_t bMode)
2363{
2364 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2365 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2366 {
2367 { 0, 0, /* -> */ 0, 0 },
2368 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2369 { ~(RTCCUINTXREG)7, 8, /* -> */ ~(RTCCUINTXREG)0x7ff, 0},
2370 { ~(RTCCUINTXREG)7, 40, /* -> */ ~(RTCCUINTXREG)7 << (ARCH_BITS == 64 ? 40 : 8), 0 },
2371 { ~(RTCCUINTXREG)7, 72, /* -> */ ~(RTCCUINTXREG)7 << 8, 0 },
2372 };
2373
2374 /* 32-bit register width */
2375 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2376 {
2377 { 0, 0, /* -> */ 0, 0 },
2378 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2379 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
2380 { ~(RTCCUINTXREG)7, 8, /* -> */ UINT32_C(0xfffff800), 0 },
2381 };
2382
2383 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2384 {
2385 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2386 { BS3_CMN_NM(bs3CpuInstr2_shlx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2387 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2388 { BS3_CMN_NM(bs3CpuInstr2_shlx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2389 };
2390 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2391 0, 0);
2392}
2393
2394
2395BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_sarx)(uint8_t bMode)
2396{
2397 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2398 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2399 {
2400 { 0, 0, /* -> */ 0, 0 },
2401 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2402 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ ~(RTCCUINTXREG)0, 0 },
2403 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ ~(RTCCUINTXREG)0, 0 },
2404 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
2405 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
2406 };
2407
2408 /* 32-bit register width */
2409 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2410 {
2411 { 0, 0, /* -> */ 0, 0 },
2412 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2413 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0xffffff80), 0 },
2414 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0xffffff80), 0 },
2415 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
2416 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
2417 };
2418
2419 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2420 {
2421 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2422 { BS3_CMN_NM(bs3CpuInstr2_sarx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2423 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2424 { BS3_CMN_NM(bs3CpuInstr2_sarx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2425 };
2426 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2427 0, 0);
2428}
2429
2430
2431BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_shrx)(uint8_t bMode)
2432{
2433 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2434 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests64[] =
2435 {
2436 { 0, 0, /* -> */ 0, 0 },
2437 { 0, ~(RTCCUINTXREG)3, /* -> */ 0, 0 },
2438 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1, /* -> */ 1, 0 },
2439 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 1), RTCCINTXREG_BITS - 1 + 64, /* -> */ 1, 0 },
2440 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3, /* -> */ 2, 0 },
2441 { (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), RTCCINTXREG_BITS - 3 + 64, /* -> */ 2, 0 },
2442 };
2443
2444 /* 32-bit register width */
2445 static BS3CPUINSTR2_SUBTEST_Gy_Ey_By_T const s_aSubTests32[] =
2446 {
2447 { 0, 0, /* -> */ 0, 0 },
2448 { 0, ~(RTCCUINTXREG)9, /* -> */ 0, 0 },
2449 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24, /* -> */ UINT32_C(0x80), 0 },
2450 { ~(RTCCUINTXREG)UINT32_C(0x7fffffff), 24+32, /* -> */ UINT32_C(0x80), 0 },
2451 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24, /* -> */ UINT32_C(0x40), 0 },
2452 { ~(RTCCUINTXREG)UINT32_C(0xbfffffff), 24+32, /* -> */ UINT32_C(0x40), 0 },
2453 };
2454
2455 static BS3CPUINSTR2_TEST_Gy_Ey_By_T const s_aTests[] =
2456 {
2457 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_RBX_RCX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2458 { BS3_CMN_NM(bs3CpuInstr2_shrx_RAX_FSxBX_RCX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2459 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_EBX_ECX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2460 { BS3_CMN_NM(bs3CpuInstr2_shrx_EAX_FSxBX_ECX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2461 };
2462 return bs3CpuInstr2_Common_Gy_Ey_By(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2463 0, 0);
2464}
2465
2466
2467/*
2468 * For testing BLSR, BLSMSK, and BLSI.
2469 */
2470typedef struct BS3CPUINSTR2_SUBTEST_By_Ey_T
2471{
2472 RTCCUINTXREG uSrc;
2473 RTCCUINTXREG uDst;
2474 uint16_t fEflOut;
2475} BS3CPUINSTR2_SUBTEST_By_Ey_T;
2476
2477typedef struct BS3CPUINSTR2_TEST_By_Ey_T
2478{
2479 FPFNBS3FAR pfnWorker;
2480 bool fMemSrc;
2481 uint8_t cbInstr;
2482 uint8_t cSubTests;
2483 BS3CPUINSTR2_SUBTEST_By_Ey_T const *paSubTests;
2484} BS3CPUINSTR2_TEST_By_Ey_T;
2485
2486static uint8_t bs3CpuInstr2_Common_By_Ey(uint8_t bMode, BS3CPUINSTR2_TEST_By_Ey_T const *paTests, unsigned cTests,
2487 uint32_t fStdExtFeatEbx, uint16_t fEflCheck, uint16_t fEflIgnore)
2488{
2489 BS3REGCTX Ctx;
2490 BS3TRAPFRAME TrapFrame;
2491 unsigned i, j, k;
2492 uint32_t uStdExtFeatEbx = 0;
2493 bool fSupportsInstr;
2494
2495 fEflCheck &= ~fEflIgnore;
2496
2497 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2498 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2499 fSupportsInstr = RT_BOOL(uStdExtFeatEbx & fStdExtFeatEbx);
2500
2501 /* Ensure the structures are allocated before we sample the stack pointer. */
2502 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2503 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2504
2505 /*
2506 * Create test context.
2507 */
2508 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2509
2510 /*
2511 * Do the tests twice, first with all flags set, then once again with
2512 * flags cleared. The flags are not supposed to be touched at all.
2513 */
2514 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2515 for (j = 0; j < 2; j++)
2516 {
2517 for (i = 0; i < cTests; i++)
2518 {
2519 for (k = 0; k < paTests[i].cSubTests; k++)
2520 {
2521 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsInstr;
2522 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2523 uint64_t uExpectRax, uExpectRip;
2524 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2525
2526 Ctx.rax.uCcXReg = ~paTests[i].paSubTests[k].uSrc ^ 0x593e7591;
2527 if (!paTests[i].fMemSrc)
2528 {
2529 Ctx.rbx.uCcXReg = paTests[i].paSubTests[k].uSrc;
2530 uMemSrcExpect = uMemSrc = ~paTests[i].paSubTests[k].uSrc;
2531 }
2532 else
2533 {
2534 uMemSrcExpect = uMemSrc = paTests[i].paSubTests[k].uSrc;
2535 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2536 }
2537 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paTests[i].pfnWorker);
2538 uExpectRax = fOkay ? paTests[i].paSubTests[k].uDst : Ctx.rax.u;
2539 uExpectRip = Ctx.rip.u + (fOkay ? paTests[i].cbInstr + 1 : 0);
2540 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2541
2542 if ( TrapFrame.bXcpt != bExpectXcpt
2543 || TrapFrame.Ctx.rip.u != uExpectRip
2544 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2545 || TrapFrame.Ctx.rax.u != uExpectRax
2546 /* check that nothing else really changed: */
2547 || (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2548 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck)
2549 || (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2550 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2551 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2552 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2553 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2554 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2555 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2556 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2557 || uMemSrc != uMemSrcExpect
2558 )
2559 {
2560 Bs3TestFailedF("test #%i/%i failed: input %#" RTCCUINTXREG_XFMT,
2561 i, k, paTests[i].paSubTests[k].uSrc);
2562 if (TrapFrame.bXcpt != bExpectXcpt)
2563 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2564 if (TrapFrame.Ctx.rip.u != uExpectRip)
2565 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2566 if (TrapFrame.Ctx.rax.u != uExpectRax)
2567 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2568 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2569 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2570 if ( (TrapFrame.Ctx.rflags.u16 & fEflCheck)
2571 != ((fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck))
2572 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (output)",
2573 (fOkay ? paTests[i].paSubTests[k].fEflOut : Ctx.rflags.u16) & fEflCheck,
2574 TrapFrame.Ctx.rflags.u16 & fEflCheck);
2575 if ( (TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS)
2576 != (Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS))
2577 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2578 Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS,
2579 TrapFrame.Ctx.rflags.u16 & ~(fEflCheck | fEflIgnore) & X86_EFL_STATUS_BITS);
2580
2581 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
2582 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
2583 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2584 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2585 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2586 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2587 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2588 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2589 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2590 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2591 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2592 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2593 if (uMemSrc != uMemSrcExpect)
2594 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
2595 }
2596 }
2597 }
2598 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2599 }
2600
2601 return 0;
2602}
2603
2604
2605BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsr)(uint8_t bMode)
2606{
2607 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2608 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2609 {
2610 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2611 { 1, /* -> */ 0, X86_EFL_ZF },
2612 { 2, /* -> */ 0, X86_EFL_ZF },
2613 { 3, /* -> */ 2, 0 },
2614 { 5, /* -> */ 4, 0 },
2615 { 6, /* -> */ 4, 0 },
2616 { 7, /* -> */ 6, 0 },
2617 { 9, /* -> */ 8, 0 },
2618 { 10, /* -> */ 8, 0 },
2619 { ~(RTCCUINTXREG)1, /* -> */ ~(RTCCUINTXREG)3, X86_EFL_SF },
2620 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2), X86_EFL_SF },
2621 };
2622
2623 /* 32-bit register width */
2624 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2625 {
2626 { 0, /* -> */ 0, X86_EFL_ZF | X86_EFL_CF },
2627 { 1, /* -> */ 0, X86_EFL_ZF },
2628 { ~(RTCCUINTXREG)1, /* -> */ UINT32_C(0xfffffffc), X86_EFL_SF },
2629 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x80000000), X86_EFL_SF },
2630 };
2631
2632 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2633 {
2634 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2635 { BS3_CMN_NM(bs3CpuInstr2_blsr_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2636 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2637 { BS3_CMN_NM(bs3CpuInstr2_blsr_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2638 };
2639 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2640 X86_EFL_STATUS_BITS, 0);
2641}
2642
2643
2644BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsmsk)(uint8_t bMode)
2645{
2646 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2647 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2648 {
2649 { 0, /* -> */ ~(RTCCUINTXREG)0, X86_EFL_CF | X86_EFL_SF },
2650 { 1, /* -> */ 1, 0 },
2651 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2652 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ ~((RTCCUINTXREG)2 << (RTCCINTXREG_BITS - 2)), 0 },
2653 };
2654
2655 /* 32-bit register width */
2656 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2657 {
2658 { 0, /* -> */ UINT32_MAX, X86_EFL_CF | X86_EFL_SF },
2659 { 1, /* -> */ 1, 0 },
2660 { ~(RTCCUINTXREG)1, /* -> */ 3, 0 },
2661 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x7fffffff), 0},
2662 };
2663
2664 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2665 {
2666 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2667 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2668 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2669 { BS3_CMN_NM(bs3CpuInstr2_blsmsk_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2670 };
2671 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2672 X86_EFL_STATUS_BITS, 0);
2673}
2674
2675
2676BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_blsi)(uint8_t bMode)
2677{
2678 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2679 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests64[] =
2680 {
2681 { 0, /* -> */ 0, X86_EFL_ZF },
2682 { 1, /* -> */ 1, X86_EFL_CF },
2683 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2684 { (RTCCUINTXREG)3 << (RTCCINTXREG_BITS - 2), /* -> */ (RTCCUINTXREG)1 << (RTCCINTXREG_BITS - 2), X86_EFL_CF },
2685 };
2686
2687 /* 32-bit register width */
2688 static BS3CPUINSTR2_SUBTEST_By_Ey_T const s_aSubTests32[] =
2689 {
2690 { 0, /* -> */ 0, X86_EFL_ZF },
2691 { 1, /* -> */ 1, X86_EFL_CF },
2692 { ~(RTCCUINTXREG)1, /* -> */ 2, X86_EFL_CF },
2693 { ~(RTCCUINTXREG)0 << 30, /* -> */ UINT32_C(0x40000000), X86_EFL_CF },
2694 };
2695
2696 static BS3CPUINSTR2_TEST_By_Ey_T const s_aTests[] =
2697 {
2698 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_RBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2699 { BS3_CMN_NM(bs3CpuInstr2_blsi_RAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests64), s_aSubTests64 },
2700 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_EBX_icebp), false, 5, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2701 { BS3_CMN_NM(bs3CpuInstr2_blsi_EAX_FSxBX_icebp), true, 6, RT_ELEMENTS(s_aSubTests32), s_aSubTests32 },
2702 };
2703 return bs3CpuInstr2_Common_By_Ey(bMode, s_aTests, RT_ELEMENTS(s_aTests), X86_CPUID_STEXT_FEATURE_EBX_BMI1,
2704 X86_EFL_STATUS_BITS, 0);
2705}
2706
2707
2708/*
2709 * MULX (BMI2) - destination registers (/r & vvvv) = r/m * rDX
2710 */
2711BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mulx)(uint8_t bMode)
2712{
2713 static const struct
2714 {
2715 FPFNBS3FAR pfnWorker;
2716 bool fMemSrc;
2717 bool fSameDst;
2718 uint8_t cbInstr;
2719 RTCCUINTXREG uSrc1;
2720 RTCCUINTXREG uSrc2;
2721 RTCCUINTXREG uDst1;
2722 RTCCUINTXREG uDst2;
2723 } s_aTests[] =
2724 {
2725 /* 64 bits register width (32 bits in 32- and 16-bit modes): */
2726 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #0
2727 0, 0, /* -> */ 0, 0 },
2728 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #1
2729 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2730 { BS3_CMN_NM(bs3CpuInstr2_mulx_RCX_RCX_RBX_RDX_icebp), false, true, 5, // #2
2731 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, ~(RTCCUINTXREG)1 },
2732 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #3
2733 2, 2, /* -> */ 0, 4 },
2734 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_RBX_RDX_icebp), false, false, 5, // #4
2735 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2736
2737 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #5
2738 0, 0, /* -> */ 0, 0 },
2739 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #6
2740 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(RTCCUINTXREG)1, 1 },
2741 { BS3_CMN_NM(bs3CpuInstr2_mulx_RAX_RCX_FSxBX_RDX_icebp), true, false, 6, // #7
2742 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(RTCCUINTXREG)41 },
2743
2744 /* 32-bit register width */
2745 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #8
2746 0, 0, /* -> */ 0, 0 },
2747 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #9
2748 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2749 { BS3_CMN_NM(bs3CpuInstr2_mulx_ECX_ECX_EBX_EDX_icebp), false, true, 5, // #10
2750 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, ~(uint32_t)1 },
2751 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #11
2752 2, 2, /* -> */ 0, 4 },
2753 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_EBX_EDX_icebp), false, false, 5, // #12
2754 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2755
2756 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #13
2757 0, 0, /* -> */ 0, 0 },
2758 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #14
2759 ~(RTCCUINTXREG)0, ~(RTCCUINTXREG)0, /* -> */ ~(uint32_t)1, 1 },
2760 { BS3_CMN_NM(bs3CpuInstr2_mulx_EAX_ECX_FSxBX_EDX_icebp), true, false, 6, // #15
2761 ~(RTCCUINTXREG)0, 42, /* -> */ 0x29, ~(uint32_t)41 },
2762 };
2763
2764 BS3REGCTX Ctx;
2765 BS3TRAPFRAME TrapFrame;
2766 unsigned i, j;
2767 uint32_t uStdExtFeatEbx = 0;
2768 bool fSupportsAndN;
2769
2770 if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2771 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &uStdExtFeatEbx, NULL, NULL);
2772 fSupportsAndN = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_BMI2);
2773
2774 /* Ensure the structures are allocated before we sample the stack pointer. */
2775 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2776 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2777
2778 /*
2779 * Create test context.
2780 */
2781 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2782
2783 /*
2784 * Do the tests twice, first with all flags set, then once again with
2785 * flags cleared. The flags are not supposed to be touched at all.
2786 */
2787 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2788 for (j = 0; j < 2; j++)
2789 {
2790 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2791 {
2792 bool const fOkay = !BS3_MODE_IS_RM_OR_V86(bMode) && fSupportsAndN;
2793 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2794 uint64_t uExpectRax, uExpectRcx, uExpectRip;
2795 RTCCUINTXREG uMemSrc1, uMemSrc1Expect;
2796
2797 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2798 Ctx.rcx.uCcXReg = RTCCUINTXREG_MAX * 4095;
2799 Ctx.rdx.uCcXReg = s_aTests[i].uSrc2;
2800 if (!s_aTests[i].fMemSrc)
2801 {
2802 Ctx.rbx.uCcXReg = s_aTests[i].uSrc1;
2803 uMemSrc1Expect = uMemSrc1 = ~s_aTests[i].uSrc1;
2804 }
2805 else
2806 {
2807 uMemSrc1Expect = uMemSrc1 = s_aTests[i].uSrc1;
2808 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc1);
2809 }
2810 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2811 uExpectRax = fOkay && !s_aTests[i].fSameDst ? s_aTests[i].uDst1 : Ctx.rax.u;
2812 uExpectRcx = fOkay ? s_aTests[i].uDst2 : Ctx.rcx.u;
2813 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2814 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2815
2816 if ( TrapFrame.bXcpt != bExpectXcpt
2817 || TrapFrame.Ctx.rip.u != uExpectRip
2818 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2819 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2820 || TrapFrame.Ctx.rax.u != uExpectRax
2821 || TrapFrame.Ctx.rcx.u != uExpectRcx
2822 /* check that nothing else really changed: */
2823 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS)
2824 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2825 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2826 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2827 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2828 || uMemSrc1 != uMemSrc1Expect
2829 )
2830 {
2831 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT ", %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc1, s_aTests[i].uSrc2);
2832 if (TrapFrame.bXcpt != bExpectXcpt)
2833 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2834 if (TrapFrame.Ctx.rip.u != uExpectRip)
2835 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2836 if (TrapFrame.Ctx.rax.u != uExpectRax)
2837 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2838 if (TrapFrame.Ctx.rcx.u != uExpectRcx)
2839 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", uExpectRcx, TrapFrame.Ctx.rcx.u);
2840 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2841 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2842 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
2843 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
2844
2845 if ( (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (Ctx.rflags.u16 & X86_EFL_STATUS_BITS))
2846 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32 (immutable)",
2847 Ctx.rflags.u16 & X86_EFL_STATUS_BITS, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
2848 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
2849 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
2850 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
2851 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
2852 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
2853 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
2854 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
2855 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
2856 if (uMemSrc1 != uMemSrc1Expect)
2857 Bs3TestFailedF("Expected uMemSrc1 = %#06RX64, got %#06RX64", (uint64_t)uMemSrc1Expect, (uint64_t)uMemSrc1);
2858 }
2859 }
2860 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
2861 }
2862
2863 return 0;
2864}
2865
2866
2867/*
2868 * POPCNT - Intel: POPCNT; AMD: ABM.
2869 */
2870BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_popcnt)(uint8_t bMode)
2871{
2872 static const struct
2873 {
2874 FPFNBS3FAR pfnWorker;
2875 bool fMemSrc;
2876 uint8_t cWidth;
2877 uint8_t cbInstr;
2878 RTCCUINTXREG uSrc;
2879 RTCCUINTXREG uDst;
2880 uint16_t fEFlags;
2881 } s_aTests[] =
2882 {
2883 /* 16-bit register width */
2884 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #0
2885 0, /* -> */ 0, X86_EFL_ZF },
2886 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #1
2887 ~(RTCCUINTXREG)0, /* -> */ 16, 0 },
2888 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #2
2889 UINT16_C(0xffff), /* -> */ 16, 0 },
2890 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_BX_icebp), false, 16, 4 + (ARCH_BITS != 16), // #3
2891 UINT16_C(0x0304), /* -> */ 3, 0 },
2892 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #4
2893 UINT16_C(0xd569), /* -> */ 9, 0},
2894 { BS3_CMN_NM(bs3CpuInstr2_popcnt_AX_FSxBX_icebp), true, 16, 5 + (ARCH_BITS != 16), // #5
2895 0, /* -> */ 0, X86_EFL_ZF },
2896
2897 /* 32-bit register width */
2898 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #6
2899 0, /* -> */ 0, X86_EFL_ZF },
2900 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #7
2901 ~(RTCCUINTXREG)0, /* -> */ 32, 0},
2902 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_EBX_icebp), false, 32, 4 + (ARCH_BITS == 16), // #8
2903 UINT32_C(0x01020304), /* -> */ 5, 0},
2904 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #9
2905 0, /* -> */ 0, X86_EFL_ZF },
2906 { BS3_CMN_NM(bs3CpuInstr2_popcnt_EAX_FSxBX_icebp), true, 32, 5 + (ARCH_BITS == 16), // #10
2907 UINT32_C(0x49760948), /* -> */ 12, 0 },
2908
2909#if ARCH_BITS == 64
2910 /* 64-bit register width */
2911 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #11
2912 0, /* -> */ 0, X86_EFL_ZF },
2913 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #12
2914 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2915 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_RBX_icebp), false, 64, 5, // #13
2916 UINT64_C(0x1234123412341234), /* -> */ 5*4, 0 },
2917 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #14
2918 0, /* -> */ 0, X86_EFL_ZF },
2919 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #15
2920 ~(RTCCUINTXREG)0, /* -> */ 64, 0 },
2921 { BS3_CMN_NM(bs3CpuInstr2_popcnt_RAX_FSxBX_icebp), true, 64, 6, // #16
2922 UINT64_C(0x5908760293769087), /* -> */ 26, 0 },
2923#endif
2924 };
2925
2926 BS3REGCTX Ctx;
2927 BS3TRAPFRAME TrapFrame;
2928 unsigned i, j;
2929 bool const fSupportsPopCnt = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
2930 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_POPCNT);
2931
2932 /* Ensure the structures are allocated before we sample the stack pointer. */
2933 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
2934 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
2935
2936 /*
2937 * Create test context.
2938 */
2939 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
2940
2941 /*
2942 * Do the tests twice, first with all flags set, then once again with
2943 * flags cleared. The flags are not supposed to be touched at all.
2944 */
2945 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
2946 for (j = 0; j < 2; j++)
2947 {
2948 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
2949 {
2950 bool const fOkay = fSupportsPopCnt;
2951 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
2952 uint64_t uExpectRax, uExpectRip;
2953 RTCCUINTXREG uMemSrc, uMemSrcExpect;
2954
2955 Ctx.rax.uCcXReg = RTCCUINTXREG_MAX * 1019;
2956 if (!s_aTests[i].fMemSrc)
2957 {
2958 Ctx.rbx.uCcXReg = s_aTests[i].uSrc;
2959 uMemSrcExpect = uMemSrc = ~s_aTests[i].uSrc;
2960 }
2961 else
2962 {
2963 uMemSrcExpect = uMemSrc = s_aTests[i].uSrc;
2964 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
2965 }
2966 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
2967 uExpectRax = fOkay ? s_aTests[i].uDst : Ctx.rax.u;
2968 if (s_aTests[i].cWidth == 16)
2969 uExpectRax = (uExpectRax & UINT16_MAX) | (Ctx.rax.u & ~(uint64_t)UINT16_MAX);
2970
2971 uExpectRip = Ctx.rip.u + (fOkay ? s_aTests[i].cbInstr + 1 : 0);
2972 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
2973
2974 if ( TrapFrame.bXcpt != bExpectXcpt
2975 || TrapFrame.Ctx.rip.u != uExpectRip
2976 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
2977 || TrapFrame.Ctx.rax.u != uExpectRax
2978 || (TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16)
2979 /* check that nothing else really changed: */
2980 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
2981 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
2982 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
2983 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
2984 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
2985 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
2986 || uMemSrc != uMemSrcExpect
2987 )
2988 {
2989 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTXREG_XFMT, i, s_aTests[i].uSrc);
2990 if (TrapFrame.bXcpt != bExpectXcpt)
2991 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
2992 if (TrapFrame.Ctx.rip.u != uExpectRip)
2993 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
2994 if (TrapFrame.Ctx.rax.u != uExpectRax)
2995 Bs3TestFailedF("Expected RAX = %#06RX64, got %#06RX64", uExpectRax, TrapFrame.Ctx.rax.u);
2996 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
2997 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
2998 if ((TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS) != (fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16))
2999 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32",
3000 fOkay ? s_aTests[i].fEFlags : Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16 & X86_EFL_STATUS_BITS);
3001
3002 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3003 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3004 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3005 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3006 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3007 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3008 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3009 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3010 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3011 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3012 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3013 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3014 if (uMemSrc != uMemSrcExpect)
3015 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3016 }
3017 }
3018 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3019 }
3020
3021 return 0;
3022}
3023
3024/*
3025 * CRC32 - SSE4.2
3026 */
3027BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_crc32)(uint8_t bMode)
3028{
3029 typedef struct BS3CPUINSTR2_CRC32_VALUES_T
3030 {
3031 uint32_t uDstIn;
3032 uint32_t uDstOut;
3033 uint64_t uSrc;
3034 } BS3CPUINSTR2_CRC32_VALUES_T;
3035 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues1[] =
3036 {
3037 { UINT32_C(0000000000), UINT32_C(0000000000), UINT8_C(0000) },
3038 { UINT32_C(0xffffffff), UINT32_C(0x25502c8c), UINT8_C(0xea) },
3039 { UINT32_C(0x25502c8c), UINT32_C(0x474224a6), UINT8_C(0xea) },
3040 { UINT32_C(0x474224a6), UINT32_C(0x0c7f9048), UINT8_C(0xea) },
3041 { UINT32_C(0x0c7f9048), UINT32_C(0x39c5b9e0), UINT8_C(0x01) },
3042 { UINT32_C(0x39c5b9e0), UINT32_C(0x2493fabc), UINT8_C(0x04) },
3043 { UINT32_C(0x2493fabc), UINT32_C(0x0b05c4d6), UINT8_C(0x27) },
3044 { UINT32_C(0x0b05c4d6), UINT32_C(0xbe26a561), UINT8_C(0x2a) },
3045 { UINT32_C(0xbe26a561), UINT32_C(0xe1855652), UINT8_C(0x63) },
3046 { UINT32_C(0xe1855652), UINT32_C(0xc67efe3f), UINT8_C(0xa7) },
3047 { UINT32_C(0xc67efe3f), UINT32_C(0x227028cd), UINT8_C(0xfd) },
3048 { UINT32_C(0x227028cd), UINT32_C(0xf4559a1d), UINT8_C(0xea) },
3049 };
3050 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues2[] =
3051 {
3052 { UINT32_C(0000000000), UINT32_C(0000000000), UINT16_C(000000) },
3053 { UINT32_C(0xffffffff), UINT32_C(0xd550e2a0), UINT16_C(0x04d2) },
3054 { UINT32_C(0xd550e2a0), UINT32_C(0x38e07a0a), UINT16_C(0xe8cc) },
3055 { UINT32_C(0x38e07a0a), UINT32_C(0x60ebd519), UINT16_C(0x82a2) },
3056 { UINT32_C(0x60ebd519), UINT32_C(0xaaa127b5), UINT16_C(0x0fff) },
3057 { UINT32_C(0xaaa127b5), UINT32_C(0xb13175c6), UINT16_C(0x00ff) },
3058 { UINT32_C(0xb13175c6), UINT32_C(0x3a226f1b), UINT16_C(0x0300) },
3059 { UINT32_C(0x3a226f1b), UINT32_C(0xbaedef0c), UINT16_C(0x270f) },
3060 { UINT32_C(0xbaedef0c), UINT32_C(0x2d18866e), UINT16_C(0x3ff6) },
3061 { UINT32_C(0x2d18866e), UINT32_C(0x07e2e954), UINT16_C(0x9316) },
3062 { UINT32_C(0x07e2e954), UINT32_C(0x95f82acb), UINT16_C(0xa59c) },
3063 };
3064 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues4[] =
3065 {
3066 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000) },
3067 { UINT32_C(0xffffffff), UINT32_C(0xc9a7250e), UINT32_C(0x0270fa68) },
3068 { UINT32_C(0xc9a7250e), UINT32_C(0x7340d175), UINT32_C(0x23729736) },
3069 { UINT32_C(0x7340d175), UINT32_C(0x7e17b67d), UINT32_C(0x8bc75d35) },
3070 { UINT32_C(0x7e17b67d), UINT32_C(0x5028eb71), UINT32_C(0x0e9bebf2) },
3071 { UINT32_C(0x5028eb71), UINT32_C(0xc0a7f45a), UINT32_C(0x000001bc) },
3072 { UINT32_C(0xc0a7f45a), UINT32_C(0xa96f4012), UINT32_C(0x0034ba02) },
3073 { UINT32_C(0xa96f4012), UINT32_C(0xb27c0718), UINT32_C(0x0000002a) },
3074 { UINT32_C(0xb27c0718), UINT32_C(0x79fb2d35), UINT32_C(0x0153158e) },
3075 { UINT32_C(0x79fb2d35), UINT32_C(0x23434fc9), UINT32_C(0x02594882) },
3076 { UINT32_C(0x23434fc9), UINT32_C(0x354bf3b6), UINT32_C(0xb230b8f3) },
3077 };
3078#if ARCH_BITS >= 64
3079 static const BS3CPUINSTR2_CRC32_VALUES_T s_aValues8[] =
3080 {
3081 { UINT32_C(0000000000), UINT32_C(0000000000), UINT64_C(000000000000000000) },
3082 { UINT32_C(0xffffffff), UINT32_C(0xadc36834), UINT64_C(0x02b0b5e2a975c1cc) },
3083 { UINT32_C(0xadc36834), UINT32_C(0xf0e893c9), UINT64_C(0x823d386bf7517583) },
3084 { UINT32_C(0xf0e893c9), UINT32_C(0x1a22a837), UINT64_C(0x0481f5311fa061d0) },
3085 { UINT32_C(0x1a22a837), UINT32_C(0xcf8b6d61), UINT64_C(0x13fa70f64d52a92d) },
3086 { UINT32_C(0xcf8b6d61), UINT32_C(0xc7dde203), UINT64_C(0x3ccc8b035903d3e1) },
3087 { UINT32_C(0xc7dde203), UINT32_C(0xd42b5823), UINT64_C(0x0000011850ec2fac) },
3088 { UINT32_C(0xd42b5823), UINT32_C(0x8b1ce49e), UINT64_C(0x0000000000001364) },
3089 { UINT32_C(0x8b1ce49e), UINT32_C(0x1af31710), UINT64_C(0x000000057840205a) },
3090 { UINT32_C(0x1af31710), UINT32_C(0xdea35e8b), UINT64_C(0x2e5d93688d9a0bfa) },
3091 { UINT32_C(0xdea35e8b), UINT32_C(0x594c013a), UINT64_C(0x8ac7230489e7ffff) },
3092 { UINT32_C(0x594c013a), UINT32_C(0x27b061e5), UINT64_C(0x6bf037ae325f1c71) },
3093 { UINT32_C(0x27b061e5), UINT32_C(0x3120b5f7), UINT64_C(0x0fffffff34503556) },
3094 };
3095#endif
3096 static const struct
3097 {
3098 FPFNBS3FAR pfnWorker;
3099 bool fMemSrc;
3100 uint8_t cbOp;
3101 uint8_t cValues;
3102 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues;
3103 } s_aTests[] =
3104 {
3105 /* 8-bit register width */
3106 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BL_icebp), false, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
3107 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_byte_FSxBX_icebp), true, 1, RT_ELEMENTS(s_aValues1), s_aValues1 },
3108
3109 /* 16-bit register width */
3110 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_BX_icebp), false, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
3111 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_word_FSxBX_icebp), true, 2, RT_ELEMENTS(s_aValues2), s_aValues2 },
3112
3113 /* 32-bit register width */
3114 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
3115 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4 },
3116#if ARCH_BITS >= 64
3117 /* 32-bit register width */
3118 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
3119 { BS3_CMN_NM(bs3CpuInstr2_crc32_EAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8 },
3120#endif
3121 };
3122
3123 BS3REGCTX Ctx;
3124 BS3TRAPFRAME TrapFrame;
3125 unsigned i, j;
3126 bool const fSupportsCrc32 = (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3127 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_SSE4_2);
3128
3129 /* Ensure the structures are allocated before we sample the stack pointer. */
3130 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3131 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3132
3133 /*
3134 * Create test context.
3135 */
3136 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3137
3138 /*
3139 * Do the tests twice, first with all flags set, then once again with
3140 * flags cleared. The flags are not supposed to be touched at all.
3141 */
3142 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3143 for (j = 0; j < 2; j++)
3144 {
3145 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3146 {
3147 uint8_t const cbOp = s_aTests[i].cbOp;
3148 unsigned const cValues = s_aTests[i].cValues;
3149 BS3CPUINSTR2_CRC32_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3150 unsigned iValue;
3151 bool const fOkay = fSupportsCrc32;
3152 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3153 uint64_t const uSrcGarbage = ( cbOp == 1 ? UINT64_C(0x03948314d0f03400)
3154 : cbOp == 2 ? UINT64_C(0x03948314d0f00000)
3155 : cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
3156 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
3157 uint64_t uExpectRip;
3158
3159 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3160 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3161
3162 for (iValue = 0; iValue < cValues; iValue++)
3163 {
3164 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3165 uint64_t uMemSrc, uMemSrcExpect;
3166
3167 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
3168 if (!s_aTests[i].fMemSrc)
3169 {
3170 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
3171 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
3172 }
3173 else
3174 {
3175 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
3176 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
3177 }
3178
3179 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3180
3181 if ( TrapFrame.bXcpt != bExpectXcpt
3182 || TrapFrame.Ctx.rip.u != uExpectRip
3183 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
3184 || TrapFrame.Ctx.rax.u != uExpectRax
3185 /* check that nothing else really changed: */
3186 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
3187 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
3188 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
3189 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
3190 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
3191 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
3192 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
3193 || uMemSrc != uMemSrcExpect
3194 )
3195 {
3196 Bs3TestFailedF("test #%i value #%i failed: input %#RX32, %#RX64",
3197 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
3198 if (TrapFrame.bXcpt != bExpectXcpt)
3199 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
3200 if (TrapFrame.Ctx.rip.u != uExpectRip)
3201 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
3202 if (TrapFrame.Ctx.rax.u != uExpectRax)
3203 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
3204 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
3205 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
3206
3207 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
3208 Bs3TestFailedF("Expected EFLAGS = %#06RX32, got %#06RX32", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
3209 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3210 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3211 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3212 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3213 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3214 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3215 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3216 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3217 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3218 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3219 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3220 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3221 if (uMemSrc != uMemSrcExpect)
3222 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3223 }
3224 }
3225 }
3226 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3227 }
3228
3229 return 0;
3230}
3231
3232#if 0 /* Program for generating CRC32 value sets: */
3233#include <stdio.h>
3234#include <stdint.h>
3235#include <stdlib.h>
3236
3237int main(int argc, char **argv)
3238{
3239 int cbOp = atoi(argv[1]);
3240 uint32_t uBefore = atoi(argv[2]);
3241 int i = 3;
3242 while (i < argc)
3243 {
3244 unsigned long long uValue = strtoull(argv[i], NULL, 0);
3245 uint32_t uAfter = uBefore;
3246 switch (cbOp)
3247 {
3248 case 1:
3249 __asm__ __volatile__("crc32b %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint8_t)uValue));
3250 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT8_C(%#04x) },\n",
3251 uBefore, uAfter, (unsigned)(uint8_t)uValue);
3252 break;
3253 case 2:
3254 __asm__ __volatile__("crc32w %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint16_t)uValue));
3255 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT16_C(%#06x) },\n",
3256 uBefore, uAfter, (unsigned)(uint16_t)uValue);
3257 break;
3258 case 4:
3259 __asm__ __volatile__("crc32l %2, %0" : "=r" (uAfter) : "0" (uAfter), "r" ((uint32_t)uValue));
3260 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT32_C(%#010x) },\n",
3261 uBefore, uAfter, (uint32_t)uValue);
3262 break;
3263 case 8:
3264 {
3265 uint64_t u64After = uBefore;
3266 __asm__ __volatile__("crc32q %2, %0" : "=r" (u64After) : "0" (u64After), "r" (uValue));
3267 uAfter = (uint32_t)u64After;
3268 printf(" { UINT32_C(%#010x), UINT32_C(%#010x), UINT64_C(%#018llx) },\n", uBefore, uAfter, uValue);
3269 break;
3270 }
3271 }
3272
3273 /* next */
3274 uBefore = uAfter;
3275 i++;
3276 }
3277 return 0;
3278}
3279#endif
3280
3281
3282/*
3283 * ADCX/ADOX - ADX
3284 */
3285BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_adcx_adox)(uint8_t bMode)
3286{
3287 typedef struct BS3CPUINSTR2_ADX_VALUES_T
3288 {
3289 uint64_t uDstOut;
3290 uint64_t uDstIn;
3291 uint64_t uSrc;
3292 bool fFlagIn;
3293 bool fFlagOut;
3294 } BS3CPUINSTR2_ADX_VALUES_T;
3295 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues4[] =
3296 {
3297 { UINT32_C(0000000000), UINT32_C(0000000000), UINT32_C(0000000000), false, false },
3298 { UINT32_C(0000000001), UINT32_C(0000000000), UINT32_C(0000000000), true, false },
3299
3300 { UINT32_C(0xfffffffe), UINT32_MAX / 2, UINT32_MAX / 2, false, false },
3301 { UINT32_C(0xffffffff), UINT32_MAX / 2, UINT32_MAX / 2, true, false },
3302
3303 { UINT32_C(0x7ffffffe), UINT32_MAX, UINT32_MAX / 2, false, true },
3304 { UINT32_C(0x7fffffff), UINT32_MAX, UINT32_MAX / 2, true, true },
3305
3306 { UINT32_C(0x7ffffffe), UINT32_MAX / 2, UINT32_MAX, false, true },
3307 { UINT32_C(0x7fffffff), UINT32_MAX / 2, UINT32_MAX, true, true },
3308
3309 { UINT32_C(0xfffffffe), UINT32_MAX, UINT32_MAX, false, true },
3310 { UINT32_C(0xffffffff), UINT32_MAX, UINT32_MAX, true, true },
3311 };
3312#if ARCH_BITS >= 64
3313 static const BS3CPUINSTR2_ADX_VALUES_T s_aValues8[] =
3314 {
3315 { UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), false, false },
3316 { UINT64_C(00000000000000000001), UINT64_C(00000000000000000000), UINT64_C(00000000000000000000), true, false },
3317
3318 { UINT64_C(0xfffffffffffffffe), UINT64_MAX / 2, UINT64_MAX / 2, false, false },
3319 { UINT64_C(0xffffffffffffffff), UINT64_MAX / 2, UINT64_MAX / 2, true, false },
3320
3321 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX, UINT64_MAX / 2, false, true },
3322 { UINT64_C(0x7fffffffffffffff), UINT64_MAX, UINT64_MAX / 2, true, true },
3323
3324 { UINT64_C(0x7ffffffffffffffe), UINT64_MAX / 2, UINT64_MAX, false, true },
3325 { UINT64_C(0x7fffffffffffffff), UINT64_MAX / 2, UINT64_MAX, true, true },
3326
3327 { UINT64_C(0xfffffffffffffffe), UINT64_MAX, UINT64_MAX, false, true },
3328 { UINT64_C(0xffffffffffffffff), UINT64_MAX, UINT64_MAX, true, true },
3329 };
3330#endif
3331 static const struct
3332 {
3333 FPFNBS3FAR pfnWorker;
3334 bool fMemSrc;
3335 uint8_t cbOp;
3336 uint8_t cValues;
3337 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues;
3338 uint32_t fEFlagsMod;
3339 } s_aTests[] =
3340 {
3341 /* 32-bit register width */
3342 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
3343 { BS3_CMN_NM(bs3CpuInstr2_adcx_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_CF },
3344
3345 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_EBX_icebp), false, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
3346 { BS3_CMN_NM(bs3CpuInstr2_adox_EAX_dword_FSxBX_icebp), true, 4, RT_ELEMENTS(s_aValues4), s_aValues4, X86_EFL_OF },
3347#if ARCH_BITS >= 64
3348 /* 64-bit register width */
3349 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
3350 { BS3_CMN_NM(bs3CpuInstr2_adcx_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_CF },
3351
3352 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_RBX_icebp), false, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
3353 { BS3_CMN_NM(bs3CpuInstr2_adox_RAX_qword_FSxBX_icebp), true, 8, RT_ELEMENTS(s_aValues8), s_aValues8, X86_EFL_OF },
3354#endif
3355 };
3356
3357 BS3REGCTX Ctx;
3358 BS3TRAPFRAME TrapFrame;
3359 unsigned i, j;
3360 bool fSupportsAdx = false;
3361
3362 if ( (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3363 && ASMCpuId_EAX(0) >= 7)
3364 {
3365 uint32_t fEbx = 0;
3366 ASMCpuIdExSlow(7, 0, 0, 0, NULL, &fEbx, NULL, NULL);
3367 fSupportsAdx = RT_BOOL(fEbx & X86_CPUID_STEXT_FEATURE_EBX_ADX);
3368 }
3369
3370 /* Ensure the structures are allocated before we sample the stack pointer. */
3371 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3372 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3373
3374 /*
3375 * Create test context.
3376 */
3377 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3378
3379 /*
3380 * Do the tests twice, first with all flags set, then once again with
3381 * flags cleared. The flags are not supposed to be touched at all except for the one indicated (CF or OF).
3382 */
3383 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3384 for (j = 0; j < 2; j++)
3385 {
3386 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3387 {
3388 uint8_t const cbOp = s_aTests[i].cbOp;
3389 unsigned const cValues = s_aTests[i].cValues;
3390 BS3CPUINSTR2_ADX_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3391 uint32_t const fEFlagsMod = s_aTests[i].fEFlagsMod;
3392 unsigned iValue;
3393 bool const fOkay = fSupportsAdx;
3394 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3395 uint64_t const uSrcGarbage = ( cbOp == 4 ? UINT64_C(0x0394831000000000) : 0)
3396 & (ARCH_BITS >= 64 ? UINT64_MAX : UINT32_MAX);
3397 uint64_t uExpectRip;
3398
3399 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3400 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3401
3402 for (iValue = 0; iValue < cValues; iValue++)
3403 {
3404 uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3405 uint64_t uMemSrc, uMemSrcExpect;
3406
3407 Ctx.rax.uCcXReg = paValues[iValue].uDstIn;
3408 if (!s_aTests[i].fMemSrc)
3409 {
3410 Ctx.rbx.u64 = paValues[iValue].uSrc | uSrcGarbage;
3411 uMemSrcExpect = uMemSrc = ~(paValues[iValue].uSrc | uSrcGarbage);
3412 }
3413 else
3414 {
3415 uMemSrcExpect = uMemSrc = paValues[iValue].uSrc | uSrcGarbage;
3416 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMemSrc);
3417 }
3418
3419 Ctx.rflags.u16 &= ~fEFlagsMod;
3420 if (paValues[iValue].fFlagIn)
3421 Ctx.rflags.u16 |= fEFlagsMod;
3422
3423 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3424
3425 if (fOkay)
3426 {
3427 Ctx.rflags.u16 &= ~fEFlagsMod;
3428 if (paValues[iValue].fFlagOut)
3429 Ctx.rflags.u16 |= fEFlagsMod;
3430 }
3431
3432 if ( TrapFrame.bXcpt != bExpectXcpt
3433 || TrapFrame.Ctx.rip.u != uExpectRip
3434 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
3435 || TrapFrame.Ctx.rax.u != uExpectRax
3436 /* check that nothing else really changed: */
3437 || TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16
3438 || TrapFrame.Ctx.rcx.u != Ctx.rcx.u
3439 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
3440 || TrapFrame.Ctx.rsp.u != Ctx.rsp.u
3441 || TrapFrame.Ctx.rbp.u != Ctx.rbp.u
3442 || TrapFrame.Ctx.rsi.u != Ctx.rsi.u
3443 || TrapFrame.Ctx.rdi.u != Ctx.rdi.u
3444 || uMemSrc != uMemSrcExpect
3445 )
3446 {
3447 Bs3TestFailedF("test #%i value #%i failed: input %#RX64, %#RX64",
3448 i, iValue, paValues[iValue].uDstIn, paValues[iValue].uSrc);
3449 if (TrapFrame.bXcpt != bExpectXcpt)
3450 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", bExpectXcpt, TrapFrame.bXcpt);
3451 if (TrapFrame.Ctx.rip.u != uExpectRip)
3452 Bs3TestFailedF("Expected RIP = %#06RX64, got %#06RX64", uExpectRip, TrapFrame.Ctx.rip.u);
3453 if (TrapFrame.Ctx.rax.u != uExpectRax)
3454 Bs3TestFailedF("Expected RAX = %#010RX64, got %#010RX64", uExpectRax, TrapFrame.Ctx.rax.u);
3455 if (TrapFrame.Ctx.rbx.u != Ctx.rbx.u)
3456 Bs3TestFailedF("Expected RBX = %#06RX64, got %#06RX64 (dst)", Ctx.rbx.u, TrapFrame.Ctx.rbx.u);
3457
3458 if (TrapFrame.Ctx.rflags.u16 != Ctx.rflags.u16)
3459 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", Ctx.rflags.u16, TrapFrame.Ctx.rflags.u16);
3460 if (TrapFrame.Ctx.rcx.u != Ctx.rcx.u)
3461 Bs3TestFailedF("Expected RCX = %#06RX64, got %#06RX64", Ctx.rcx.u, TrapFrame.Ctx.rcx.u);
3462 if (TrapFrame.Ctx.rdx.u != Ctx.rdx.u)
3463 Bs3TestFailedF("Expected RDX = %#06RX64, got %#06RX64 (src)", Ctx.rdx.u, TrapFrame.Ctx.rdx.u);
3464 if (TrapFrame.Ctx.rsp.u != Ctx.rsp.u)
3465 Bs3TestFailedF("Expected RSP = %#06RX64, got %#06RX64", Ctx.rsp.u, TrapFrame.Ctx.rsp.u);
3466 if (TrapFrame.Ctx.rbp.u != Ctx.rbp.u)
3467 Bs3TestFailedF("Expected RBP = %#06RX64, got %#06RX64", Ctx.rbp.u, TrapFrame.Ctx.rbp.u);
3468 if (TrapFrame.Ctx.rsi.u != Ctx.rsi.u)
3469 Bs3TestFailedF("Expected RSI = %#06RX64, got %#06RX64", Ctx.rsi.u, TrapFrame.Ctx.rsi.u);
3470 if (TrapFrame.Ctx.rdi.u != Ctx.rdi.u)
3471 Bs3TestFailedF("Expected RDI = %#06RX64, got %#06RX64", Ctx.rdi.u, TrapFrame.Ctx.rdi.u);
3472 if (uMemSrc != uMemSrcExpect)
3473 Bs3TestFailedF("Expected uMemSrc = %#06RX64, got %#06RX64", (uint64_t)uMemSrcExpect, (uint64_t)uMemSrc);
3474 }
3475 }
3476 }
3477 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3478 }
3479
3480 return 0;
3481}
3482
3483
3484
3485/*
3486 * MOVBE
3487 */
3488BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_movbe)(uint8_t bMode)
3489{
3490 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3491
3492 typedef struct BS3CPUINSTR2_MOVBE_VALUES_T
3493 {
3494 RTCCUINTXREG uDstOut;
3495 RTCCUINTXREG uDstIn;
3496 RTCCUINTXREG uSrc;
3497 } BS3CPUINSTR2_MOVBE_VALUES_T;
3498 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues2[] =
3499 {
3500 { UINT64_C(0xc0dedeaddead3412), UINT64_C(0xc0dedeaddeadc0de), UINT16_C(0x1234) }
3501 };
3502 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues4MemSrc[] =
3503 {
3504 { UINT64_C(0x78563412), UINT64_C(0xc0dedeaddeadc0de), UINT32_C(0x12345678) }
3505 };
3506 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues4MemDst[] =
3507 {
3508 { UINT64_C(0xc0dedead78563412), UINT64_C(0xc0dedeaddeadc0de), UINT32_C(0x12345678) }
3509 };
3510#if ARCH_BITS >= 64
3511 static const BS3CPUINSTR2_MOVBE_VALUES_T s_aValues8[] =
3512 {
3513 { UINT64_C(0xf0debc9a78563412), UINT64_C(0xc0dedeaddeadc0de), UINT64_C(0x123456789abcdef0) }
3514 };
3515#endif
3516 static const struct
3517 {
3518 FPFNBS3FAR pfnWorker;
3519 bool fMemSrc;
3520 uint8_t offIcebp;
3521 uint8_t cValues;
3522 BS3CPUINSTR2_MOVBE_VALUES_T const BS3_FAR *paValues;
3523 } s_aTests[] =
3524 {
3525 /* 16-bit register width */
3526 { BS3_CMN_NM(bs3CpuInstr2_movbe_AX_word_FSxBX_icebp), true, 6 + (ARCH_BITS != 16), RT_ELEMENTS(s_aValues2), s_aValues2 },
3527 { BS3_CMN_NM(bs3CpuInstr2_movbe_word_FSxBX_AX_icebp), false, 6 + (ARCH_BITS != 16), RT_ELEMENTS(s_aValues2), s_aValues2 },
3528 /* 32-bit register width */
3529 { BS3_CMN_NM(bs3CpuInstr2_movbe_EAX_dword_FSxBX_icebp), true, 6 + (ARCH_BITS == 16), RT_ELEMENTS(s_aValues4MemSrc), s_aValues4MemSrc },
3530 { BS3_CMN_NM(bs3CpuInstr2_movbe_dword_FSxBX_EAX_icebp), false, 6 + (ARCH_BITS == 16), RT_ELEMENTS(s_aValues4MemDst), s_aValues4MemDst },
3531#if ARCH_BITS >= 64
3532 /* 64-bit register width */
3533 { BS3_CMN_NM(bs3CpuInstr2_movbe_RAX_qword_FSxBX_icebp), true, 7, RT_ELEMENTS(s_aValues8), s_aValues8 },
3534 { BS3_CMN_NM(bs3CpuInstr2_movbe_qword_FSxBX_RAX_icebp), false, 7, RT_ELEMENTS(s_aValues8), s_aValues8 },
3535#endif
3536 };
3537
3538 BS3REGCTX Ctx;
3539 BS3REGCTX ExpectCtx;
3540 BS3TRAPFRAME TrapFrame;
3541 unsigned i, j;
3542 bool fSupportsMovBe = false;
3543
3544 if ( (g_uBs3CpuDetected & BS3CPU_F_CPUID)
3545 && ASMCpuId_EAX(0) >= 1)
3546 {
3547 uint32_t fEcx = 0;
3548 ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, NULL);
3549 fSupportsMovBe = RT_BOOL(fEcx & X86_CPUID_FEATURE_ECX_MOVBE);
3550 }
3551
3552 /* Ensure the structures are allocated before we sample the stack pointer. */
3553 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3554 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3555 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3556
3557 /*
3558 * Create test context.
3559 */
3560 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3561
3562 /*
3563 * Do the tests twice, first with all flags set, then once again with
3564 * flags cleared. The flags are not supposed to be touched at all.
3565 */
3566 g_usBs3TestStep = 0;
3567 for (j = 0; j < 2; j++)
3568 {
3569 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
3570 {
3571 unsigned const cValues = s_aTests[i].cValues;
3572 BS3CPUINSTR2_MOVBE_VALUES_T const BS3_FAR *paValues = s_aTests[i].paValues;
3573 unsigned iValue;
3574 bool const fOkay = fSupportsMovBe;
3575 uint8_t const bExpectXcpt = fOkay ? X86_XCPT_DB : X86_XCPT_UD;
3576 uint64_t uExpectRip;
3577
3578 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aTests[i].pfnWorker);
3579 uExpectRip = Ctx.rip.u + (fOkay ? ((uint8_t const BS3_FAR *)s_aTests[i].pfnWorker)[-1] + 1 : 0);
3580
3581 for (iValue = 0; iValue < cValues; iValue++)
3582 {
3583 //uint64_t const uExpectRax = fOkay ? paValues[iValue].uDstOut : paValues[iValue].uDstIn;
3584 uint64_t uMem, uMemExpect;
3585
3586 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3587
3588 if (!s_aTests[i].fMemSrc)
3589 {
3590 /* Memory is destination */
3591 Ctx.rax.u64 = paValues[iValue].uSrc;
3592 ExpectCtx.rax.u64 = paValues[iValue].uSrc;
3593 uMem = paValues[iValue].uDstIn;
3594 uMemExpect = paValues[iValue].uDstOut;
3595 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMem);
3596 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rbx, &ExpectCtx.fs, &uMem);
3597 }
3598 else
3599 {
3600 /* Memory is source */
3601 uMemExpect = uMem = paValues[iValue].uSrc;
3602 Ctx.rax.u64 = paValues[iValue].uDstIn;
3603 ExpectCtx.rax.u64 = paValues[iValue].uDstOut;
3604 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rbx, &Ctx.fs, &uMem);
3605 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rbx, &ExpectCtx.fs, &uMem);
3606 }
3607
3608 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3609 g_usBs3TestStep++;
3610
3611 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, bExpectXcpt == X86_XCPT_DB ? s_aTests[i].offIcebp : 0 /*cbPcAdjust*/,
3612 0 /*cbSpAcjust*/, 0 /*fExtraEfl*/, pszMode, g_usBs3TestStep)
3613 || TrapFrame.bXcpt != bExpectXcpt
3614 || uMem != uMemExpect
3615 )
3616 {
3617 if (TrapFrame.bXcpt != bExpectXcpt)
3618 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3619 if (uMem != uMemExpect)
3620 Bs3TestFailedF("Expected uMem = %#06RX64, got %#06RX64", (uint64_t)uMemExpect, (uint64_t)uMem);
3621 Bs3TestFailedF("^^^ iCfg=%u iWorker=%d iValue=%d\n",
3622 j, i, iValue);
3623 }
3624 }
3625 }
3626 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3627 }
3628
3629 return 0;
3630}
3631
3632
3633
3634/*
3635 * CMPXCHG8B
3636 */
3637BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg8b)(uint8_t bMode)
3638{
3639
3640 BS3REGCTX Ctx;
3641 BS3REGCTX ExpectCtx;
3642 BS3TRAPFRAME TrapFrame;
3643 RTUINT64U au64[3];
3644 PRTUINT64U pau64 = RT_ALIGN_PT(&au64[0], sizeof(RTUINT64U), PRTUINT64U);
3645 bool const fSupportCX8 = RT_BOOL(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_CX8);
3646 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3647 uint8_t bRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
3648 unsigned iFlags;
3649 unsigned offBuf;
3650 unsigned iMatch;
3651 unsigned iWorker;
3652 static struct
3653 {
3654 bool fLocked;
3655 uint8_t offIcebp;
3656 FNBS3FAR *pfnWorker;
3657 } const s_aWorkers[] =
3658 {
3659 { false, 5, BS3_CMN_NM(bs3CpuInstr2_cmpxchg8b_FSxDI_icebp) },
3660#if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PP16
3661 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg8b_FSxDI_icebp) },
3662#else
3663 { false, 6, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg8b_FSxDI_icebp) },
3664#endif
3665 { false, 6, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg8b_FSxDI_icebp) },
3666 { false, 6, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg8b_FSxDI_icebp) },
3667 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg8b_FSxDI_icebp) },
3668 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg8b_FSxDI_icebp) },
3669 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg8b_FSxDI_icebp) },
3670 { true, 1+6, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg8b_FSxDI_icebp) },
3671 };
3672
3673 /* Ensure the structures are allocated before we sample the stack pointer. */
3674 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3675 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3676 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3677 Bs3MemSet(pau64, 0, sizeof(pau64[0]) * 2);
3678
3679 /*
3680 * Create test context.
3681 */
3682 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3683 if (!fSupportCX8)
3684 Bs3TestPrintf("Note! CMPXCHG8B is not supported by the CPU!\n");
3685
3686 /*
3687 * Run the tests in all rings since alignment issues may behave
3688 * differently in ring-3 compared to ring-0.
3689 */
3690 for (;;)
3691 {
3692 /*
3693 * One loop with alignment checks disabled and one with enabled.
3694 */
3695 unsigned iCfg;
3696 for (iCfg = 0; iCfg < 2; iCfg++)
3697 {
3698 if (iCfg)
3699 {
3700 Ctx.rflags.u32 |= X86_EFL_AC;
3701 Ctx.cr0.u32 |= X86_CR0_AM;
3702 }
3703 else
3704 {
3705 Ctx.rflags.u32 &= ~X86_EFL_AC;
3706 Ctx.cr0.u32 &= ~X86_CR0_AM;
3707 }
3708
3709 /*
3710 * One loop with the normal variant and one with the locked one
3711 */
3712 g_usBs3TestStep = 0;
3713 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
3714 {
3715 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
3716
3717 /*
3718 * One loop with all status flags set, and one with them clear.
3719 */
3720 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3721 for (iFlags = 0; iFlags < 2; iFlags++)
3722 {
3723 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3724
3725 for (offBuf = 0; offBuf < sizeof(RTUINT64U); offBuf++)
3726 {
3727# define CX8_OLD_LO UINT32_C(0xcc9c4bbd)
3728# define CX8_OLD_HI UINT32_C(0x749549ab)
3729# define CX8_MISMATCH_LO UINT32_C(0x90f18981)
3730# define CX8_MISMATCH_HI UINT32_C(0xfd5b4000)
3731# define CX8_STORE_LO UINT32_C(0x51f6559b)
3732# define CX8_STORE_HI UINT32_C(0xd1b54963)
3733
3734 PRTUINT64U pBuf = (PRTUINT64U)&pau64->au8[offBuf];
3735
3736 ExpectCtx.rax.u = Ctx.rax.u = CX8_MISMATCH_LO;
3737 ExpectCtx.rdx.u = Ctx.rdx.u = CX8_MISMATCH_HI;
3738
3739 Bs3RegCtxSetGrpSegFromCurPtr(&Ctx, &Ctx.rdi, &Ctx.fs, pBuf);
3740 Bs3RegCtxSetGrpSegFromCurPtr(&ExpectCtx, &ExpectCtx.rdi, &ExpectCtx.fs, pBuf);
3741
3742 for (iMatch = 0; iMatch < 2; iMatch++)
3743 {
3744 uint8_t bExpectXcpt;
3745 pBuf->s.Lo = CX8_OLD_LO;
3746 pBuf->s.Hi = CX8_OLD_HI;
3747
3748 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3749 g_usBs3TestStep++;
3750 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
3751 bExpectXcpt = X86_XCPT_UD;
3752 if (fSupportCX8)
3753 {
3754 if ( offBuf
3755 && bRing == 3
3756 && bMode != BS3_MODE_RM
3757 && !BS3_MODE_IS_V86(bMode)
3758 && iCfg)
3759 {
3760 bExpectXcpt = X86_XCPT_AC;
3761 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
3762 }
3763 else
3764 {
3765 bExpectXcpt = X86_XCPT_DB;
3766
3767 ExpectCtx.rax.u = CX8_OLD_LO;
3768 ExpectCtx.rdx.u = CX8_OLD_HI;
3769
3770 if (iMatch & 1)
3771 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
3772 else
3773 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
3774 }
3775
3776 /* Kludge! Looks like EFLAGS.AC is cleared when raising #GP in real mode on an i7-6700K. WEIRD! */
3777 if (bMode == BS3_MODE_RM && (Ctx.rflags.u32 & X86_EFL_AC))
3778 {
3779 if (TrapFrame.Ctx.rflags.u32 & X86_EFL_AC)
3780 Bs3TestFailedF("Expected EFLAGS.AC to be cleared (bXcpt=%d)", TrapFrame.bXcpt);
3781 TrapFrame.Ctx.rflags.u32 |= X86_EFL_AC;
3782 }
3783 }
3784
3785 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, bExpectXcpt == X86_XCPT_DB ? s_aWorkers[iWorker].offIcebp : 0, 0 /*cbSpAdjust*/,
3786 bExpectXcpt == X86_XCPT_DB || BS3_MODE_IS_16BIT_SYS(bMode) ? 0 : X86_EFL_RF, pszMode, g_usBs3TestStep)
3787 || TrapFrame.bXcpt != bExpectXcpt)
3788 {
3789 if (TrapFrame.bXcpt != bExpectXcpt)
3790 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3791 Bs3TestFailedF("^^^ bRing=%u iCfg=%d iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n",
3792 bRing, iCfg, iWorker, iFlags, offBuf, iMatch);
3793 ASMHalt();
3794 }
3795
3796 ExpectCtx.rax.u = Ctx.rax.u = CX8_OLD_LO;
3797 ExpectCtx.rdx.u = Ctx.rdx.u = CX8_OLD_HI;
3798 }
3799 }
3800 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3801 }
3802 }
3803 } /* for each test config. */
3804
3805 /*
3806 * Next ring.
3807 */
3808 bRing++;
3809 if (bRing > 3 || bMode == BS3_MODE_RM)
3810 break;
3811 Bs3RegCtxConvertToRingX(&Ctx, bRing);
3812 }
3813
3814 return 0;
3815}
3816
3817
3818
3819/*
3820 *
3821 */
3822# if ARCH_BITS == 64
3823
3824BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b)(uint8_t bMode)
3825{
3826 BS3REGCTX Ctx;
3827 BS3REGCTX ExpectCtx;
3828 BS3TRAPFRAME TrapFrame;
3829 RTUINT128U au128[3];
3830 PRTUINT128U pau128 = RT_ALIGN_PT(&au128[0], sizeof(RTUINT128U), PRTUINT128U);
3831 bool const fSupportCX16 = RT_BOOL(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16);
3832 const char BS3_FAR * const pszMode = Bs3GetModeName(bMode);
3833 uint8_t bRing = BS3_MODE_IS_V86(bMode) ? 3 : 0;
3834 unsigned iFlags;
3835 unsigned offBuf;
3836 unsigned iMatch;
3837 unsigned iWorker;
3838 static struct
3839 {
3840 bool fLocked;
3841 uint8_t offUd2;
3842 FNBS3FAR *pfnWorker;
3843 } const s_aWorkers[] =
3844 {
3845 { false, 4, BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2) },
3846 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2) },
3847 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2) },
3848 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2) },
3849 { true, 1+4, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2) },
3850 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2) },
3851 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2) },
3852 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2) },
3853 };
3854
3855 /* Ensure the structures are allocated before we sample the stack pointer. */
3856 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
3857 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
3858 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
3859 Bs3MemSet(pau128, 0, sizeof(pau128[0]) * 2);
3860
3861 /*
3862 * Create test context.
3863 */
3864 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
3865 if (!fSupportCX16)
3866 Bs3TestPrintf("Note! CMPXCHG16B is not supported by the CPU!\n");
3867
3868
3869 /*
3870 * Run the tests in all rings since alignment issues may behave
3871 * differently in ring-3 compared to ring-0.
3872 */
3873 for (;;)
3874 {
3875 /*
3876 * One loop with alignment checks disabled and one with enabled.
3877 */
3878 unsigned iCfg;
3879 for (iCfg = 0; iCfg < 2; iCfg++)
3880 {
3881 if (iCfg)
3882 {
3883 Ctx.rflags.u32 |= X86_EFL_AC;
3884 Ctx.cr0.u32 |= X86_CR0_AM;
3885 }
3886 else
3887 {
3888 Ctx.rflags.u32 &= ~X86_EFL_AC;
3889 Ctx.cr0.u32 &= ~X86_CR0_AM;
3890 }
3891
3892 /*
3893 * One loop with the normal variant and one with the locked one
3894 */
3895 g_usBs3TestStep = 0;
3896 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
3897 {
3898 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
3899
3900 /*
3901 * One loop with all status flags set, and one with them clear.
3902 */
3903 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
3904 for (iFlags = 0; iFlags < 2; iFlags++)
3905 {
3906 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
3907
3908 for (offBuf = 0; offBuf < sizeof(RTUINT128U); offBuf++)
3909 {
3910# define CX16_OLD_LO UINT64_C(0xabb6345dcc9c4bbd)
3911# define CX16_OLD_HI UINT64_C(0x7b06ea35749549ab)
3912# define CX16_MISMATCH_LO UINT64_C(0xbace3e3590f18981)
3913# define CX16_MISMATCH_HI UINT64_C(0x9b385e8bfd5b4000)
3914# define CX16_STORE_LO UINT64_C(0x5cbd27d251f6559b)
3915# define CX16_STORE_HI UINT64_C(0x17ff434ed1b54963)
3916
3917 PRTUINT128U pBuf = (PRTUINT128U)&pau128->au8[offBuf];
3918
3919 ExpectCtx.rax.u = Ctx.rax.u = CX16_MISMATCH_LO;
3920 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_MISMATCH_HI;
3921 for (iMatch = 0; iMatch < 2; iMatch++)
3922 {
3923 uint8_t bExpectXcpt;
3924 pBuf->s.Lo = CX16_OLD_LO;
3925 pBuf->s.Hi = CX16_OLD_HI;
3926 ExpectCtx.rdi.u = Ctx.rdi.u = (uintptr_t)pBuf;
3927 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
3928 g_usBs3TestStep++;
3929 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
3930 bExpectXcpt = X86_XCPT_UD;
3931 if (fSupportCX16)
3932 {
3933 if (offBuf & 15)
3934 {
3935 bExpectXcpt = X86_XCPT_GP;
3936 ExpectCtx.rip.u = Ctx.rip.u;
3937 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
3938 }
3939 else
3940 {
3941 ExpectCtx.rax.u = CX16_OLD_LO;
3942 ExpectCtx.rdx.u = CX16_OLD_HI;
3943 if (iMatch & 1)
3944 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
3945 else
3946 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
3947 ExpectCtx.rip.u = Ctx.rip.u + s_aWorkers[iWorker].offUd2;
3948 }
3949 ExpectCtx.rflags.u32 |= X86_EFL_RF;
3950 }
3951 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
3952 0 /*fExtraEfl*/, pszMode, 0 /*idTestStep*/)
3953 || TrapFrame.bXcpt != bExpectXcpt)
3954 {
3955 if (TrapFrame.bXcpt != bExpectXcpt)
3956 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
3957 Bs3TestFailedF("^^^bRing=%d iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n", bRing, iWorker, iFlags, offBuf, iMatch);
3958 ASMHalt();
3959 }
3960
3961 ExpectCtx.rax.u = Ctx.rax.u = CX16_OLD_LO;
3962 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_OLD_HI;
3963 }
3964 }
3965 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
3966 }
3967 }
3968 } /* for each test config. */
3969
3970 /*
3971 * Next ring.
3972 */
3973 bRing++;
3974 if (bRing > 3 || bMode == BS3_MODE_RM)
3975 break;
3976 Bs3RegCtxConvertToRingX(&Ctx, bRing);
3977 }
3978
3979 return 0;
3980}
3981
3982
3983static void bs3CpuInstr2_fsgsbase_ExpectUD(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame)
3984{
3985 pCtx->rbx.u = 0;
3986 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
3987 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
3988 pExpectCtx->rip.u = pCtx->rip.u;
3989 pExpectCtx->rflags.u32 |= X86_EFL_RF;
3990 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
3991 0 /*idTestStep*/)
3992 || pTrapFrame->bXcpt != X86_XCPT_UD)
3993 {
3994 Bs3TestFailedF("Expected #UD, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
3995 ASMHalt();
3996 }
3997}
3998
3999
4000static bool bs3CpuInstr2_fsgsbase_VerifyWorker(uint8_t bMode, PBS3REGCTX pCtx, PBS3REGCTX pExpectCtx, PBS3TRAPFRAME pTrapFrame,
4001 BS3CI2FSGSBASE const *pFsGsBaseWorker, unsigned *puIter)
4002{
4003 bool fPassed = true;
4004 unsigned iValue = 0;
4005 static const struct
4006 {
4007 bool fGP;
4008 uint64_t u64Base;
4009 } s_aValues64[] =
4010 {
4011 { false, UINT64_C(0x0000000000000000) },
4012 { false, UINT64_C(0x0000000000000001) },
4013 { false, UINT64_C(0x0000000000000010) },
4014 { false, UINT64_C(0x0000000000000123) },
4015 { false, UINT64_C(0x0000000000001234) },
4016 { false, UINT64_C(0x0000000000012345) },
4017 { false, UINT64_C(0x0000000000123456) },
4018 { false, UINT64_C(0x0000000001234567) },
4019 { false, UINT64_C(0x0000000012345678) },
4020 { false, UINT64_C(0x0000000123456789) },
4021 { false, UINT64_C(0x000000123456789a) },
4022 { false, UINT64_C(0x00000123456789ab) },
4023 { false, UINT64_C(0x0000123456789abc) },
4024 { false, UINT64_C(0x00007ffffeefefef) },
4025 { false, UINT64_C(0x00007fffffffffff) },
4026 { true, UINT64_C(0x0000800000000000) },
4027 { true, UINT64_C(0x0000800000000000) },
4028 { true, UINT64_C(0x0000800000000333) },
4029 { true, UINT64_C(0x0001000000000000) },
4030 { true, UINT64_C(0x0012000000000000) },
4031 { true, UINT64_C(0x0123000000000000) },
4032 { true, UINT64_C(0x1234000000000000) },
4033 { true, UINT64_C(0xffff300000000000) },
4034 { true, UINT64_C(0xffff7fffffffffff) },
4035 { true, UINT64_C(0xffff7fffffffffff) },
4036 { false, UINT64_C(0xffff800000000000) },
4037 { false, UINT64_C(0xffffffffffeefefe) },
4038 { false, UINT64_C(0xffffffffffffffff) },
4039 { false, UINT64_C(0xffffffffffffffff) },
4040 { false, UINT64_C(0x00000000efefefef) },
4041 { false, UINT64_C(0x0000000080204060) },
4042 { false, UINT64_C(0x00000000ddeeffaa) },
4043 { false, UINT64_C(0x00000000fdecdbca) },
4044 { false, UINT64_C(0x000000006098456b) },
4045 { false, UINT64_C(0x0000000098506099) },
4046 { false, UINT64_C(0x00000000206950bc) },
4047 { false, UINT64_C(0x000000009740395d) },
4048 { false, UINT64_C(0x0000000064a9455e) },
4049 { false, UINT64_C(0x00000000d20b6eff) },
4050 { false, UINT64_C(0x0000000085296d46) },
4051 { false, UINT64_C(0x0000000007000039) },
4052 { false, UINT64_C(0x000000000007fe00) },
4053 };
4054
4055 Bs3RegCtxSetRipCsFromCurPtr(pCtx, pFsGsBaseWorker->pfnVerifyWorker);
4056 if (pFsGsBaseWorker->f64BitOperand)
4057 {
4058 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
4059 {
4060 bool const fGP = s_aValues64[iValue].fGP;
4061
4062 pCtx->rbx.u = s_aValues64[iValue].u64Base;
4063 pCtx->rcx.u = 0;
4064 pCtx->cr4.u |= X86_CR4_FSGSBASE;
4065 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
4066 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
4067 pExpectCtx->rip.u = pCtx->rip.u + (!fGP ? pFsGsBaseWorker->offVerifyWorkerUd2 : 0);
4068 pExpectCtx->rbx.u = !fGP ? 0 : s_aValues64[iValue].u64Base;
4069 pExpectCtx->rcx.u = !fGP ? s_aValues64[iValue].u64Base : 0;
4070 pExpectCtx->rflags.u32 |= X86_EFL_RF;
4071 if ( !Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
4072 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/)
4073 || (fGP && pTrapFrame->bXcpt != X86_XCPT_GP))
4074 {
4075 if (fGP && pTrapFrame->bXcpt != X86_XCPT_GP)
4076 Bs3TestFailedF("Expected #GP, got %#x (%#x)", pTrapFrame->bXcpt, pTrapFrame->uErrCd);
4077 else
4078 Bs3TestFailedF("iValue=%u\n", iValue);
4079 fPassed = false;
4080 break;
4081 }
4082 }
4083 }
4084 else
4085 {
4086 for (iValue = 0; iValue < RT_ELEMENTS(s_aValues64); iValue++)
4087 {
4088 pCtx->rbx.u = s_aValues64[iValue].u64Base;
4089 pCtx->rcx.u = ~s_aValues64[iValue].u64Base;
4090 pCtx->cr4.u |= X86_CR4_FSGSBASE;
4091 Bs3MemCpy(pExpectCtx, pCtx, sizeof(*pExpectCtx));
4092 Bs3TrapSetJmpAndRestore(pCtx, pTrapFrame);
4093 pExpectCtx->rip.u = pCtx->rip.u + pFsGsBaseWorker->offVerifyWorkerUd2;
4094 pExpectCtx->rbx.u = 0;
4095 pExpectCtx->rcx.u = s_aValues64[iValue].u64Base & UINT64_C(0x00000000ffffffff);
4096 pExpectCtx->rflags.u32 |= X86_EFL_RF;
4097 if (!Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
4098 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/))
4099 {
4100 Bs3TestFailedF("iValue=%u\n", iValue);
4101 fPassed = false;
4102 break;
4103 }
4104 }
4105 }
4106
4107 *puIter = iValue;
4108 return fPassed;
4109}
4110
4111
4112static void bs3CpuInstr2_rdfsbase_rdgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
4113 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
4114{
4115 BS3REGCTX Ctx;
4116 BS3REGCTX ExpectCtx;
4117 BS3TRAPFRAME TrapFrame;
4118 unsigned iWorker;
4119 unsigned iIter;
4120 uint32_t uDummy;
4121 uint32_t uStdExtFeatEbx;
4122 bool fSupportsFsGsBase;
4123
4124 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
4125 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
4126
4127 /* Ensure the structures are allocated before we sample the stack pointer. */
4128 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
4129 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
4130 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
4131
4132 /*
4133 * Create test context.
4134 */
4135 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
4136
4137 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
4138 {
4139 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
4140 if (fSupportsFsGsBase)
4141 {
4142 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
4143
4144 /* CR4.FSGSBASE disabled -> #UD. */
4145 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
4146 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4147
4148 /* Read and verify existing base address. */
4149 Ctx.rbx.u = 0;
4150 Ctx.cr4.u |= X86_CR4_FSGSBASE;
4151 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
4152 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
4153 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
4154 ExpectCtx.rbx.u = uBaseAddr;
4155 ExpectCtx.rflags.u32 |= X86_EFL_RF;
4156 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
4157 0 /*idTestStep*/))
4158 {
4159 ASMHalt();
4160 }
4161
4162 /* Write, read and verify series of base addresses. */
4163 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
4164 {
4165 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
4166 ASMHalt();
4167 }
4168
4169 /* Restore original base address. */
4170 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
4171
4172 /* Clean used GPRs. */
4173 Ctx.rbx.u = 0;
4174 Ctx.rcx.u = 0;
4175 }
4176 else
4177 {
4178 /* Unsupported by CPUID -> #UD. */
4179 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
4180 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4181 }
4182 }
4183}
4184
4185
4186static void bs3CpuInstr2_wrfsbase_wrgsbase_Common(uint8_t bMode, BS3CI2FSGSBASE const *paFsGsBaseWorkers,
4187 unsigned cFsGsBaseWorkers, uint32_t idxFsGsBaseMsr)
4188{
4189 BS3REGCTX Ctx;
4190 BS3REGCTX ExpectCtx;
4191 BS3TRAPFRAME TrapFrame;
4192 unsigned iWorker;
4193 unsigned iIter;
4194 uint32_t uDummy;
4195 uint32_t uStdExtFeatEbx;
4196 bool fSupportsFsGsBase;
4197
4198 ASMCpuId_Idx_ECX(7, 0, &uDummy, &uStdExtFeatEbx, &uDummy, &uDummy);
4199 fSupportsFsGsBase = RT_BOOL(uStdExtFeatEbx & X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE);
4200
4201 /* Ensure the structures are allocated before we sample the stack pointer. */
4202 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
4203 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
4204 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
4205
4206 /*
4207 * Create test context.
4208 */
4209 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
4210
4211 for (iWorker = 0; iWorker < cFsGsBaseWorkers; iWorker++)
4212 {
4213 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, paFsGsBaseWorkers[iWorker].pfnWorker);
4214 if (fSupportsFsGsBase)
4215 {
4216 uint64_t const uBaseAddr = ASMRdMsr(idxFsGsBaseMsr);
4217
4218 /* CR4.FSGSBASE disabled -> #UD. */
4219 Ctx.cr4.u &= ~X86_CR4_FSGSBASE;
4220 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4221
4222 /* Write a base address. */
4223 Ctx.rbx.u = 0xa0000;
4224 Ctx.cr4.u |= X86_CR4_FSGSBASE;
4225 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
4226 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
4227 ExpectCtx.rip.u = Ctx.rip.u + paFsGsBaseWorkers[iWorker].offWorkerUd2;
4228 ExpectCtx.rflags.u32 |= X86_EFL_RF;
4229 if (!Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, "lm64",
4230 0 /*idTestStep*/))
4231 {
4232 ASMHalt();
4233 }
4234
4235 /* Write and read back series of base addresses. */
4236 if (!bs3CpuInstr2_fsgsbase_VerifyWorker(bMode, &Ctx, &ExpectCtx, &TrapFrame, &paFsGsBaseWorkers[iWorker], &iIter))
4237 {
4238 Bs3TestFailedF("^^^ %s: iWorker=%u iIter=%u\n", paFsGsBaseWorkers[iWorker].pszDesc, iWorker, iIter);
4239 ASMHalt();
4240 }
4241
4242 /* Restore original base address. */
4243 ASMWrMsr(idxFsGsBaseMsr, uBaseAddr);
4244
4245 /* Clean used GPRs. */
4246 Ctx.rbx.u = 0;
4247 Ctx.rcx.u = 0;
4248 }
4249 else
4250 {
4251 /* Unsupported by CPUID -> #UD. */
4252 Bs3TestPrintf("Note! FSGSBASE is not supported by the CPU!\n");
4253 bs3CpuInstr2_fsgsbase_ExpectUD(bMode, &Ctx, &ExpectCtx, &TrapFrame);
4254 }
4255 }
4256}
4257
4258
4259BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrfsbase)(uint8_t bMode)
4260{
4261 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrFsBaseWorkers, RT_ELEMENTS(s_aWrFsBaseWorkers), MSR_K8_FS_BASE);
4262 return 0;
4263}
4264
4265
4266BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_wrgsbase)(uint8_t bMode)
4267{
4268 bs3CpuInstr2_wrfsbase_wrgsbase_Common(bMode, s_aWrGsBaseWorkers, RT_ELEMENTS(s_aWrGsBaseWorkers), MSR_K8_GS_BASE);
4269 return 0;
4270}
4271
4272
4273BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdfsbase)(uint8_t bMode)
4274{
4275 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdFsBaseWorkers, RT_ELEMENTS(s_aRdFsBaseWorkers), MSR_K8_FS_BASE);
4276 return 0;
4277}
4278
4279
4280BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_rdgsbase)(uint8_t bMode)
4281{
4282 bs3CpuInstr2_rdfsbase_rdgsbase_Common(bMode, s_aRdGsBaseWorkers, RT_ELEMENTS(s_aRdGsBaseWorkers), MSR_K8_GS_BASE);
4283 return 0;
4284}
4285
4286# endif /* ARCH_BITS == 64 */
4287
4288#endif /* BS3_INSTANTIATING_CMN */
4289
4290
4291
4292/*
4293 * Mode specific code.
4294 * Mode specific code.
4295 * Mode specific code.
4296 */
4297#ifdef BS3_INSTANTIATING_MODE
4298
4299
4300#endif /* BS3_INSTANTIATING_MODE */
4301
Note: See TracBrowser for help on using the repository browser.

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