VirtualBox

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

Last change on this file since 69222 was 69111, checked in by vboxsync, 7 years ago

(C) year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.5 KB
Line 
1/* $Id: bs3-cpu-instr-2-template.c 69111 2017-10-17 14:26:02Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-instr-2, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/asm.h>
32#include <iprt/asm-amd64-x86.h>
33
34
35
36
37/*********************************************************************************************************************************
38* Structures and Typedefs *
39*********************************************************************************************************************************/
40#ifdef BS3_INSTANTIATING_CMN
41#endif
42
43
44/*********************************************************************************************************************************
45* External Symbols *
46*********************************************************************************************************************************/
47#ifdef BS3_INSTANTIATING_CMN
48extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2);
49extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2);
50extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2);
51extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2);
52extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2);
53# if ARCH_BITS == 64
54extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2);
55extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2);
56extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2);
57extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2);
58extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2);
59extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2);
60extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2);
61extern FNBS3FAR BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2);
62# endif
63#endif
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69#ifdef BS3_INSTANTIATING_CMN
70
71#endif /* BS3_INSTANTIATING_CMN - global */
72
73
74/*
75 * Common code.
76 * Common code.
77 * Common code.
78 */
79#ifdef BS3_INSTANTIATING_CMN
80
81BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
82{
83#define MUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
84#define MUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
85
86 static const struct
87 {
88 RTCCUINTREG uInAX;
89 RTCCUINTREG uInBX;
90 RTCCUINTREG uOutDX;
91 RTCCUINTREG uOutAX;
92 uint16_t fFlags;
93 } s_aTests[] =
94 {
95 { 1, 1,
96 0, 1, 0 },
97 { 2, 2,
98 0, 4, 0 },
99 { RTCCUINTREG_MAX, RTCCUINTREG_MAX,
100 RTCCUINTREG_MAX-1, 1, X86_EFL_CF | X86_EFL_OF },
101 { RTCCINTREG_MAX, RTCCINTREG_MAX,
102 RTCCINTREG_MAX / 2, 1, X86_EFL_CF | X86_EFL_OF },
103 { 1, RTCCUINTREG_MAX,
104 0, RTCCUINTREG_MAX, X86_EFL_PF | X86_EFL_SF },
105 { 1, RTCCINTREG_MAX,
106 0, RTCCINTREG_MAX, X86_EFL_PF },
107 { 2, RTCCINTREG_MAX,
108 0, RTCCUINTREG_MAX - 1, X86_EFL_SF },
109 { (RTCCUINTREG)RTCCINTREG_MAX + 1, 2,
110 1, 0, X86_EFL_PF | X86_EFL_CF | X86_EFL_OF },
111 { (RTCCUINTREG)RTCCINTREG_MAX / 2 + 1, 3,
112 0, ((RTCCUINTREG)RTCCINTREG_MAX / 2 + 1) * 3, X86_EFL_PF | X86_EFL_SF },
113 };
114
115 BS3REGCTX Ctx;
116 BS3TRAPFRAME TrapFrame;
117 unsigned i, j, k;
118
119 /* Ensure the structures are allocated before we sample the stack pointer. */
120 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
121 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
122
123 /*
124 * Create test context.
125 */
126 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
127 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2));
128 for (k = 0; k < 2; k++)
129 {
130 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
131 for (j = 0; j < 2; j++)
132 {
133 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
134 {
135 if (k == 0)
136 {
137 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
138 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
139 }
140 else
141 {
142 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
143 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
144 }
145 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
146 if (TrapFrame.bXcpt != X86_XCPT_UD)
147 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
148 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
149 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
150 || (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
151 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
152 {
153 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
154 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
155
156 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
157 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
158 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
159 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
160 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
161 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
162 if ( (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
163 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
164 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & MUL_CHECK_EFLAGS,
165 TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO));
166 }
167 }
168 Ctx.rflags.u16 &= ~(MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO);
169 }
170 }
171
172 return 0;
173}
174
175
176BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_imul)(uint8_t bMode)
177{
178#define IMUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
179#define IMUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
180 static const struct
181 {
182 RTCCUINTREG uInAX;
183 RTCCUINTREG uInBX;
184 RTCCUINTREG uOutDX;
185 RTCCUINTREG uOutAX;
186 uint16_t fFlags;
187 } s_aTests[] =
188 {
189 /* two positive values. */
190 { 1, 1,
191 0, 1, 0 },
192 { 2, 2,
193 0, 4, 0 },
194 { RTCCINTREG_MAX, RTCCINTREG_MAX,
195 RTCCINTREG_MAX/2, 1, X86_EFL_CF | X86_EFL_OF },
196 { 1, RTCCINTREG_MAX,
197 0, RTCCINTREG_MAX, X86_EFL_PF },
198 { 2, RTCCINTREG_MAX,
199 0, RTCCUINTREG_MAX - 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF },
200 { 2, RTCCINTREG_MAX / 2,
201 0, RTCCINTREG_MAX - 1U, 0 },
202 { 2, (RTCCINTREG_MAX / 2 + 1),
203 0, (RTCCUINTREG)RTCCINTREG_MAX + 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
204 { 4, (RTCCINTREG_MAX / 2 + 1),
205 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
206
207 /* negative and positive */
208 { -4, 3,
209 -1, -12, X86_EFL_SF },
210 { 32, -127,
211 -1, -4064, X86_EFL_SF },
212 { RTCCINTREG_MIN, 1,
213 -1, RTCCINTREG_MIN, X86_EFL_SF | X86_EFL_PF },
214 { RTCCINTREG_MIN, 2,
215 -1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
216 { RTCCINTREG_MIN, 3,
217 -2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
218 { RTCCINTREG_MIN, 4,
219 -2, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
220 { RTCCINTREG_MIN, RTCCINTREG_MAX,
221 RTCCINTREG_MIN / 2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
222 { RTCCINTREG_MIN, RTCCINTREG_MAX - 1,
223 RTCCINTREG_MIN / 2 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
224
225 /* two negative values. */
226 { -4, -63,
227 0, 252, X86_EFL_PF },
228 { RTCCINTREG_MIN, RTCCINTREG_MIN,
229 RTCCUINTREG_MAX / 4 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
230 { RTCCINTREG_MIN, RTCCINTREG_MIN + 1,
231 RTCCUINTREG_MAX / 4, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF},
232 { RTCCINTREG_MIN + 1, RTCCINTREG_MIN + 1,
233 RTCCUINTREG_MAX / 4, 1, X86_EFL_CF | X86_EFL_OF },
234
235 };
236
237 BS3REGCTX Ctx;
238 BS3TRAPFRAME TrapFrame;
239 unsigned i, j, k;
240
241 /* Ensure the structures are allocated before we sample the stack pointer. */
242 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
243 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
244
245 /*
246 * Create test context.
247 */
248 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
249 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2));
250
251 for (k = 0; k < 2; k++)
252 {
253 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
254 for (j = 0; j < 2; j++)
255 {
256 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
257 {
258 if (k == 0)
259 {
260 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
261 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
262 }
263 else
264 {
265 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
266 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
267 }
268 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
269 if (TrapFrame.bXcpt != X86_XCPT_UD)
270 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
271 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
272 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
273 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
274 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
275 {
276 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
277 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
278
279 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
280 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
281 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
282 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
283 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
284 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
285 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
286 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
287 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
288 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
289 }
290 }
291 }
292 }
293
294 /*
295 * Repeat for the truncating two operand version.
296 */
297 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2));
298
299 for (k = 0; k < 2; k++)
300 {
301 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
302 for (j = 0; j < 2; j++)
303 {
304 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
305 {
306 if (k == 0)
307 {
308 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
309 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
310 }
311 else
312 {
313 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
314 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
315 }
316 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
317 if (TrapFrame.bXcpt != X86_XCPT_UD)
318 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
319 else if ( TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
320 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
321 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
322 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
323 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
324 {
325 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
326 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
327
328 if (TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
329 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
330 s_aTests[i].uOutAX, TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS));
331 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
332 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
333 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
334 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
335 }
336 }
337 }
338 }
339
340 return 0;
341}
342
343
344BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_div)(uint8_t bMode)
345{
346#define DIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
347 static const struct
348 {
349 RTCCUINTREG uInDX;
350 RTCCUINTREG uInAX;
351 RTCCUINTREG uInBX;
352 RTCCUINTREG uOutAX;
353 RTCCUINTREG uOutDX;
354 uint8_t bXcpt;
355 } s_aTests[] =
356 {
357 { 0, 1, 1,
358 1, 0, X86_XCPT_UD },
359 { 0, 5, 2,
360 2, 1, X86_XCPT_UD },
361 { 0, 0, 0,
362 0, 0, X86_XCPT_DE },
363 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 0,
364 0, 0, X86_XCPT_DE },
365 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 1,
366 0, 0, X86_XCPT_DE },
367 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
368 0, 0, X86_XCPT_DE },
369 { RTCCUINTREG_MAX - 1, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
370 RTCCUINTREG_MAX, RTCCUINTREG_MAX - 1, X86_XCPT_UD },
371 };
372
373 BS3REGCTX Ctx;
374 BS3TRAPFRAME TrapFrame;
375 unsigned i, j;
376
377 /* Ensure the structures are allocated before we sample the stack pointer. */
378 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
379 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
380
381 /*
382 * Create test context.
383 */
384 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
385 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2));
386
387 /*
388 * Do the tests twice, first with all flags set, then once again with
389 * flags cleared. The flags are not touched by my intel skylake CPU.
390 */
391 Ctx.rflags.u16 |= DIV_CHECK_EFLAGS;
392 for (j = 0; j < 2; j++)
393 {
394 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
395 {
396 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
397 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
398 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
399 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
400
401 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
402 || ( s_aTests[i].bXcpt == X86_XCPT_UD
403 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
404 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
405 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS)
406 : TrapFrame.Ctx.rax.u != Ctx.rax.u
407 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
408 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS) ) )
409 {
410 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
411 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
412 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
413 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
414 if (s_aTests[i].bXcpt == X86_XCPT_UD)
415 {
416 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
417 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
418 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
419 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
420 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
421 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
422 if ((TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS))
423 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
424 Ctx.rflags.u16 & DIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS);
425 }
426 }
427 }
428 Ctx.rflags.u16 &= ~DIV_CHECK_EFLAGS;
429 }
430
431 return 0;
432}
433
434
435
436BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_idiv)(uint8_t bMode)
437{
438#define IDIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
439 static const struct
440 {
441 RTCCUINTREG uInDX;
442 RTCCUINTREG uInAX;
443 RTCCUINTREG uInBX;
444 RTCCUINTREG uOutAX;
445 RTCCUINTREG uOutDX;
446 uint8_t bXcpt;
447 } s_aTests[] =
448 {
449 { 0, 0, 0,
450 0, 0, X86_XCPT_DE },
451 { RTCCINTREG_MAX, RTCCINTREG_MAX, 0,
452 0, 0, X86_XCPT_DE },
453 /* two positive values. */
454 { 0, 1, 1,
455 1, 0, X86_XCPT_UD },
456 { 0, 5, 2,
457 2, 1, X86_XCPT_UD },
458 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2, RTCCINTREG_MAX,
459 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_UD },
460 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2 + 1, RTCCINTREG_MAX,
461 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_DE },
462 /* negative dividend, positive divisor. */
463 { -1, -7, 2,
464 -3, -1, X86_XCPT_UD },
465 { RTCCINTREG_MIN / 2 + 1, 0, RTCCINTREG_MAX,
466 RTCCINTREG_MIN + 2, RTCCINTREG_MIN + 2, X86_XCPT_UD },
467 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MAX,
468 0, 0, X86_XCPT_DE },
469 /* positive dividend, negative divisor. */
470 { 0, 7, -2,
471 -3, 1, X86_XCPT_UD },
472 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX, RTCCINTREG_MIN,
473 RTCCINTREG_MIN, RTCCINTREG_MAX, X86_XCPT_UD },
474 { RTCCINTREG_MAX / 2 + 1, (RTCCUINTREG)RTCCINTREG_MAX+1, RTCCINTREG_MIN,
475 0, 0, X86_XCPT_DE },
476 /* negative dividend, negative divisor. */
477 { -1, -7, -2,
478 3, -1, X86_XCPT_UD },
479 { RTCCINTREG_MIN / 2, 1, RTCCINTREG_MIN,
480 RTCCINTREG_MAX, RTCCINTREG_MIN + 1, X86_XCPT_UD },
481 { RTCCINTREG_MIN / 2, 2, RTCCINTREG_MIN,
482 RTCCINTREG_MAX, RTCCINTREG_MIN + 2, X86_XCPT_UD },
483 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MIN,
484 0, 0, X86_XCPT_DE },
485 };
486
487 BS3REGCTX Ctx;
488 BS3TRAPFRAME TrapFrame;
489 unsigned i, j;
490
491 /* Ensure the structures are allocated before we sample the stack pointer. */
492 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
493 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
494
495 /*
496 * Create test context.
497 */
498 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
499 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2));
500
501 /*
502 * Do the tests twice, first with all flags set, then once again with
503 * flags cleared. The flags are not touched by my intel skylake CPU.
504 */
505 Ctx.rflags.u16 |= IDIV_CHECK_EFLAGS;
506 for (j = 0; j < 2; j++)
507 {
508 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
509 {
510 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
511 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
512 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
513 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
514
515 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
516 || ( s_aTests[i].bXcpt == X86_XCPT_UD
517 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
518 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
519 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS)
520 : TrapFrame.Ctx.rax.u != Ctx.rax.u
521 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
522 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) ) )
523 {
524 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
525 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
526 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
527 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
528 if (s_aTests[i].bXcpt == X86_XCPT_UD)
529 {
530 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
531 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
532 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
533 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
534 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
535 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
536 if ((TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS))
537 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
538 Ctx.rflags.u16 & IDIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS);
539 }
540 }
541 }
542 Ctx.rflags.u16 &= ~IDIV_CHECK_EFLAGS;
543 }
544
545 return 0;
546}
547
548
549# if ARCH_BITS == 64
550BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b)(uint8_t bMode)
551{
552 BS3REGCTX Ctx;
553 BS3REGCTX ExpectCtx;
554 BS3TRAPFRAME TrapFrame;
555 RTUINT128U au128[3];
556 PRTUINT128U pau128 = RT_ALIGN_PT(&au128[0], sizeof(RTUINT128U), PRTUINT128U);
557 bool const fSupportCX16 = RT_BOOL(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16);
558 unsigned iFlags;
559 unsigned offBuf;
560 unsigned iMatch;
561 unsigned iWorker;
562 static struct
563 {
564 bool fLocked;
565 uint8_t offUd2;
566 FNBS3FAR *pfnWorker;
567 } const s_aWorkers[] =
568 {
569 { false, 4, BS3_CMN_NM(bs3CpuInstr2_cmpxchg16b_rdi_ud2) },
570 { false, 5, BS3_CMN_NM(bs3CpuInstr2_o16_cmpxchg16b_rdi_ud2) },
571 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repz_cmpxchg16b_rdi_ud2) },
572 { false, 5, BS3_CMN_NM(bs3CpuInstr2_repnz_cmpxchg16b_rdi_ud2) },
573 { true, 1+4, BS3_CMN_NM(bs3CpuInstr2_lock_cmpxchg16b_rdi_ud2) },
574 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_o16_cmpxchg16b_rdi_ud2) },
575 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repz_cmpxchg16b_rdi_ud2) },
576 { true, 1+5, BS3_CMN_NM(bs3CpuInstr2_lock_repnz_cmpxchg16b_rdi_ud2) },
577 };
578
579 /* Ensure the structures are allocated before we sample the stack pointer. */
580 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
581 Bs3MemSet(&ExpectCtx, 0, sizeof(ExpectCtx));
582 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
583 Bs3MemSet(pau128, 0, sizeof(pau128[0]) * 2);
584
585 /*
586 * Create test context.
587 */
588 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
589 if (!fSupportCX16)
590 Bs3TestPrintf("Note! CMPXCHG16B is not supported by the CPU!\n");
591
592 /*
593 * One loop with the normal variant and one with the locked one
594 */
595 g_usBs3TestStep = 0;
596 for (iWorker = 0; iWorker < RT_ELEMENTS(s_aWorkers); iWorker++)
597 {
598 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, s_aWorkers[iWorker].pfnWorker);
599
600 /*
601 * One loop with all status flags set, and one with them clear.
602 */
603 Ctx.rflags.u16 |= X86_EFL_STATUS_BITS;
604 for (iFlags = 0; iFlags < 2; iFlags++)
605 {
606 Bs3MemCpy(&ExpectCtx, &Ctx, sizeof(ExpectCtx));
607
608 for (offBuf = 0; offBuf < sizeof(RTUINT128U); offBuf++)
609 {
610# define CX16_OLD_LO UINT64_C(0xabb6345dcc9c4bbd)
611# define CX16_OLD_HI UINT64_C(0x7b06ea35749549ab)
612# define CX16_MISMATCH_LO UINT64_C(0xbace3e3590f18981)
613# define CX16_MISMATCH_HI UINT64_C(0x9b385e8bfd5b4000)
614# define CX16_STORE_LO UINT64_C(0x5cbd27d251f6559b)
615# define CX16_STORE_HI UINT64_C(0x17ff434ed1b54963)
616
617 PRTUINT128U pBuf = (PRTUINT128U)&pau128->au8[offBuf];
618
619 ExpectCtx.rax.u = Ctx.rax.u = CX16_MISMATCH_LO;
620 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_MISMATCH_HI;
621 for (iMatch = 0; iMatch < 2; iMatch++)
622 {
623 uint8_t bExpectXcpt;
624 pBuf->s.Lo = CX16_OLD_LO;
625 pBuf->s.Hi = CX16_OLD_HI;
626 ExpectCtx.rdi.u = Ctx.rdi.u = (uintptr_t)pBuf;
627 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
628 g_usBs3TestStep++;
629 //Bs3TestPrintf("Test: iFlags=%d offBuf=%d iMatch=%u iWorker=%u\n", iFlags, offBuf, iMatch, iWorker);
630 bExpectXcpt = X86_XCPT_UD;
631 if (fSupportCX16)
632 {
633 if (offBuf & 15)
634 {
635 bExpectXcpt = X86_XCPT_GP;
636 ExpectCtx.rip.u = Ctx.rip.u;
637 ExpectCtx.rflags.u32 = Ctx.rflags.u32;
638 }
639 else
640 {
641 ExpectCtx.rax.u = CX16_OLD_LO;
642 ExpectCtx.rdx.u = CX16_OLD_HI;
643 if (iMatch & 1)
644 ExpectCtx.rflags.u32 = Ctx.rflags.u32 | X86_EFL_ZF;
645 else
646 ExpectCtx.rflags.u32 = Ctx.rflags.u32 & ~X86_EFL_ZF;
647 ExpectCtx.rip.u = Ctx.rip.u + s_aWorkers[iWorker].offUd2;
648 }
649 ExpectCtx.rflags.u32 |= X86_EFL_RF;
650 }
651 if ( !Bs3TestCheckRegCtxEx(&TrapFrame.Ctx, &ExpectCtx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/,
652 0 /*fExtraEfl*/, "lm64", 0 /*idTestStep*/)
653 || TrapFrame.bXcpt != bExpectXcpt)
654 {
655 if (TrapFrame.bXcpt != bExpectXcpt)
656 Bs3TestFailedF("Expected bXcpt=#%x, got %#x (%#x)", bExpectXcpt, TrapFrame.bXcpt, TrapFrame.uErrCd);
657 Bs3TestFailedF("^^^ iWorker=%d iFlags=%d offBuf=%d iMatch=%u\n", iWorker, iFlags, offBuf, iMatch);
658 ASMHalt();
659 }
660
661 ExpectCtx.rax.u = Ctx.rax.u = CX16_OLD_LO;
662 ExpectCtx.rdx.u = Ctx.rdx.u = CX16_OLD_HI;
663 }
664 }
665 Ctx.rflags.u16 &= ~X86_EFL_STATUS_BITS;
666 }
667 }
668
669 return 0;
670}
671# endif /* ARCH_BITS == 64 */
672
673
674#endif /* BS3_INSTANTIATING_CMN */
675
676
677
678/*
679 * Mode specific code.
680 * Mode specific code.
681 * Mode specific code.
682 */
683#ifdef BS3_INSTANTIATING_MODE
684
685
686#endif /* BS3_INSTANTIATING_MODE */
687
Note: See TracBrowser for help on using the repository browser.

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