FPU error in psplink

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

FPU error in psplink

Post by Ghoti »

Hi folks,

I have this error in psplink:

Code: Select all

Exception - FPU Exception (IUV)
Thread ID - 0x00206A2D
Th Name   - user_main
Module ID - 0x017DA21F
Mod Name  - "Raze"
EPC       - 0x089113B4
Cause     - 0x1000003C
BadVAddr  - 0x00000000
Status    - 0x20008613
zr:0x00000000 at:0x08DC0000 v0:0x00000085 v1:0x00000035
a0:0x09F7FCFC a1:0x003BFE34 a2:0x42BBFE34 a3:0x00000000
t0:0x00000085 t1:0x00000000 t2:0x09F7FC98 t3:0x355EF4E8
now it crashes in this code:

Code: Select all

void Vector3D::Normalize(ScePspFVector3& vec1){
	float lenght = (float)sqrt((double)(vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z));
	vec1.x /= lenght;
	vec1.y /= lenght;
	vec1.z /= lenght;
};
Now this code works because it correctly does his job for other values but with this vector:
0.000000f, 0.00000f, -0.1000000f
it does not work.
I have tried to not divide when both length is zero or the vec attribute is zero but still that error.

any ideas? it's driving me crazy :S

greets ghoti
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

please output the assembly code at this point.

by the way could you try to avoid "double" ? using it will compute in a software mode (double are emulated through integer computation), which is probably not what you want.
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

Post by Ghoti »

Hi, well I did not cast anything before this, hoped it was the problem. If i don't use the casts it still works fine for theother values.
the sqrt command needs doubles so is there a better way to avoid the software mode ? (if i don't cast will that do the trick , like i did before trying to cast?)

I can't output the assembly code at this point because I never got the debugger to work.

any ideas ?
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

void Vector3D::Normalize(ScePspFVector3& vec1){
float lenght = (float)sqrt((double)(vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z));
vec1.x /= lenght;
vec1.y /= lenght;
vec1.z /= lenght;
};

Code: Select all


void Vector3D::Normalize(ScePspFVector3& vec1){
asm (
" lv.s S000, 0+%0\n"
" lv.s S001, 4+%0\n"
" lv.s S002, 8+%0\n"
" vdot.t S003, C000, C000\n" // length = vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z
" vrcp.s S003, S003\n" // length = 1/length 
" vscl.t C000, S003\n" // vec1.x /= length; vec1.y /= length; vec1.z /= length;
" sv.s S000, 0+%0\n"
" sv.s S001, 4+%0\n"
" sv.s S002, 8+%0\n"
: "+m"(vec1) : : "memory");
}

libpspmath.zip from MrMr[Ice] has stuff like that, if you really want to have a fast library.
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

Post by Ghoti »

k well I'm not into asm at all so i replaced my function for yours(I thought I should do that i guess)

and I get also errors with the FPU only now in compiler time:
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s: Assembler messages:
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: Improper VFPU register prefix 's'
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: Improper VFPU register number (003)
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: illegal operands `vmul.t'

maybe I should not have done that but I could not find a difference with the other code. hope this helps a bit :s
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

fsqrt ?
Last edited by hlide on Sun Jul 29, 2007 8:18 am, edited 1 time in total.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Ghoti wrote:k well I'm not into asm at all so i replaced my function for yours(I thought I should do that i guess)

and I get also errors with the FPU only now in compiler time:
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s: Assembler messages:
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: Improper VFPU register prefix 's'
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: Improper VFPU register number (003)
/cygdrive/c/DOCUME~1/Reinier/LOCALS~1/Temp/ccERFXrw.s:328: Error: illegal operands `vmul.t'

maybe I should not have done that but I could not find a difference with the other code. hope this helps a bit :s
not vmul.t but vscl.t indeed

well this is just to tell you there is a libpspmath.zip which has a lot of function about 3d stuff and which are very quick.

and dont forget to enable VFPU in your thread if you plan to use them
Last edited by hlide on Sun Jul 29, 2007 8:28 am, edited 1 time in total.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Code: Select all

void Vector3D::Normalize(ScePspFVector3& vec1){
   float length = fsqrt(vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z);
   vec1.x /= length;
   vec1.y /= length;
   vec1.z /= length;
};
that should be okay but still slower than one in libpspmath.zip ;P.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Code: Select all

void Vector3D::Normalize(ScePspFVector3& vec1){
   float x2 = vec1.x * vec1.x; LOG("x2 = %f\n", x2);
   float y2 = vec1.y * vec1.y; LOG("y2 = %f\n", y2);
   float z2 = vec1.z * vec1.z; LOG("z2 = %f\n", z2);
   float length2 = vec1.x + vec1.y + vec1.z; LOG("l2 = %f\n", length2);
   float length = fsqrt(length2); LOG("l = %f\n", length);
   vec1.x /= length; LOG("vec1.x = %f\n", vec1.x);
   vec1.y /= length; LOG("vec1.y = %f\n", vec1.y);
   vec1.z /= length; LOG("vec1.z = %f\n", vec1.z);
}; 
replace LOG with the debug print function and cross the fingers to see where and why there is an exception. You should work this way if you cannot debug it.
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

Post by Ghoti »

i have a lot to learn still :s

what include file do i need for the fsqrt ? can't find it and also through google not.
Will that fix the crash also ?
crazyc
Posts: 408
Joined: Fri Jun 17, 2005 10:13 am

Post by crazyc »

Ghoti wrote: what include file do i need for the fsqrt ?
Try sqrtf.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

math.h ?

well the float version of math functions must be preceded with f

so sqrt(double) -> fsqrt(float)

http://nixdoc.net/man-pages/IRIX/man3/sqrt.3.html

if not defined :

Code: Select all

inline float fsqrt(float v) {
float r; asm volatile ("sqrt.s %0, %1" : "=f"(r) : "f"(v));
return r;
}
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

Post by Ghoti »

k it crashes at the first calculation:
float x2 = vec1.x * vec1.x;
doesn't make sense :s

and it does that with those values, because the first time i use it it works without a crash
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

C99 says it's a suffix, not a prefix.

Code: Select all

#include <math.h>
double sqrt&#40;double x&#41;;
float sqrtf&#40;float x&#41;;
long double sqrtl&#40;long double x&#41;;
I can only think the exception is an underflow, ie. vec.x is a very tiny number and when squared it underflows to 0. Perhaps the exception mask needs changing?

Jim
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

Jim wrote:C99 says it's a suffix, not a prefix.

Code: Select all

#include <math.h>
double sqrt&#40;double x&#41;;
float sqrtf&#40;float x&#41;;
long double sqrtl&#40;long double x&#41;;
I can only think the exception is an underflow, ie. vec.x is a very tiny number and when squared it underflows to 0. Perhaps the exception mask needs changing?

Jim
ok.

just a thought : if 0.0 x -0.0 = -0.0 (X x -Y = -XY), what 0.0 + -0.0 gives us ? 0.0, -0.0 , NaN ? and sqrtf(-0.0) ?

for some reason, I suspect LOG (whatever you put in) has no time to display a message, so you should have a "pause" between each LOG (that is, press a key to continue) so you can have time to see a message before the next instruction crashes
Ghoti
Posts: 288
Joined: Sat Dec 31, 2005 11:06 pm

Post by Ghoti »

Hi well, I have a toolclass for this with a lot of functions, writing to file, displaying debug info etc. but one function is to loop the debug info, so when you reach that function it goes into a loop, or well it should go into a loop. I have create the loop in front of thevariables and after the variables and before it does its work perfectly fine but right after the first line of code it crashes :(

EDIT:
if I do this:
sprintf(s, "x= %f y= %f z= %f", vec1.x, vec1.y, vec1.z);
it shows that but as soon as I change it into vec1.x*vec1.x in stead of just vec1.x then it crashes :s
vec1.x = 0.00000f , so since when can't i multiply somthing by zero, i though that you cannot divide by zero but multiply also ?
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Of course you can multiply by zero, but is it really 0, or just 0 to 5 decimal places? Can you try using %g instead of %f?

If this "Status - 0x20008613" is your FPSCR, then that is showing a divide by zero exception.
<edit>I'm pretty sure it is, can you post the code with the "don't divide by zero" check in it that you are using?

Jim
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Status is actually the MIPS SR reg, you should be able to dump the actual FPU status reg with the 'exprfpu' command. Of course the character codes after the FPU exception actually indicate what has happend. In this case they are I which is inexact operation, U which is underflow and V which is invalid operation. Basically you have a normalisation issue with one of your floats being too small and the fpu blows up :) Best way around this is normally to just disable fpu exceptions.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Aha! Thanks, I should have spotted that :)

Jim
Post Reply