Recent

Author Topic: "Invalid floating point operation" with Set8087CW($133f)  (Read 14388 times)

scribly

  • Jr. Member
  • **
  • Posts: 68
"Invalid floating point operation" with Set8087CW($133f)
« on: February 05, 2009, 02:37:37 am »
I'm trying to port my application from delphi to freepascal, but one of the threads does some extensive floating point comparing on raw data.
In Delphi I used Set8087CW($133f) to get rid of the situations where the raw data is corrupt, but with lazarus/fpc I keep getting the "Invalid floating point operation" exception.

Putting the compares between a try/except is no solution as the routine has to go through 14GB of floating point only data, and the added delay of the try/except on every single item slows it down so it's unusable.

Is there another way to disable floating point exceptions from being risen ?

OS: windows 64

Edit: Nevermind, I found it out myself. FPC makes use of SSE, so I had to use SetSSECSR to set the appropriate exception masks
« Last Edit: February 05, 2009, 02:51:06 am by scribly »

PeterS

  • New Member
  • *
  • Posts: 12
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #1 on: February 15, 2015, 06:49:26 pm »
I am currently converting an application from Delphi 5 to Lazarus (actually 1.2.6).
I have lots of strange FPU Exceptions which I cannot handle.
So I searched a lot on the www and I casually came across  this - yes, very old - Topic.
I hope it helps me making my app run under Lazarus.

But I have an additional question - do I now have to set both
- Set8087CW
- SetSSECSR   
  ???

Does anybody have a hint ot some links for me ?
So I can correctly set these FPU flags, on modern CPUs ...

Thanks !

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #2 on: February 15, 2015, 07:10:43 pm »
SetExceptionMask sets the exception mask for both: FPU, and -if supported- SSE.

If you are sure your app is to be used on newer CPUs only, you can enforce using SSE2, for instance , by passing -CfSSE2 to the compiler (somewhere around Compiler Options - Other - Custom Settings, might be different on Lazarus 1.2.6).
« Last Edit: February 15, 2015, 07:12:16 pm by engkin »

PeterS

  • New Member
  • *
  • Posts: 12
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #3 on: February 15, 2015, 07:52:43 pm »
SetExceptionMask sets the exception mask for both: FPU, and -if supported- SSE.

If you are sure your app is to be used on newer CPUs only, you can enforce using SSE2, for instance , by passing -CfSSE2 to the compiler (somewhere around Compiler Options - Other - Custom Settings, might be different on Lazarus 1.2.6).
Thank You, this is very helpful.
setexceptionmask() makes things easier.
I would never force the app onto SSE/SSE2, makes no sense to me.

I would like to make the app run on both "old 8087" and on SSE / SSE2
Does Lazarus automatically make this possible ?
Does it detect SSE / SSE2 and if not present, execute "8087 code" ?

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #4 on: February 15, 2015, 09:17:07 pm »
I would like to make the app run on both "old 8087" and on SSE / SSE2
Does Lazarus automatically make this possible ?
Does it detect SSE / SSE2 and if not present, execute "8087 code" ?

As far as I know, the default for applications that target 32bit Intel CPU is 8087 code, while on 64bit Intel CPU it uses SSE code. It does provide a way to detect SSE presence: has_sse_support ( and has_mmx_support, if you care) to help you switch to your own SSE assembly instructions. But it does not, AFAIK, include both SSE and 8087 code in the same executable. SetExceptionMask is the only place where it uses has_sse_support in the RTL source code on my system. I don't know about the trunk.


PeterS

  • New Member
  • *
  • Posts: 12
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #5 on: February 15, 2015, 10:27:23 pm »
As far as I know, the default for applications that target 32bit Intel CPU is 8087 code, while on 64bit Intel CPU it uses SSE code. It does provide a way to detect SSE presence: has_sse_support ( and has_mmx_support, if you care) to help you switch to your own SSE assembly instructions. But it does not, AFAIK, include both SSE and 8087 code in the same executable. SetExceptionMask is the only place where it uses has_sse_support in the RTL source code on my system. I don't know about the trunk.

Thanks for Your help !

If target is SSE on a 64 Bit CPU then the problems I have may arise from this.
My Project still compiles under Delphi 5. But crashes under Lazarus.
Too many lines of code, this will take some time to find out wether it's only the FPU or/and some other code .. 

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #6 on: February 15, 2015, 10:55:27 pm »
If target is SSE on a 64 Bit CPU then the problems I have may arise from this.

I don't know if it works on 64bit but you can try to enforce 8087 code using: -CfX87
Delphi mode is worth trying: -Mdelphi

Edit:
I suggest that you use 32bit Lazarus/FPC and to produce a 32bit conversion first.
« Last Edit: February 15, 2015, 11:14:24 pm by engkin »

PeterS

  • New Member
  • *
  • Posts: 12
Re: "Invalid floating point operation" with Set8087CW($133f)
« Reply #7 on: February 15, 2015, 11:38:08 pm »
I don't know if it works on 64bit but you can try to enforce 8087 code using: -CfX87
Delphi mode is worth trying: -Mdelphi

Edit:
I suggest that you use 32bit Lazarus/FPC and to produce a 32bit conversion first.

Yes, I use the 32bit Lazarus, and target is a 32bit exe.
I first added the -CfX87  but the crashes do still occur.

The -Mdelphi is not required because I do a file-by-file decision on this.
Lots of units do already work in the objfpc mode
since I {$IFDEF} the differences betweeen Lazarus and ol' Delphi 5 ... ;-)

The whole project does compile already, since a week now.
So I must track down to the root of the first exception that occurs
to find out what's going wrong. There's lots of Set8087CW() in the code
and maybe I have to replace all these calls with SetExceptionMask()