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 

Error using VFPU matrix 3?

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



Joined: 12 Sep 2009
Posts: 79

PostPosted: Tue Oct 20, 2009 6:13 am    Post subject: Error using VFPU matrix 3? Reply with quote

I have the following code - which works, that's not the problem. The problem is, it didn't work when I used VFPU matrix 3 instead of matrix 2. Is there any known problem with it?

Code:

   for (i = 0; i < mdl->numObjects; ++i)
   {
      pl2Object *obj = mdl->objects[i];

      pl2Vertex *vert = &(obj->verts[0]);
      pgeVertTNV *tvert = &(obj->tverts[0]);

      for (j = 0; j < obj->numVerts; ++j)
      {
         ScePspFVector4 v = { vert->x,  vert->y,  vert->z,  1 };
         ScePspFVector4 n = { vert->nx, vert->ny, vert->nz, 0 };

         __asm__ volatile(
            "vzero.t C200\n"           // C300 = new vertex
            "vzero.t C210\n"           // C310 = new normal
            "ulv.q   C220, 0 + %0\n"   // C320 = original vertex
            "ulv.q   C230, 0 + %1\n"   // C330 = original normal
            :: "m"(v), "m"(n));

         for (k = 0; k < 3; ++k)
         {
            if (vert->bones[k] == 0xff) break;

            __asm__ volatile(
               "ulv.q   C000,  0 + %0\n"     // M000 = transform matrix
               "ulv.q   C010, 16 + %0\n"
               "ulv.q   C020, 32 + %0\n"
               "ulv.q   C030, 48 + %0\n"
               "lv.s    S110,  0 + %1\n"     // S110 = weight
               "vtfm4.q C100, M000, C220\n"  // C100 = [ transform matrix ] [ original vertex ]
               "vscl.t  C100, C100, S110\n"  // add weighted value to new vertex
               "vadd.t  C200, C200, C100\n"
               "vtfm4.q C100, M000, C230\n"  // C100 = [ transform matrix ] [ original normal ]
               "vscl.t  C100, C100, S110\n"  // add weighted value to new normal
               "vadd.t  C210, C210, C100\n"
               : : "m"(tfm[vert->bones[k]]), "m"(vert->weight[k]));
         }

         __asm__ volatile(
            "vdot.t     S000, C210, C210\n"  // normalize new normal
            "vrsq.s     S000, S000\n"
            "vscl.t     C210[-1:1,-1:1,-1:1], C210, S000\n"
            "sv.s       S200, 0 + %0\n"      // store new vertex
            "sv.s       S201, 0 + %1\n"
            "sv.s       S202, 0 + %2\n"
            "sv.s       S210, 0 + %3\n"      // store new normal
            "sv.s       S211, 0 + %4\n"
            "sv.s       S212, 0 + %5\n"
            : "=m" (tvert->x),  "=m" (tvert->y),  "=m" (tvert->z),
              "=m" (tvert->nx), "=m" (tvert->ny), "=m" (tvert->nz));

         tvert->u  = vert->u;
         tvert->v  = vert->v;

         ++vert; ++tvert;
      }
   }


Last edited by Criptych on Tue Oct 20, 2009 7:34 am; edited 1 time in total
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Tue Oct 20, 2009 6:38 am    Post subject: Reply with quote

Did you test this on a psp-1000 by chance?
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Tue Oct 20, 2009 7:34 am    Post subject: Reply with quote

crazyc wrote:
Did you test this on a psp-1000 by chance?

No, only a 2000. I don't have a 1000. (Might be a good idea to get one for testing, though.)
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Tue Oct 20, 2009 9:38 am    Post subject: Reply with quote

There was an issue with ulv.q corrupting an FPU register, but I think it was fixed after the 1000. You could probably account for it by adding a clobber constraint. (something like $fp0 with C000, $fp1 with C100 I think)
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Tue Oct 20, 2009 11:20 am    Post subject: Reply with quote

crazyc wrote:
There was an issue with ulv.q corrupting an FPU register, but I think it was fixed after the 1000.

I'd heard about that, and I'll try to remove them before releasing for compatibility. But yes, my first thought was some other function had corrupted the values - then I remembered that it doesn't call any other functions, especially not within the critical loop (numVerts) where the values are needed. It's just really weird that by changing only the matrix number it went from "not working" to "no problem." :-\
crazyc wrote:
You could probably account for it by adding a clobber constraint. (something like $fp0 with C000, $fp1 with C100 I think)

Way over my head, I've only ever used assembly for minimal VFPU access, and I'm still learning most of the opcodes. :P How do I add a "clobber constraint"? Is it an extra argument/modifier to the instruction?

Bugger. I tried changing the 2s back to 3s and it still works... maybe it was only a typo that got worked out when I rewrote my function to use matrix 2. Sorry for wasting your time, crazyc. orz

At least now I know it can be done with 3 matrices instead of 4.


Last edited by Criptych on Tue Oct 20, 2009 11:26 am; edited 1 time in total
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Tue Oct 20, 2009 11:24 am    Post subject: Reply with quote

yeah, ulvq is corrupting fpu registers, i tested it on my old psp1k. As long as you need to be compatible, you have no choice but no using ulvq.

can you be more precise about which instructions are giving bad results ?
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Tue Oct 20, 2009 1:15 pm    Post subject: Reply with quote

Criptych wrote:

Way over my head, I've only ever used assembly for minimal VFPU access, and I'm still learning most of the opcodes. :P How do I add a "clobber constraint"? Is it an extra argument/modifier to the instruction?
A clobber constraint is an extra parameter added to the inline asm block that tells gcc that a register contents will be destroyed, Something like in your first block
Code:
         __asm__ volatile(
            "vzero.t C200\n"           // C300 = new vertex
            "vzero.t C210\n"           // C310 = new normal
            "ulv.q   C220, 0 + %0\n"   // C320 = original vertex
            "ulv.q   C230, 0 + %1\n"   // C330 = original normal
            :: "m"(v), "m"(n):"$fp2");
to indicate $fp2 contents should not be assumed to be preserved. I don't know if this will work as I've never tried it.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Tue Oct 20, 2009 4:10 pm    Post subject: Reply with quote

I'll give it a shot. Is this register corruption the only reason not to use ulv.q/usv.q? From what I read in the diggins they aren't significantly slower than the aligned version; how do they compare to lv.s/sv.s * 4?
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Wed Oct 21, 2009 1:17 am    Post subject: Reply with quote

Criptych wrote:
I'll give it a shot. Is this register corruption the only reason not to use ulv.q/usv.q?
I believe so.
Criptych wrote:
From what I read in the diggins they aren't significantly slower than the aligned version; how do they compare to lv.s/sv.s * 4?
I don't know. I haven't done much with the VFPU.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Wed Oct 21, 2009 3:57 am    Post subject: Reply with quote

Criptych wrote:
I'll give it a shot. Is this register corruption the only reason not to use ulv.q/usv.q? From what I read in the diggins they aren't significantly slower than the aligned version; how do they compare to lv.s/sv.s * 4?


the issue is only with ulv.q, not with usv.q. You have choice between lv.q (16-byte alignment) or lv.s (if you use 2D for instance). Normaly I added an option to psp-gcc to make stack alignment to what you want. It is the same option you'll find for x86. I don't remember the name :/ as it was a long time ago i did it.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Wed Oct 21, 2009 5:33 am    Post subject: Reply with quote

hlide wrote:
the issue is only with ulv.q, not with usv.q. You have choice between lv.q (16-byte alignment) or lv.s (if you use 2D for instance).

Okay, I've changed my code to use only lv.q, and seems to be working.

hlide wrote:
Normaly I added an option to psp-gcc to make stack alignment to what you want. It is the same option you'll find for x86. I don't remember the name :/ as it was a long time ago i did it.

Could it be "-mpreferred-stack-boundary"?

@crazyc: Adding clobber constraints gave me several errors like "error: unknown register name '$fp2' in 'asm.'" But since I'm not using ulv.q anymore, I wouldn't worry about it.


Last edited by Criptych on Sun Nov 01, 2009 6:04 pm; edited 1 time in total
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Wed Oct 21, 2009 6:56 am    Post subject: Reply with quote

Criptych wrote:
hlide wrote:
the issue is only with ulv.q, not with usv.q. You have choice between lv.q (16-byte alignment) or lv.s (if you use 2D for instance).

Okay, I've changed my code to use only lv.q, and seems to be working.

hlide wrote:
Normaly I added an option to psp-gcc to make stack alignment to what you want. It is the same option you'll find for x86. I don't remember the name :/ as it was a long time ago i did it.

Could it be "-mpreferred-stack-boundary"?


exactly, normally i made a patch to add it for mips/allegrex as it was specific to x86. I think Heimdall uses it for his mingw version of psp-gcc. Not sure for the pspdev.org SVN version.


Last edited by hlide on Wed Oct 21, 2009 7:10 am; edited 1 time in total
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Wed Oct 21, 2009 7:09 am    Post subject: Reply with quote

Criptych wrote:
@crazyc: Adding clobber constraints gave me several errors like "error: unknown register name '$fp2' in 'asm.'" But since I'm not using ulv.q anymore, I wouldn't worry about it.

if I'm not wrong, it should be '$fpr2' or '$f2'. And it only works for save-callee registers, which are $f20-$f31. So registers $f0-$f19 cannot be clobberred this way.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Sun Nov 01, 2009 6:08 pm    Post subject: Reply with quote

hlide wrote:
if I'm not wrong, it should be '$fpr2' or '$f2'. And it only works for save-callee registers, which are $f20-$f31. So registers $f0-$f19 cannot be clobberred this way.

Okay, it accepts "$f2." But does that last part mean you can't use clobber constraints or that their values won't get clobbered? If the former, it sounds like crazyc's idea won't work. :(
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun Nov 01, 2009 8:24 pm    Post subject: Reply with quote

Criptych wrote:
Okay, it accepts "$f2." But does that last part mean you can't use clobber constraints or that their values won't get clobbered? If the former, it sounds like crazyc's idea won't work. :(

I tried to use this feature in my old yapse4psp (psx emulator) and found out it only works on save-callee registers. The purpose was to prevent from some C functions called by dynarec code to use $t0-$t9 registers as I wanted them for virtual registers mapped to psx registers.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Sun Nov 01, 2009 11:27 pm    Post subject: Reply with quote

hlide wrote:
I tried to use this feature in my old yapse4psp (psx emulator) and found out it only works on save-callee registers. The purpose was to prevent from some C functions called by dynarec code to use $t0-$t9 registers as I wanted them for virtual registers mapped to psx registers.

I'm not sure I understand what you mean by a "save-callee" register. Are you saying the values in other registers get clobbered anyway?
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Mon Nov 02, 2009 7:33 am    Post subject: Reply with quote

Criptych wrote:
I'm not sure I understand what you mean by a "save-callee" register. Are you saying the values in other registers get clobbered anyway?


Ok, a caller is the code which calls a function. Callee is the code of the called function. Locals in a function are allocated through save-callee registers if possible else in stack. So it means your functions will have a prologue to save those registers and an epilogue to restore those registers. In the body you can change the values of this registers because they are LOCAL.

for MIPS, the save-callee registers are $s0-$s8 (there are some special registers too but let us keep it simple). The other registers - if they are not simply fix registers, that is, not used by gcc - are considered as save-caller registers (that means you NEED to save them BEFORE any call to a function if you want to restore them AFTER any call. The fact is I never see gcc does it automatically, that is, clobbering them doesn't enforce a save/restore of those registers BEFORE/AFTER any call. We could at least expect for gcc not to use those clobbered registers but in practice it does use them even after clobbering them. Well my function was calling some inline functions so maybe those inline functions defected the clobbering purpose.

The same thing goes with FPR, some are save-callee registers, others are save-caller registers.

So, since clobbering constraints seem to be effective only for save-callee registers, i cannot use it
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Tue Nov 03, 2009 4:19 am    Post subject: Reply with quote

Okay, I understand the concept but I'd never heard that term used before. Thanks. :)
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Tue Nov 03, 2009 5:36 am    Post subject: Reply with quote

Criptych wrote:
Okay, I understand the concept but I'd never heard that term used before. Thanks. :)

This is a technical term. Just google it and you'll find a ton.
Back to top
View user's profile Send private message
davidgf



Joined: 31 Aug 2009
Posts: 22

PostPosted: Fri Feb 12, 2010 3:29 am    Post subject: Reply with quote

Sorry for reopening this post, but I can't find anything in google about this.
Where did you exactly find out the register corruption? I'm interested in this.
But if I don't use Matrix 0 shoul'd be any problem, isn't it?

After some tests on a FAT PSP I notices some bugs related to some register corruption and I use ulv a lot.

Thanks!
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