VirtualBox

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

Last change on this file since 64226 was 62455, checked in by vboxsync, 8 years ago

bs3-cpu-instr-2: Test 2 operand imul variant.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.7 KB
Line 
1/* $Id: bs3-cpu-instr-2-template.c 62455 2016-07-22 15:55:14Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-instr-2, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2016 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#endif
54
55
56/*********************************************************************************************************************************
57* Global Variables *
58*********************************************************************************************************************************/
59#ifdef BS3_INSTANTIATING_CMN
60
61#endif /* BS3_INSTANTIATING_CMN - global */
62
63
64/*
65 * Common code.
66 * Common code.
67 * Common code.
68 */
69#ifdef BS3_INSTANTIATING_CMN
70
71BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_mul)(uint8_t bMode)
72{
73#define MUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
74#define MUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
75
76 static const struct
77 {
78 RTCCUINTREG uInAX;
79 RTCCUINTREG uInBX;
80 RTCCUINTREG uOutDX;
81 RTCCUINTREG uOutAX;
82 uint16_t fFlags;
83 } s_aTests[] =
84 {
85 { 1, 1,
86 0, 1, 0 },
87 { 2, 2,
88 0, 4, 0 },
89 { RTCCUINTREG_MAX, RTCCUINTREG_MAX,
90 RTCCUINTREG_MAX-1, 1, X86_EFL_CF | X86_EFL_OF },
91 { RTCCINTREG_MAX, RTCCINTREG_MAX,
92 RTCCINTREG_MAX / 2, 1, X86_EFL_CF | X86_EFL_OF },
93 { 1, RTCCUINTREG_MAX,
94 0, RTCCUINTREG_MAX, X86_EFL_PF | X86_EFL_SF },
95 { 1, RTCCINTREG_MAX,
96 0, RTCCINTREG_MAX, X86_EFL_PF },
97 { 2, RTCCINTREG_MAX,
98 0, RTCCUINTREG_MAX - 1, X86_EFL_SF },
99 { RTCCINTREG_MAX + 1, 2,
100 1, 0, X86_EFL_PF | X86_EFL_CF | X86_EFL_OF },
101 { RTCCINTREG_MAX / 2 + 1, 3,
102 0, (RTCCINTREG_MAX / 2 + 1) * 3, X86_EFL_PF | X86_EFL_SF },
103 };
104
105 BS3REGCTX Ctx;
106 BS3TRAPFRAME TrapFrame;
107 unsigned i, j, k;
108
109 /* Ensure the structures are allocated before we sample the stack pointer. */
110 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
111 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
112
113 /*
114 * Create test context.
115 */
116 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
117 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_mul_xBX_ud2));
118 for (k = 0; k < 2; k++)
119 {
120 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
121 for (j = 0; j < 2; j++)
122 {
123 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
124 {
125 if (k == 0)
126 {
127 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
128 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
129 }
130 else
131 {
132 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
133 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
134 }
135 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
136 if (TrapFrame.bXcpt != X86_XCPT_UD)
137 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
138 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
139 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
140 || (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
141 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
142 {
143 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
144 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
145
146 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
147 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
148 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
149 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
150 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
151 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
152 if ( (TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO))
153 != (s_aTests[i].fFlags & MUL_CHECK_EFLAGS) )
154 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & MUL_CHECK_EFLAGS,
155 TrapFrame.Ctx.rflags.u16 & (MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO));
156 }
157 }
158 Ctx.rflags.u16 &= ~(MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO);
159 }
160 }
161
162 return 0;
163}
164
165
166BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_imul)(uint8_t bMode)
167{
168#define IMUL_CHECK_EFLAGS_ZERO (uint16_t)(X86_EFL_AF | X86_EFL_ZF)
169#define IMUL_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF)
170 static const struct
171 {
172 RTCCUINTREG uInAX;
173 RTCCUINTREG uInBX;
174 RTCCUINTREG uOutDX;
175 RTCCUINTREG uOutAX;
176 uint16_t fFlags;
177 } s_aTests[] =
178 {
179 /* two positive values. */
180 { 1, 1,
181 0, 1, 0 },
182 { 2, 2,
183 0, 4, 0 },
184 { RTCCINTREG_MAX, RTCCINTREG_MAX,
185 RTCCINTREG_MAX/2, 1, X86_EFL_CF | X86_EFL_OF },
186 { 1, RTCCINTREG_MAX,
187 0, RTCCINTREG_MAX, X86_EFL_PF },
188 { 2, RTCCINTREG_MAX,
189 0, RTCCUINTREG_MAX - 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF },
190 { 2, RTCCINTREG_MAX / 2,
191 0, RTCCINTREG_MAX - 1U, 0 },
192 { 2, (RTCCINTREG_MAX / 2 + 1),
193 0, RTCCINTREG_MAX + 1U, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
194 { 4, (RTCCINTREG_MAX / 2 + 1),
195 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
196
197 /* negative and positive */
198 { -4, 3,
199 -1, -12, X86_EFL_SF },
200 { 32, -127,
201 -1, -4064, X86_EFL_SF },
202 { RTCCINTREG_MIN, 1,
203 -1, RTCCINTREG_MIN, X86_EFL_SF | X86_EFL_PF },
204 { RTCCINTREG_MIN, 2,
205 -1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
206 { RTCCINTREG_MIN, 3,
207 -2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
208 { RTCCINTREG_MIN, 4,
209 -2, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
210 { RTCCINTREG_MIN, RTCCINTREG_MAX,
211 RTCCINTREG_MIN / 2, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF },
212 { RTCCINTREG_MIN, RTCCINTREG_MAX - 1,
213 RTCCINTREG_MIN / 2 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
214
215 /* two negative values. */
216 { -4, -63,
217 0, 252, X86_EFL_PF },
218 { RTCCINTREG_MIN, RTCCINTREG_MIN,
219 RTCCUINTREG_MAX / 4 + 1, 0, X86_EFL_CF | X86_EFL_OF | X86_EFL_PF },
220 { RTCCINTREG_MIN, RTCCINTREG_MIN + 1,
221 RTCCUINTREG_MAX / 4, RTCCINTREG_MIN, X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_PF},
222 { RTCCINTREG_MIN + 1, RTCCINTREG_MIN + 1,
223 RTCCUINTREG_MAX / 4, 1, X86_EFL_CF | X86_EFL_OF },
224
225 };
226
227 BS3REGCTX Ctx;
228 BS3TRAPFRAME TrapFrame;
229 unsigned i, j, k;
230
231 /* Ensure the structures are allocated before we sample the stack pointer. */
232 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
233 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
234
235 /*
236 * Create test context.
237 */
238 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
239 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xBX_ud2));
240
241 for (k = 0; k < 2; k++)
242 {
243 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
244 for (j = 0; j < 2; j++)
245 {
246 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
247 {
248 if (k == 0)
249 {
250 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
251 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
252 }
253 else
254 {
255 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
256 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
257 }
258 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
259 if (TrapFrame.bXcpt != X86_XCPT_UD)
260 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
261 else if ( TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
262 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
263 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
264 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
265 {
266 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
267 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
268
269 if (TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
270 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
271 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
272 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
273 Bs3TestFailedF("Expected xDX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
274 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
275 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
276 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
277 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
278 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
279 }
280 }
281 }
282 }
283
284 /*
285 * Repeat for the truncating two operand version.
286 */
287 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_imul_xCX_xBX_ud2));
288
289 for (k = 0; k < 2; k++)
290 {
291 Ctx.rflags.u16 |= MUL_CHECK_EFLAGS | MUL_CHECK_EFLAGS_ZERO;
292 for (j = 0; j < 2; j++)
293 {
294 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
295 {
296 if (k == 0)
297 {
298 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
299 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
300 }
301 else
302 {
303 Ctx.rcx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
304 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
305 }
306 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
307 if (TrapFrame.bXcpt != X86_XCPT_UD)
308 Bs3TestFailedF("Expected #UD got %#x", TrapFrame.bXcpt);
309 else if ( TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
310 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
311 || TrapFrame.Ctx.rbx.u != Ctx.rbx.u
312 || (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
313 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
314 {
315 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT " * %#" RTCCUINTREG_XFMT,
316 i, s_aTests[i].uInAX, s_aTests[i].uInBX);
317
318 if (TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX)
319 Bs3TestFailedF("Expected xAX = %#RX" RT_XSTR(ARCH_BITS) " got %#RX" RT_XSTR(ARCH_BITS),
320 s_aTests[i].uOutAX, TrapFrame.Ctx.rcx.RT_CONCAT(u,ARCH_BITS));
321 if ( (TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO))
322 != (s_aTests[i].fFlags & IMUL_CHECK_EFLAGS) )
323 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16", s_aTests[i].fFlags & IMUL_CHECK_EFLAGS,
324 TrapFrame.Ctx.rflags.u16 & (IMUL_CHECK_EFLAGS | IMUL_CHECK_EFLAGS_ZERO));
325 }
326 }
327 }
328 }
329
330 return 0;
331}
332
333
334BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_div)(uint8_t bMode)
335{
336#define DIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
337 static const struct
338 {
339 RTCCUINTREG uInDX;
340 RTCCUINTREG uInAX;
341 RTCCUINTREG uInBX;
342 RTCCUINTREG uOutAX;
343 RTCCUINTREG uOutDX;
344 uint8_t bXcpt;
345 } s_aTests[] =
346 {
347 { 0, 1, 1,
348 1, 0, X86_XCPT_UD },
349 { 0, 5, 2,
350 2, 1, X86_XCPT_UD },
351 { 0, 0, 0,
352 0, 0, X86_XCPT_DE },
353 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 0,
354 0, 0, X86_XCPT_DE },
355 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, 1,
356 0, 0, X86_XCPT_DE },
357 { RTCCUINTREG_MAX, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
358 0, 0, X86_XCPT_DE },
359 { RTCCUINTREG_MAX - 1, RTCCUINTREG_MAX, RTCCUINTREG_MAX,
360 RTCCUINTREG_MAX, RTCCUINTREG_MAX - 1, X86_XCPT_UD },
361 };
362
363 BS3REGCTX Ctx;
364 BS3TRAPFRAME TrapFrame;
365 unsigned i, j;
366
367 /* Ensure the structures are allocated before we sample the stack pointer. */
368 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
369 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
370
371 /*
372 * Create test context.
373 */
374 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
375 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_div_xBX_ud2));
376
377 /*
378 * Do the tests twice, first with all flags set, then once again with
379 * flags cleared. The flags are not touched by my intel skylake CPU.
380 */
381 Ctx.rflags.u16 |= DIV_CHECK_EFLAGS;
382 for (j = 0; j < 2; j++)
383 {
384 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
385 {
386 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
387 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
388 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
389 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
390
391 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
392 || ( s_aTests[i].bXcpt == X86_XCPT_UD
393 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
394 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
395 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS)
396 : TrapFrame.Ctx.rax.u != Ctx.rax.u
397 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
398 || (TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS) ) )
399 {
400 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
401 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
402 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
403 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
404 if (s_aTests[i].bXcpt == X86_XCPT_UD)
405 {
406 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
407 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
408 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
409 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
410 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
411 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
412 if ((TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & DIV_CHECK_EFLAGS))
413 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
414 Ctx.rflags.u16 & DIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & DIV_CHECK_EFLAGS);
415 }
416 }
417 }
418 Ctx.rflags.u16 &= ~DIV_CHECK_EFLAGS;
419 }
420
421 return 0;
422}
423
424
425
426BS3_DECL_FAR(uint8_t) BS3_CMN_NM(bs3CpuInstr2_idiv)(uint8_t bMode)
427{
428#define IDIV_CHECK_EFLAGS (uint16_t)(X86_EFL_CF | X86_EFL_OF | X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF)
429 static const struct
430 {
431 RTCCUINTREG uInDX;
432 RTCCUINTREG uInAX;
433 RTCCUINTREG uInBX;
434 RTCCUINTREG uOutAX;
435 RTCCUINTREG uOutDX;
436 uint8_t bXcpt;
437 } s_aTests[] =
438 {
439 { 0, 0, 0,
440 0, 0, X86_XCPT_DE },
441 { RTCCINTREG_MAX, RTCCINTREG_MAX, 0,
442 0, 0, X86_XCPT_DE },
443 /* two positive values. */
444 { 0, 1, 1,
445 1, 0, X86_XCPT_UD },
446 { 0, 5, 2,
447 2, 1, X86_XCPT_UD },
448 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2, RTCCINTREG_MAX,
449 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_UD },
450 { RTCCINTREG_MAX / 2, RTCCUINTREG_MAX / 2 + 1, RTCCINTREG_MAX,
451 RTCCINTREG_MAX, RTCCINTREG_MAX - 1, X86_XCPT_DE },
452 /* negative dividend, positive divisor. */
453 { -1, -7, 2,
454 -3, -1, X86_XCPT_UD },
455 { RTCCINTREG_MIN / 2 + 1, 0, RTCCINTREG_MAX,
456 RTCCINTREG_MIN + 2, RTCCINTREG_MIN + 2, X86_XCPT_UD },
457 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MAX,
458 0, 0, X86_XCPT_DE },
459 /* positive dividend, negative divisor. */
460 { 0, 7, -2,
461 -3, 1, X86_XCPT_UD },
462 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX, RTCCINTREG_MIN,
463 RTCCINTREG_MIN, RTCCINTREG_MAX, X86_XCPT_UD },
464 { RTCCINTREG_MAX / 2 + 1, RTCCINTREG_MAX+1, RTCCINTREG_MIN,
465 0, 0, X86_XCPT_DE },
466 /* negative dividend, negative divisor. */
467 { -1, -7, -2,
468 3, -1, X86_XCPT_UD },
469 { RTCCINTREG_MIN / 2, 1, RTCCINTREG_MIN,
470 RTCCINTREG_MAX, RTCCINTREG_MIN + 1, X86_XCPT_UD },
471 { RTCCINTREG_MIN / 2, 2, RTCCINTREG_MIN,
472 RTCCINTREG_MAX, RTCCINTREG_MIN + 2, X86_XCPT_UD },
473 { RTCCINTREG_MIN / 2, 0, RTCCINTREG_MIN,
474 0, 0, X86_XCPT_DE },
475 };
476
477 BS3REGCTX Ctx;
478 BS3TRAPFRAME TrapFrame;
479 unsigned i, j;
480
481 /* Ensure the structures are allocated before we sample the stack pointer. */
482 Bs3MemSet(&Ctx, 0, sizeof(Ctx));
483 Bs3MemSet(&TrapFrame, 0, sizeof(TrapFrame));
484
485 /*
486 * Create test context.
487 */
488 Bs3RegCtxSaveEx(&Ctx, bMode, 512);
489 Bs3RegCtxSetRipCsFromCurPtr(&Ctx, BS3_CMN_NM(bs3CpuInstr2_idiv_xBX_ud2));
490
491 /*
492 * Do the tests twice, first with all flags set, then once again with
493 * flags cleared. The flags are not touched by my intel skylake CPU.
494 */
495 Ctx.rflags.u16 |= IDIV_CHECK_EFLAGS;
496 for (j = 0; j < 2; j++)
497 {
498 for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
499 {
500 Ctx.rax.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInAX;
501 Ctx.rdx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInDX;
502 Ctx.rbx.RT_CONCAT(u,ARCH_BITS) = s_aTests[i].uInBX;
503 Bs3TrapSetJmpAndRestore(&Ctx, &TrapFrame);
504
505 if ( TrapFrame.bXcpt != s_aTests[i].bXcpt
506 || ( s_aTests[i].bXcpt == X86_XCPT_UD
507 ? TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutAX
508 || TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX
509 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS)
510 : TrapFrame.Ctx.rax.u != Ctx.rax.u
511 || TrapFrame.Ctx.rdx.u != Ctx.rdx.u
512 || (TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) ) )
513 {
514 Bs3TestFailedF("test #%i failed: input %#" RTCCUINTREG_XFMT ":%" RTCCUINTREG_XFMT " / %#" RTCCUINTREG_XFMT,
515 i, s_aTests[i].uInDX, s_aTests[i].uInAX, s_aTests[i].uInBX);
516 if (TrapFrame.bXcpt != s_aTests[i].bXcpt)
517 Bs3TestFailedF("Expected bXcpt = %#x, got %#x", s_aTests[i].bXcpt, TrapFrame.bXcpt);
518 if (s_aTests[i].bXcpt == X86_XCPT_UD)
519 {
520 if (TrapFrame.Ctx.rax.RT_CONCAT(u, ARCH_BITS) != s_aTests[i].uOutAX)
521 Bs3TestFailedF("Expected xAX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
522 s_aTests[i].uOutAX, TrapFrame.Ctx.rax.RT_CONCAT(u,ARCH_BITS));
523 if (TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS) != s_aTests[i].uOutDX)
524 Bs3TestFailedF("Expected xDX = %#" RTCCUINTREG_XFMT ", got %#" RTCCUINTREG_XFMT,
525 s_aTests[i].uOutDX, TrapFrame.Ctx.rdx.RT_CONCAT(u,ARCH_BITS));
526 if ((TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS) != (Ctx.rflags.u16 & IDIV_CHECK_EFLAGS))
527 Bs3TestFailedF("Expected EFLAGS = %#06RX16, got %#06RX16",
528 Ctx.rflags.u16 & IDIV_CHECK_EFLAGS, TrapFrame.Ctx.rflags.u16 & IDIV_CHECK_EFLAGS);
529 }
530 }
531 }
532 Ctx.rflags.u16 &= ~IDIV_CHECK_EFLAGS;
533 }
534
535 return 0;
536}
537
538
539#endif /* BS3_INSTANTIATING_CMN */
540
541
542
543/*
544 * Mode specific code.
545 * Mode specific code.
546 * Mode specific code.
547 */
548#ifdef BS3_INSTANTIATING_MODE
549
550
551#endif /* BS3_INSTANTIATING_MODE */
552
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