EDN Admin
Well-known member
Hi,
I have a little issue with 64bit and exception and FPU state.
The following code works fine in 32bit but fails in 64bit due probably to a bug in the exception frame handling code.
const unsigned int original=_controlfp(0, 0);
unsigned int restored = 0;
try
{
const unsigned int flipped=(_MCW_RC^original);
#ifndef _WIN64
unsigned int control_mask = static_cast<unsigned int>(-1);
#else
unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
#endif
<div style="margin-left:40px unsigned int changed_state = _controlfp(flipped, control_mask);
throw std::exception("Testing");
}
catch (std::exception&)
{
unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
restored = _controlfp(original, control_mask); //CALLSTACK DISPLAYED BELOW
}
unsigned int new_state = _controlfp(0, 0);
ASSERT(original==new_state));
In the catch the code is supposed to restore the state and you can check that the restored value is indeed equal to the original one.
However the new_state after the catch is equal to changed_state and not the original as expected.
As far as I can see the state is saved after the exception is thrown and restored after the last line of code in the catch by some code in NTDLL (restoration of xmm register done there too).
The call stack in the catch code shows:
test.exe!test()::catch$0() Line 69 C++
msvcr80d.dll!_CallSettingFrame() Line 36 Asm
msvcr80d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept=0x000000000012cfd0) Line 1342 + 0x15 bytes C++
> ntdll.dll!0000000077ef3712()
Then once done the code continues and end up doing...
0000000077EF3799 movdqa xmm14,xmmword ptr [rcx+280h]
0000000077EF37A2 movdqa xmm15,xmmword ptr [rcx+290h]
0000000077EF37AB ldmxcsr dword ptr [rcx+34h]
That last line restores the status that was present at the time of the exception I think invalidating the whole process.
Any advice on how to fix that if its possible at all.
(Code above compiled and tested in 64bit with VS2005 SP1 on an AMD64 machine)
Thanks.
Laurent
View the full article
I have a little issue with 64bit and exception and FPU state.
The following code works fine in 32bit but fails in 64bit due probably to a bug in the exception frame handling code.
const unsigned int original=_controlfp(0, 0);
unsigned int restored = 0;
try
{
const unsigned int flipped=(_MCW_RC^original);
#ifndef _WIN64
unsigned int control_mask = static_cast<unsigned int>(-1);
#else
unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
#endif
<div style="margin-left:40px unsigned int changed_state = _controlfp(flipped, control_mask);
throw std::exception("Testing");
}
catch (std::exception&)
{
unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
restored = _controlfp(original, control_mask); //CALLSTACK DISPLAYED BELOW
}
unsigned int new_state = _controlfp(0, 0);
ASSERT(original==new_state));
In the catch the code is supposed to restore the state and you can check that the restored value is indeed equal to the original one.
However the new_state after the catch is equal to changed_state and not the original as expected.
As far as I can see the state is saved after the exception is thrown and restored after the last line of code in the catch by some code in NTDLL (restoration of xmm register done there too).
The call stack in the catch code shows:
test.exe!test()::catch$0() Line 69 C++
msvcr80d.dll!_CallSettingFrame() Line 36 Asm
msvcr80d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept=0x000000000012cfd0) Line 1342 + 0x15 bytes C++
> ntdll.dll!0000000077ef3712()
Then once done the code continues and end up doing...
0000000077EF3799 movdqa xmm14,xmmword ptr [rcx+280h]
0000000077EF37A2 movdqa xmm15,xmmword ptr [rcx+290h]
0000000077EF37AB ldmxcsr dword ptr [rcx+34h]
That last line restores the status that was present at the time of the exception I think invalidating the whole process.
Any advice on how to fix that if its possible at all.
(Code above compiled and tested in 64bit with VS2005 SP1 on an AMD64 machine)
Thanks.
Laurent
View the full article