Discussion:
Cannot trap divide by zero in xmm register
(too old to reply)
Anthony Walter
2017-06-20 12:57:15 UTC
Permalink
Raw Message
I am having a problem with unrecoverable errors in external code,
presumably generated by the video driver, crashing my programs. I cannot
trap these errors with try..except blocks. Here is a capture of the
assembler window with ** marking the line where the error occurs.

00007FFFEA79016F 4898 cltq
**00007FFFEA790171 f20f5e44c430 divsd 0x30(%rsp,%rax,8),%xmm0
00007FFFEA790177 f20f118424f8000000 movsd %xmm0,0xf8(%rsp)
00007FFFEA790180 f20f118424f0000000 movsd %xmm0,0xf0(%rsp)
00007FFFEA790189 f20f118424e8000000 movsd %xmm0,0xe8(%rsp)

In pascal code I am attempting to link a glsl program (part of OpenGL) when
the uncatchable and unrecoverable error occurs.

*function* TShaderProgram.Link: Boolean;
*var*
I: GLint;
S: string;
*begin*
*if* Flinked *then*
Exit(False);
*if* FAttachCount < 2 *then*
Exit(False);
FLinked := True;
*// Sometimes the uncatchable error happens here*
glLinkProgram(FHandle);
glGetProgramiv(FHandle, GL_LINK_STATUS, @I);
FValid := I = GL_TRUE;
*if* *not* FValid *then*
*begin*
FErrorObject := Self;
glGetProgramiv(FHandle, GL_INFO_LOG_LENGTH, @I);
*if* I > 0 *then*
*begin*
SetLength(S, I);
glGetProgramInfoLog(FHandle, I, @I, PChar(S));
*end*
*else*
S := 'Unknown error';
FErrorString := S;
*end*;
*end*;

In this code I am attempting to link user defined glsl vertex and fragment
shaders to generate a valid glsl program object. Sometimes either the
vertex or fragment shader contains bad code, but it shouldn't bring down my
entire pascal application. I've written and used these same shaders in c#
using mono and I've never had them crash my mono applications. Is there
some setting in fpc or in lazarus to handle these types of errors in the
XMM registers gracefully?

To give you an idea of what I am doing, here is a screen recording of made
earlier of these same shader programs running without crashing my
application when using mono.

http://cache.getlazarus.org/videos/bare-csharp.mp4
Anthony Walter
2017-06-20 14:53:32 UTC
Permalink
Raw Message
Some progress ... Since this is an OpenGL app I had been
setting Set8087CW($133F) to prevent FPU errors from showing as exceptions.
When I omit Set8087CW I get EDivByZero an exception, but my program is
still in an unusable state.

Since this error occurs in the SSE XMM registers, I think I should also be
using the SetSSECSR function. Does anyone have any details about how this
function works in relation to XMM registers and rounding or divide by zero
errors and how it could be applied in my situation?
Henry Vermaak
2017-06-20 15:12:18 UTC
Permalink
Raw Message
Post by Anthony Walter
Some progress ... Since this is an OpenGL app I had been
setting Set8087CW($133F) to prevent FPU errors from showing as exceptions.
When I omit Set8087CW I get EDivByZero an exception, but my program is
still in an unusable state.
Since this error occurs in the SSE XMM registers, I think I should also be
using the SetSSECSR function. Does anyone have any details about how this
function works in relation to XMM registers and rounding or divide by zero
errors and how it could be applied in my situation?
I use this for all my programs that use C libraries:

{$if defined(cpui386) or defined(cpux86_64)}
SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]);
{$ifend}

Works fine with libs like OpenCV, etc.

Henry
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/
Henry Vermaak
2017-06-20 15:20:52 UTC
Permalink
Raw Message
Post by Henry Vermaak
Post by Anthony Walter
Some progress ... Since this is an OpenGL app I had been
setting Set8087CW($133F) to prevent FPU errors from showing as exceptions.
When I omit Set8087CW I get EDivByZero an exception, but my program is
still in an unusable state.
Since this error occurs in the SSE XMM registers, I think I should also be
using the SetSSECSR function. Does anyone have any details about how this
function works in relation to XMM registers and rounding or divide by zero
errors and how it could be applied in my situation?
{$if defined(cpui386) or defined(cpux86_64)}
SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]);
{$ifend}
Works fine with libs like OpenCV, etc.
Sorry, meant to add that this will also set the flags in MXCSR if you
look at the implementation of SetExceptionMask().

Henry
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-deve
Anthony Walter
2017-06-20 17:11:02 UTC
Permalink
Raw Message
Wow, that fixed it. Thanks Henry!

Loading...