From f09f9ef5e1dbdd9521fb05031693baf362dd555b Mon Sep 17 00:00:00 2001
From: Peter Beutner
Date: Thu, 8 Mar 2007 22:47:14 +0100
Subject: [PATCH] ntdll: Testcase for handling SIMD exceptions.
---
dlls/ntdll/tests/exception.c | 78 +++++++++++++++++++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 07f4bc6121e..58306d9a9d4 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -723,6 +723,82 @@ static void test_debugger(void)
return;
}
+static DWORD simd_fault_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
+{
+ int *stage = *(int **)(frame + 1);
+
+ got_exception++;
+
+ if( *stage == 1) {
+ /* fault while executing sse instruction */
+ context->Eip += 3; /* skip addps */
+ return ExceptionContinueExecution;
+ }
+
+ /* stage 2 - divide by zero fault */
+ if( rec->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
+ skip("system doesn't support SIMD exceptions\n");
+ else {
+ ok( rec->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS,
+ "exception code: %#x, should be %#x\n",
+ rec->ExceptionCode, STATUS_FLOAT_MULTIPLE_TRAPS);
+ ok( rec->NumberParameters == 1, "# of params: %i, should be 1\n",
+ rec->NumberParameters);
+ if( rec->NumberParameters == 1 )
+ ok( rec->ExceptionInformation[0] == 0, "param #1: %lx, should be 0\n", rec->ExceptionInformation[0]);
+ }
+
+ context->Eip += 3; /* skip divps */
+
+ return ExceptionContinueExecution;
+}
+
+static const BYTE simd_exception_test[] = {
+ 0x83, 0xec, 0x4, /* sub $0x4, %esp */
+ 0x0f, 0xae, 0x1c, 0x24, /* stmxcsr (%esp) */
+ 0x66, 0x81, 0x24, 0x24, 0xff, 0xfd, /* andw $0xfdff,(%esp) * enable divide by */
+ 0x0f, 0xae, 0x14, 0x24, /* ldmxcsr (%esp) * zero exceptions */
+ 0x6a, 0x01, /* push $0x1 */
+ 0x6a, 0x01, /* push $0x1 */
+ 0x6a, 0x01, /* push $0x1 */
+ 0x6a, 0x01, /* push $0x1 */
+ 0x0f, 0x10, 0x0c, 0x24, /* movups (%esp),%xmm1 * fill dividend */
+ 0x0f, 0x57, 0xc0, /* xorps %xmm0,%xmm0 * clear divisor */
+ 0x0f, 0x5e, 0xc8, /* divps %xmm0,%xmm1 * generate fault */
+ 0x83, 0xc4, 0x10, /* add $0x10,%esp */
+ 0x66, 0x81, 0x0c, 0x24, 0x00, 0x02, /* orw $0x200,(%esp) * disable exceptions */
+ 0x0f, 0xae, 0x14, 0x24, /* ldmxcsr (%esp) */
+ 0x83, 0xc4, 0x04, /* add $0x4,%esp */
+ 0xc3, /* ret */
+};
+
+static const BYTE sse_check[] = {
+ 0x0f, 0x58, 0xc8, /* addps %xmm0,%xmm1 */
+ 0xc3, /* ret */
+};
+
+static void test_simd_exceptions(void)
+{
+ int stage;
+
+ /* test if CPU & OS can do sse */
+ stage = 1;
+ got_exception = 0;
+ run_exception_test(simd_fault_handler, &stage, sse_check, sizeof(sse_check));
+ if(got_exception) {
+ skip("system doesn't support SSE\n");
+ return;
+ }
+
+ /* generate a SIMD exception */
+ stage = 2;
+ got_exception = 0;
+ run_exception_test(simd_fault_handler, &stage, simd_exception_test,
+ sizeof(simd_exception_test));
+ ok( got_exception == 1, "got exception: %i, should be 1\n", got_exception);
+}
+
#endif /* __i386__ */
START_TEST(exception)
@@ -787,8 +863,8 @@ START_TEST(exception)
test_prot_fault();
test_exceptions();
test_rtlraiseexcpetion();
-
test_debugger();
+ test_simd_exceptions();
VirtualFree(code_mem, 1024, MEM_RELEASE);
#endif