forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Inline VFPU help

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Sun Apr 23, 2006 3:50 pm    Post subject: Inline VFPU help Reply with quote

I am trying to replace the sqrt() function using the codegen.h approach and have written the following but it has a bug. I am a new at inline assembler and can't get the following to work (it just returns the value I pass it)
Code:
float mysqrt(float val)
{
   register float a=val;
   register float b;

   __asm__ volatile (
      cgen_asm(vsqrt_s(R_a0, R_a1))
      :"=r"(b)
      :"r"(a), "r"(b)
   );
   return (b);
}

Can anyone lead me out of the dark on how to do this correctly?
Back to top
View user's profile Send private message
popcornx



Joined: 14 Mar 2006
Posts: 6

PostPosted: Mon Apr 24, 2006 4:58 pm    Post subject: Reply with quote

hmm I'm a MIPS n00b too but I'll still try to help

Code:

float mysqrt(float val)
{
   int b=0;

   register float par1 asm($16)=val; //parameter 1
   register float par2 asm($17)=2; //parameter 2

   asm (
      :
      :"r"(par1),"r"(par2) // insert val into reg $16 & 2 into $17
   );

  asm("move $a0,$16");//move the first paratermeter
 asm("move $a1,$17");//move the first paratermeter
  asm("jal vsqrt");
  asm("sw $ra,($18");

  register float retv asm($18); //return value
     asm (
      :"=r"(retv)
      :
   );
   return (retv);
}


I'm a n00b so I dunno if this works or not...I hope it does!!!
if not you can ask skylark or fanjita for help. I think they will respond.
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Mon Apr 24, 2006 6:05 pm    Post subject: Reply with quote

Actually, since you're trying to use the VFPU, I wonder if you can even use the general registers for this... Something like this should work: (note that VFPU is supported in the current binutils, so no need for codegen)

Code:
float mysqrt(float val)
{
        float ret;

        __asm__ volatile (
                "mtv %1, S000\n"
                "vsqrt.s S001, S000\n"
                "mfv %0, S001\n"
        : "=r"(ret) : "r"(val) );

        return ret;
}


This should work (I looked at the output and it looked ok), but I don't have access to hardware to test it with right now.
_________________
GE Dominator
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu Apr 27, 2006 8:22 am    Post subject: Reply with quote

Can't get anywhere with this. I'm on september '05 toolchain and sdk so the VFPU stuff is not builtin so I had to stick with codegen.h approach. Unfortunatly there is no mtv/mvf and I spent some time trying to add those opcodes to little avail.

Then I decided to update my toolchain and grabbed the latest "famous" version from oopo.net haggled through that for a bit to find that it looks like the VFPU stuff is only in the version in SVN as of yet.

I've never been able to checkout stuff from svn.ps2dev.net - it keeps saying that the hostname is invalid. I tried punching TCP/3690 open on my router but can't get to it.

I tried the beta toolchain from oopo.net, but it failed in the install so I went back to the latest "famous" version.

Is there a userid/pw that is needed for svn.pspdev.org?
Back to top
View user's profile Send private message
Oobles
Site Admin


Joined: 17 Jan 2004
Posts: 362
Location: Melbourne, Australia

PostPosted: Thu Apr 27, 2006 9:13 am    Post subject: Reply with quote

No userid or password is required for svn.ps2dev.org. Please make sure you have the correct URL. In your last message you refer to it as svn.ps2ev.net and svn.pspdev.org which are both wrong.

If you have a restrictive firewall you might not be able to access the server. Let me know if you have any more problems. I believe someone did create a mirror of subversion that can be accessed through HTTP. You should be able to find it on forums via search.

David. aka Oobles.
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger
dot_blank



Joined: 28 Sep 2005
Posts: 498
Location: Brasil

PostPosted: Thu Apr 27, 2006 11:34 am    Post subject: Reply with quote

tried and below works:

user@host$ svn co svn://ps2dev.org/psp/trunk/pspsdk

then future updating is:

user@host$ cd pspsdk
user@host$ svn up
_________________
10011011 00101010 11010111 10001001 10111010
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu Apr 27, 2006 7:12 pm    Post subject: Reply with quote

Well I still can't get into svn, but I was able to get my sqrt(), sin(), cos(), etc over to VFPU and got a very nice speed-up so thank you to everyone who helped with this!!
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Fri Apr 28, 2006 11:58 am    Post subject: Reply with quote

These are probably done in newlib or elsewhere already, but if you have the latest toolchain you should be able to implement your own math functions that are MUCH faster. Note you have to add "|" PSP_THREAD_ATTR_VFPU into your PSP_MAIN_THREAD_ATTR() def in main.c.
Code:
float mysqrtf(float val)
{
   float ret;

   __asm__ volatile (
      "mtv %1, S000\n"
      "vsqrt.s S001, S000\n"
      "mfv %0, S001\n"
      : "=r"(ret) : "r"(val));

   return ret;
}

Code:
float mysinf(float val)
   {
   float ret;

   val *= 0.6366197f; // convert to deg/90

   __asm__ volatile (
      "mtv %1, S000\n"
      "vsin.s S001, S000\n"
      "mfv %0, S001\n"
      : "=r"(ret) : "r"(val));

   return ret;
   }

Code:
float mycosf(float val)
   {
   float ret;

   val *= 0.6366197f; // convert to deg/90

   __asm__ volatile (
      "mtv %1, S000\n"
      "vcos.s S001, S000\n"
      "mfv %0, S001\n"
      : "=r"(ret) : "r"(val));

   return ret;
   }
Back to top
View user's profile Send private message
dot_blank



Joined: 28 Sep 2005
Posts: 498
Location: Brasil

PostPosted: Fri Apr 28, 2006 3:02 pm    Post subject: Reply with quote

well these seem to work quiet well :)
i think the toolchain will do good with maybe a
vfpu math library ....something in the sense of
Code:
#include <vmath.h>

and then one would simply use them as such
Code:
vcos(2*c_wave);
vinf(value);
//etc...

what do the mods think?
_________________
10011011 00101010 11010111 10001001 10111010
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Fri Apr 28, 2006 7:21 pm    Post subject: Reply with quote

Just as a little sidenote, the sin/cos can be rewritten to
Code:

float mysinf(float val)
   {
   float ret;

   __asm__ volatile (
      "mtv %1, S000\n"
      "vcst.s S002, VFPU_2_PI\n"
      "vmul.s S001, S000, S002\n"
      "vsin.s S000, S001\n" // or vcos.s
      "mfv %0, S000\n"
      : "=r"(ret) : "r"(val));

   return ret;
   }

and if you use something like vrot.q instead of vsin, you can get sinus and cosinus computed at the same time. Something like this should do it:
Code:

void vsincosf(float angle, ScePspFVector4* result)
{
 __asm__ volatile (
    "mtv %1, S000\n"
    "vcst.s S001, VFPU_2_PI\n"
    "vmul.s S002, S000, S001\n"
    "vrot.q C010, S002, [s, c, 0, 0]\n"
    "usv.q C010, 0 + %0\n"
    : "+m"(*result) : "r"(angle));
}

_________________
GE Dominator
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Sat Apr 29, 2006 3:29 am    Post subject: Reply with quote

Code:
float myacosf(float val)
   {
   float ret;

   __asm__ volatile (
      "mtv %1, S000\n"
      "vasin.s S001, S000\n"
      "vone.s S002\n"
      "vsub.s S000, S002, S001\n"
      "vcst.s S002, VFPU_PI_2\n"
      "vmul.s S001, S000, S002\n"
      "mfv %0, S001\n"
      : "=r"(ret) : "r"(val));

   return ret;
   }

float myasinf(float val)
   {
   float ret;

   __asm__ volatile (
      "mtv %1, S000\n"
      "vasin.s S001, S000\n"
      "vcst.s S002, VFPU_PI_2\n"
      "vmul.s S000, S001, S002\n"
      "mfv %0, S000\n"
      : "=r"(ret) : "r"(val));

   return ret;
   }

Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu May 04, 2006 9:03 am    Post subject: Reply with quote

Here is an applyMatrix routine. This is about 4 times faster than in software.
Code:
// NOTE: v0, m0, v1 must be 16 byte aligned!!
// NOTE: this is row-major matrix format
void myApplyMatrix(FVECTOR v0, FMATRIX m0, FVECTOR v1)
   {
   __asm__ volatile (
   "lv.q   R000, 0x0(%1)\n"
   "lv.q   R001, 0x10(%1)\n"
   "lv.q   R002, 0x20(%1)\n"
   "lv.q   R003, 0x30(%1)\n"

   "lv.q   R100, 0x0(%2)\n"

   "vdot.q   S200, R000, R100\n"
   "vdot.q   S210, R001, R100\n"
   "vdot.q   S220, R002, R100\n"
   "vdot.q   S230, R003, R100\n"
   "sv.q   R200, 0x0(%0)\n"
   : : "r" (v0) , "r" (m0) ,"r" (v1) );
   }
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu May 04, 2006 9:44 am    Post subject: Reply with quote

Here is a Matrix Multiply routine. This is about 10 times faster than in software:
Code:
// NOTE: m0, m1, m2 must be 16 byte aligned!!
// NOTE: this is row-major matrix format
void myMulMatrix(FMATRIX m2, FMATRIX m0, FMATRIX m1)
   {
   __asm__ volatile (
   "lv.q   R000, 0x0(%1)\n"
   "lv.q   R001, 0x10(%1)\n"
   "lv.q   R002, 0x20(%1)\n"
   "lv.q   R003, 0x30(%1)\n"

   "lv.q   R100, 0x0(%2)\n"
   "lv.q   R101, 0x10(%2)\n"
   "lv.q   R102, 0x20(%2)\n"
   "lv.q   R103, 0x30(%2)\n"

   "vmmul.q   M200, M000, M100\n"

   "sv.q   R200, 0x0(%0)\n"
   "sv.q   R201, 0x10(%0)\n"
   "sv.q   R202, 0x20(%0)\n"
   "sv.q   R203, 0x30(%0)\n"
   : : "r" (m2) , "r" (m0) ,"r" (m1) );
   }
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu May 04, 2006 10:39 am    Post subject: Reply with quote

Here is a matrix copy routine. This is about 6 times faster than in software:
Code:
// NOTE: m0, m1 must be 16 byte aligned!!
// NOTE: this is row-major matrix format
void myCopyMatrix(FMATRIX m1, FMATRIX m0)
   {
   __asm__ volatile (
   "lv.q   R000, 0x0(%1)\n"
   "lv.q   R001, 0x10(%1)\n"
   "lv.q   R002, 0x20(%1)\n"
   "lv.q   R003, 0x30(%1)\n"

   "sv.q   R000, 0x0(%0)\n"
   "sv.q   R001, 0x10(%0)\n"
   "sv.q   R002, 0x20(%0)\n"
   "sv.q   R003, 0x30(%0)\n"
   : : "r" (m1) , "r" (m0) );
   }
Back to top
View user's profile Send private message
Psilocybeing



Joined: 04 May 2006
Posts: 3

PostPosted: Thu May 04, 2006 11:27 am    Post subject: Reply with quote

Very nice, sin/cosine functions are used heavily in one of my projects, these will come in very handy. Thanks :)
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Thu May 04, 2006 9:47 pm    Post subject: Reply with quote

starman2049 wrote:
Here is an applyMatrix routine. This is about 4 times faster than in software.
<snip>


You should take a look at vtfm3/4 instead of using vdot, it should execute even faster. Example:
Code:
void myApplyMatrix(FVECTOR v0, FMATRIX m0, FVECTOR v1)
   {
   __asm__ volatile (
   "lv.q   R000, 0x0(%1)\n"
   "lv.q   R001, 0x10(%1)\n"
   "lv.q   R002, 0x20(%1)\n"
   "lv.q   R003, 0x30(%1)\n"

   "lv.q   R100, 0x0(%2)\n"

   "vtfm4.q R200, E000, R100\n"
   "sv.q   R200, 0x0(%0)\n"
   : : "r" (v0) , "r" (m0) ,"r" (v1) );
   }


I do however think most of the time is spent loading the matrix, so you should perhaps change your code to multiply more than one vertex per call (like using it for an array of vertices). The overhead you then would get when you need to multiply just one is minimal compared to the opposite situation. And don't forget that you can let the GE do all this job if you just intend to render it. :)
_________________
GE Dominator
Back to top
View user's profile Send private message
starman2049



Joined: 19 Sep 2005
Posts: 75

PostPosted: Thu May 18, 2006 2:05 pm    Post subject: Reply with quote

Here's a much faster atan2 routine. This isn't in VFPU format (yet), but I thought I would post for now and update later. This is about 10 times faster than the default atan2 routine. PLEAE NOTE: this is a low order approximation and should only be used when you need precision to a few digits. I use this 50 to 100 times per frame in some levels so it was a big boost for me (8 fps!)

Since the VFPU has an asin() in silicon and there is a known identity between atan and asin this could be done other ways, and could be done to higher order.

I'm personally hoping chp has a fancy matrix approach for this one :)

Code:
float myatan2f(float y, float x)
   {
   float angle;
   float coeff_1 = 3.141592654f/4.0f;
   float coeff_2 = 3.0f*coeff_1;
   float abs_y = fabs(y) + 0.00000001f;      // kludge to prevent 0/0 condition
   float r;

   if (x >= 0.0f)
      {
      r = (x - abs_y) / (x + abs_y);
      angle = coeff_1 - coeff_1 * r;
      }
   else
      {
      r = (x + abs_y) / (abs_y - x);
      angle = coeff_2 - coeff_1 * r;
      }

   if (y < 0.0f)
      return(-angle);     // negate if in quad III or IV
   else
      return(angle);
   }

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group