From 6a03e618df280dcfd8fce1223a871fbd89b227cb Mon Sep 17 00:00:00 2001 From: Qian Hong Date: Thu, 3 Dec 2015 00:06:50 +0800 Subject: [PATCH] ntdll/tests: Add SIMD exception test for floating point invalid operation fault. Signed-off-by: Qian Hong Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/exception.c | 57 ++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 84779881676..221d86a9d85 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -1015,22 +1015,25 @@ static DWORD simd_fault_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_R 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 || broken(is_wow64 && rec->NumberParameters == 2), - "# 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]); + else if ( *stage == 2 || *stage == 3 ) { + /* stage 2 - divide by zero fault */ + /* stage 3 - invalid operation 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 || broken(is_wow64 && rec->NumberParameters == 2), + "# 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 */ } - - context->Eip += 3; /* skip divps */ + else + ok(FALSE, "unexpected stage %x\n", *stage); return ExceptionContinueExecution; } @@ -1054,6 +1057,21 @@ static const BYTE simd_exception_test[] = { 0xc3, /* ret */ }; +static const BYTE simd_exception_test2[] = { + 0x83, 0xec, 0x4, /* sub $0x4, %esp */ + 0x0f, 0xae, 0x1c, 0x24, /* stmxcsr (%esp) */ + 0x8b, 0x04, 0x24, /* mov (%esp),%eax * store mxcsr */ + 0x66, 0x81, 0x24, 0x24, 0x7f, 0xff, /* andw $0xff7f,(%esp) * enable invalid */ + 0x0f, 0xae, 0x14, 0x24, /* ldmxcsr (%esp) * operation exceptions */ + 0x0f, 0x57, 0xc9, /* xorps %xmm1,%xmm1 * clear dividend */ + 0x0f, 0x57, 0xc0, /* xorps %xmm0,%xmm0 * clear divisor */ + 0x0f, 0x5e, 0xc8, /* divps %xmm0,%xmm1 * generate fault */ + 0x89, 0x04, 0x24, /* mov %eax,(%esp) * restore to old mxcsr */ + 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 */ @@ -1077,7 +1095,14 @@ static void test_simd_exceptions(void) got_exception = 0; run_exception_test(simd_fault_handler, &stage, simd_exception_test, sizeof(simd_exception_test), 0); - ok( got_exception == 1, "got exception: %i, should be 1\n", got_exception); + ok(got_exception == 1, "got exception: %i, should be 1\n", got_exception); + + /* generate a SIMD exception, test FPE_FLTINV */ + stage = 3; + got_exception = 0; + run_exception_test(simd_fault_handler, &stage, simd_exception_test2, + sizeof(simd_exception_test2), 0); + ok(got_exception == 1, "got exception: %i, should be 1\n", got_exception); } struct fpu_exception_info