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 

VFPU playground, code generation for gas-unsupported opcodes
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Wed Oct 05, 2005 6:19 pm    Post subject: Reply with quote

MrMr[iCE] wrote:

holger: more opcodes for ya



cool, added, except vidt:

Code:

/*
+-------------------------------------------------------------+--------------+
|31                                   16 | 15 | 14     8  | 7 | 6         0  |
+-------------------------------------------------------------+--------------+
| opcode 0xd003 (p)                      |  0 |      0    | 1 | vfpu_rd[6-0] |
| opcode 0xd003 (t)                      |  1 |      0    | 0 | vfpu_rd[6-0] |
| opcode 0xd003 (q)                      |  1 |      0    | 1 | vfpu_rd[6-0] |
+-------------------------------------------------------------+--------------+
   
   VectorLoadIdentity.Pair/Triple/Quad

    vidt.p %vfpu_rd   ; Set 2x1 Vector to Identity
    vidt.t %vfpu_rd   ; Set 3x1 Vector to Identity
    vidt.q %vfpu_rd   ; Set 4x1 Vector to Identity

        %vfpu_rd:   VFPU Vector Destination Register ([s|p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- identity vector
*/
#define vidt_p(vfpu_rd)  (0xd0030080 | (vfpu_rd))
#define vidt_t(vfpu_rd)  (0xd0038000 | (vfpu_rd))
#define vidt_q(vfpu_rd)  (0xd0038080 | (vfpu_rd))



what is an identity vector? Is this (0, 0, 0, 1) or (1, 1, 1, 1)/vone?
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Thu Oct 06, 2005 1:52 am    Post subject: Reply with quote

Quote:

what is an identity vector? Is this (0, 0, 0, 1) or (1, 1, 1, 1)/vone?


My bad I didnt test this function well enough to notice what it really does, but I did a few more tests and here's what I found:

This function initializes a vector to identity, but it does so according to the layout of the appropriate matrix. In the register display, I see this:

vidt_q Q_C000
vidt_q Q_C010

1 0 0 0
0 1 0 0
x x x x
x x x x


Now with Q_R000 and Q_R0001, i get:

1 0 x x
0 1 x x
0 0 x x
0 0 x x

Think of this as setting a row or column of a matrix to identity. The same behavior applies to triple and pair as well.

and heres another batch of ops:
Code:

/*
+-------------------------------------+----+--------------+---+--------------+
|31                                16 | 15 | 14         8 | 7 | 6          0 |
+-------------------------------------+----+--------------+---+--------------+
| opcode 0xd0010000 (s)               |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd0010080 (p)               |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xd0018000 (t)               |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd0018080 (q)               |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+-------------------------------------+----+--------------+---+--------------+

  AbsoluteValue.Single/Pair/Triple/Quad

   vabs.s %vfpu_rd, %vfpu_rs    ; Absolute Value Single
    vabs.p %vfpu_rd, %vfpu_rs    ; Absolute Value Pair
    vabs.t %vfpu_rd, %vfpu_rs    ; Absolute Value Triple
    vabs.q %vfpu_rd, %vfpu_rs    ; Absolute Value Quad

        %vfpu_rd:   VFPU Vector Destination Register (m[p|t|q]reg 0..127)
        %vfpu_rs:   VFPU Vector Source Register (m[p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- abs(vfpu_regs[%vfpu_rs])
*/

#define vabs_s(vfpu_rd,vfpu_rs)  (0xd0010000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vabs_p(vfpu_rd,vfpu_rs)  (0xd0010080 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vabs_t(vfpu_rd,vfpu_rs)  (0xd0018000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vabs_q(vfpu_rd,vfpu_rs)  (0xd0018080 | ((vfpu_rs) << 8) | (vfpu_rd))

/*
+-------------------------------------+----+--------------+---+--------------+
|31                                16 | 15 | 14         8 | 7 | 6          0 |
+-------------------------------------+----+--------------+---+--------------+
| opcode 0xd002 (s)                   |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd002 (p)                   |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xd002 (t)                   |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd002 (q)                   |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+-------------------------------------+----+--------------+---+--------------+

  Negate.Single/Pair/Triple/Quad

   vneg.s %vfpu_rd, %vfpu_rs    ; Negate Single
    vneg.p %vfpu_rd, %vfpu_rs    ; Negate Pair
    vneg.t %vfpu_rd, %vfpu_rs    ; Negate Triple
    vneg.q %vfpu_rd, %vfpu_rs    ; Negate Quad

        %vfpu_rd:   VFPU Vector Destination Register (m[p|t|q]reg 0..127)
        %vfpu_rs:   VFPU Vector Source Register (m[p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- -vfpu_regs[%vfpu_rs]
*/

#define vneg_s(vfpu_rd,vfpu_rs)  (0xd0020000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vneg_p(vfpu_rd,vfpu_rs)  (0xd0020080 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vneg_t(vfpu_rd,vfpu_rs)  (0xd0028000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vneg_q(vfpu_rd,vfpu_rs)  (0xd0028080 | ((vfpu_rs) << 8) | (vfpu_rd))


/*
+-------------------------------------+----+--------------+---+--------------+
|31                                16 | 15 | 14         8 | 7 | 6          0 |
+-------------------------------------+----+--------------+---+--------------+
| opcode 0xd04a (s)                   |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd04a (p)                   |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xd04a (t)                   |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xd04a (q)                   |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+-------------------------------------+----+--------------+---+--------------+

  Sign.Single/Pair/Triple/Quad

   vsgn.s %vfpu_rd, %vfpu_rs    ; Get Sign Single
    vsgn.p %vfpu_rd, %vfpu_rs    ; Get Sign Pair
    vsgn.t %vfpu_rd, %vfpu_rs    ; Get Sign Triple
    vsgn.q %vfpu_rd, %vfpu_rs    ; Get Sign Quad

        %vfpu_rd:   VFPU Vector Destination Register (m[p|t|q]reg 0..127)
        %vfpu_rs:   VFPU Vector Source Register (m[p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- sign(vfpu_regs[%vfpu_rs])

    this will set rd values to 1 or -1, depending on sign of input values
*/

#define vsgn_s(vfpu_rd,vfpu_rs)  (0xd04a0000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vsgn_p(vfpu_rd,vfpu_rs)  (0xd04a0080 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vsgn_t(vfpu_rd,vfpu_rs)  (0xd04a8000 | ((vfpu_rs) << 8) | (vfpu_rd))
#define vsgn_q(vfpu_rd,vfpu_rs)  (0xd04a8080 | ((vfpu_rs) << 8) | (vfpu_rd))

/*
+----------------------+--------------+----+--------------+---+--------------+
|31                 23 | 22        16 | 15 | 14         8 | 7 | 6         0  |
+----------------------+--------------+----+--------------+---+--------------+
| opcode 0x6d0 (s)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0x6d0 (p)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0x6d0 (t)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0x6d0 (q)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+----------------------+--------------+----+--------------+---+--------------+

  VectorMin.Single/Pair/Triple/Quad

   vmin.s %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Minimum Value Single
    vmin.p %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Minimum Value Pair
    vmin.t %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Minimum Value Triple
    vmin.q %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Minimum Value Quad

        %vfpu_rt:   VFPU Vector Source Register (sreg 0..127)
        %vfpu_rs:   VFPU Vector Source Register ([p|t|q]reg 0..127)
        %vfpu_rd:   VFPU Vector Destination Register ([s|p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- min(vfpu_regs[%vfpu_rs], vfpu_reg[%vfpu_rt])
*/

#define vmin_s(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D000000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmin_p(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D000080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmin_t(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D008000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmin_q(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D008080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))


/*
+----------------------+--------------+----+--------------+---+--------------+
|31                 23 | 22        16 | 15 | 14         8 | 7 | 6         0  |
+----------------------+--------------+----+--------------+---+--------------+
| opcode 0x6d8 (s)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0x6d8 (p)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0x6d8 (t)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0x6d8 (q)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+----------------------+--------------+----+--------------+---+--------------+

  VectorMax.Single/Pair/Triple/Quad

   vmax.s %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Maximum Value Single
    vmax.p %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Maximum Value Pair
    vmax.t %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Maximum Value Triple
    vmax.q %vfpu_rd, %vfpu_rs, %vfpu_rt ; Get Maximum Value Quad

        %vfpu_rt:   VFPU Vector Source Register (sreg 0..127)
        %vfpu_rs:   VFPU Vector Source Register ([p|t|q]reg 0..127)
        %vfpu_rd:   VFPU Vector Destination Register ([s|p|t|q]reg 0..127)

    vfpu_regs[%vfpu_rd] <- max(vfpu_regs[%vfpu_rs], vfpu_reg[%vfpu_rt])
*/

#define vmax_s(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D800000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmax_p(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D800080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmax_t(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D808000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vmax_q(vfpu_rd,vfpu_rs,vfpu_rt)  (0x6D808080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))


I'm working on v(h)tfm4/3/2, these are the vector*matrix ops, almost have a working set of functions to setup x/y/z rotation, projection matrix and concat matrix functions.

I need very specific info on vmmul. According to mips_dis.c, the vmmul instruction recieves special treatment and requires bit 13 (RXC bit) to be inverted...Im not sure how to do that, or what purpose that serves..can someone enlighten us on this?
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Thu Oct 06, 2005 2:27 am    Post subject: Reply with quote

MrMr[iCE] wrote:
Quote:

what is an identity vector? Is this (0, 0, 0, 1) or (1, 1, 1, 1)/vone?


My bad I didnt test this function well enough to notice what it really does, but I did a few more tests and here's what I found:

This function initializes a vector to identity, but it does so according to the layout of the appropriate matrix. In the register display, I see this:

vidt_q Q_C000
vidt_q Q_C010

1 0 0 0
0 1 0 0
x x x x
x x x x


Now with Q_R000 and Q_R0001, i get:

1 0 x x
0 1 x x
0 0 x x
0 0 x x

Think of this as setting a row or column of a matrix to identity. The same behavior applies to triple and pair as well.



mmmh... sounds logical, but seems a little hard to explain in the documentation... how could we elaborate this in a few short sentences?

MrMr[iCE] wrote:

and heres another batch of ops:



I'll add these ones right now...
Seems as if we have now almost everything together to implement a VFPU-based psplibc/libmath. Maybe a good field test for our findings ;)

nevertheless this requires to set MALLOC_ALIGNMENT in newlib to 16. Are there any objections?
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Thu Oct 06, 2005 12:54 pm    Post subject: Reply with quote

And they just keep on coming:

Code:

/*
+----------------------+--------------+----+--------------+---+--------------+
|31                 23 | 22        16 | 15 | 14         8 | 7 | 6         0  |
+----------------------+--------------+----+--------------+---+--------------+
| opcode 0xf08  (p)    | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xf10  (t)    | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xf18  (q)    | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
+----------------------+--------------+----+--------------+---+--------------+

  VectorTransform.Pair/Triple/Quad

    vtfm2.p %vfpu_rd, %vfpu_rs, %vfpu_rt ; Transform pair vector by pair matrix
    vtfm3.t %vfpu_rd, %vfpu_rs, %vfpu_rt ; Transform triple vector by triple matrix
    vtfm4.q %vfpu_rd, %vfpu_rs, %vfpu_rt ; Transform quad vector by quad matrix

        %vfpu_rt:   VFPU Vector Source Register (qreg 0..127)
        %vfpu_rs:   VFPU Matrix Source Register (qmatrix 0..127)
        %vfpu_rd:   VFPU Vector Destination Register (qreg 0..127)

    vfpu_regs[%vfpu_rd] <- transform(vfpu_matrix[%vfpu_rs], vfpu_vector[%vfpu_rt])
*/

#define vtfm2_p(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF0800080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vtfm3_t(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1008000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vtfm4_q(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1808080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))

/*
+----------------------+--------------+----+--------------+---+--------------+
|31                 23 | 22        16 | 15 | 14         8 | 7 | 6         0  |
+----------------------+--------------+----+--------------+---+--------------+
| opcode 0xf08 (p)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xf10 (t)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xf18 (q)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
+----------------------+--------------+----+--------------+---+--------------+

  VectorHomogeneousTransform.Pair/Triple/Quad

    vhtfm2.p %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix
    vhtfm3.t %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix
    vhtfm4.q %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix

        %vfpu_rt:   VFPU Vector Source Register (qreg 0..127)
        %vfpu_rs:   VFPU Matrix Source Register (qmatrix 0..127)
        %vfpu_rd:   VFPU Vector Destination Register (qreg 0..127)

    vfpu_regs[%vfpu_rd] <- homeogenoustransform(vfpu_matrix[%vfpu_rs], vfpu_vector[%vfpu_rt])
*/

#define vhtfm2_p(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF0800000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vhtfm3_t(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1000080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vhtfm4_q(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1808000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))


also my implementation of vmmul is wrong, it should be:
Code:

#define vmmul_p(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0000080 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))
#define vmmul_t(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0008000 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))
#define vmmul_q(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0008080 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))


this implements the inverted bit special case I saw in mips_dis.c

and for shits n giggles:
Code:

/*
   1   0    0   0
   0   cx   sx  0
   0   -sx  cx  0
   0   0    0   1
*/
void vfpu_rotateX(float degrees) {
   register void *ptr __asm ("a0") = vfpu_vars;
   vfpu_vars[0] = degrees / 90.0;
   __asm__ volatile (
      cgen_asm(lv_s(0, 0, R_a0, 0))
      cgen_asm(vsin_s(125, 0))
      cgen_asm(vcos_s(126, 0))
      cgen_asm(vmidt_q(Q_M000))
      cgen_asm(vmov_s(S_S011, 126))
      cgen_asm(vmov_s(S_S012, 125))
      cgen_asm(vneg_s(S_S021, 125))
      cgen_asm(vmov_s(S_S022, 126))
   : "=r"(ptr) : "r"(ptr) : "memory");
}

/*
   cy  0    -sy 0
   0   1    0   0
   sy  0    cy  0
   0   0    0   1
*/

void vfpu_rotateY(float degrees) {
   register void *ptr __asm ("a0") = vfpu_vars;
   vfpu_vars[0] = degrees / 90.0;
   __asm__ volatile (
      cgen_asm(lv_s(4, 0*4, R_a0, 0))
      cgen_asm(vsin_s(125, 4))
      cgen_asm(vcos_s(126, 4))
      cgen_asm(vmidt_q(Q_M100))
      cgen_asm(vmov_s(S_S100, 126))
      cgen_asm(vneg_s(S_S102, 125))
      cgen_asm(vmov_s(S_S120, 125))
      cgen_asm(vmov_s(S_S122, 126))
   : "=r"(ptr) : "r"(ptr) : "memory");
}

/*
   cz  sz   0   0
   -sz cz   0   0
   0   0    1   0
   0   0    0   1
*/

void vfpu_rotateZ(float degrees) {
   register void *ptr __asm ("a0") = vfpu_vars;
   vfpu_vars[0] = degrees / 90.0;
   __asm__ volatile (
      cgen_asm(lv_s(8, 0*4, R_a0, 0))
      cgen_asm(vsin_s(125, 8))
      cgen_asm(vcos_s(126, 8))
      cgen_asm(vmidt_q(Q_M200))
      cgen_asm(vmov_s(S_S200, 126))
      cgen_asm(vmov_s(S_S201, 125))
      cgen_asm(vneg_s(S_S210, 125))
      cgen_asm(vmov_s(S_S211, 126))
   : "=r"(ptr) : "r"(ptr) : "memory");
}

/*void matrix_projection(float* matrix, float fovy, float aspect, float near, float far)
{
   matrix_identity(matrix);

   float angle = (fovy / 2.0f) * (M_PI/180.0f);
   float cotangent = cosf(angle) / sinf(angle);

   matrix[(0<<2)+0] = cotangent / aspect;
   matrix[(1<<2)+1] = cotangent;
   matrix[(2<<2)+2] = (far + near) / (near - far);
   matrix[(3<<2)+2] = 2.0f * (far * near) / (near - far);
   matrix[(2<<2)+3] = -1;
   matrix[(3<<2)+3] = 0.0f;
}*/

void vfpu_projection(float fov, float aspect, float near, float far) {

   vfpu_vars[0] = (fov / 2.0f) / 90.0f;
   vfpu_vars[1] = (far + near) / (near - far);
   vfpu_vars[2] = 2.0f * (far * near) / (near - far);
   vfpu_vars[3] = aspect;
   register void *ptr __asm ("a0") = vfpu_vars;
   __asm__ volatile (
      cgen_asm(vmidt_q(Q_M300))
      cgen_asm(lv_q(Q_R703, 0, R_a0, 0))
      cgen_asm(vsin_s(S_S702, S_S703))
      cgen_asm(vcos_s(S_S712, S_S703))
      cgen_asm(vdiv_s(S_S311, S_S712, S_S702))
      cgen_asm(vdiv_s(S_S300, S_S311, S_S733))
      cgen_asm(vmov_s(S_S322, S_S713))
      cgen_asm(vmov_s(S_S323, S_S723))
      cgen_asm(vone_s(S_S332))
      cgen_asm(vneg_s(S_S332, S_S332))
      cgen_asm(vzero_s(S_S333))
      : "=r"(ptr) : "r"(ptr) : "memory");
}


void vfpu_concatXYZ(void) {
   __asm__ volatile (
      cgen_asm(vmmul_q(Q_M400, Q_M000, Q_M100))
      cgen_asm(vmmul_q(Q_E500, Q_M400, Q_M200))
   );
}

void vfpu_transform(float x, float y, float z) {
   vfpu_vars[0] = x;
   vfpu_vars[1] = y;
   vfpu_vars[2] = z;
   vfpu_vars[3] = 1.0;
   register void *ptr __asm ("a0") = vfpu_vars;
   __asm__ volatile (
      cgen_asm(lv_q(Q_R700, 0, R_a0, 0))
      cgen_asm(vtfm4_q(Q_R701, Q_M500, Q_R700))
      cgen_asm(vtfm4_q(Q_R702, Q_M300, Q_R701))
      : "=r"(ptr) : "r"(ptr) : "memory");
}


Thats a little matrix library I've been implementing as I was figuring out the vfpu opcodes. The transform code simply performs the rotation/projection transform, I'm not storing the result anywhere. Ill polish this up later after I get some sleep =)
Back to top
View user's profile Send private message
dot_blank



Joined: 28 Sep 2005
Posts: 498
Location: Brasil

PostPosted: Thu Oct 06, 2005 1:14 pm    Post subject: Reply with quote

8) looks good to me
_________________
10011011 00101010 11010111 10001001 10111010
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Fri Oct 07, 2005 2:37 am    Post subject: Reply with quote

MrMr[iCE] wrote:
And they just keep on coming:

Code:

/*
+----------------------+--------------+----+--------------+---+--------------+
|31                 23 | 22        16 | 15 | 14         8 | 7 | 6         0  |
+----------------------+--------------+----+--------------+---+--------------+
| opcode 0xf08 (p)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
| opcode 0xf10 (t)     | vfpu_rt[6-0] |  0 | vfpu_rs[6-0] | 1 | vfpu_rd[6-0] |
| opcode 0xf18 (q)     | vfpu_rt[6-0] |  1 | vfpu_rs[6-0] | 0 | vfpu_rd[6-0] |
+----------------------+--------------+----+--------------+---+--------------+

  VectorHomogeneousTransform.Pair/Triple/Quad

    vhtfm2.p %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix
    vhtfm3.t %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix
    vhtfm4.q %vfpu_rd, %vfpu_rs, %vfpu_rt ; Homogeneous transform quad vector by quad matrix

        %vfpu_rt:   VFPU Vector Source Register (qreg 0..127)
        %vfpu_rs:   VFPU Matrix Source Register (qmatrix 0..127)
        %vfpu_rd:   VFPU Vector Destination Register (qreg 0..127)

    vfpu_regs[%vfpu_rd] <- homeogenoustransform(vfpu_matrix[%vfpu_rs], vfpu_vector[%vfpu_rt])
*/

#define vhtfm2_p(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF0800000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vhtfm3_t(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1000080 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))
#define vhtfm4_q(vfpu_rd,vfpu_rs,vfpu_rt)  (0xF1808000 | ((vfpu_rt) << 16) | ((vfpu_rs) << 8) | (vfpu_rd))




mmmh... I fear we need to add some explanations what a "homogenous transform" is and where exactly the difference to the "normal" transform is...


Quote:

also my implementation of vmmul is wrong, it should be:
Code:

#define vmmul_p(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0000080 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))
#define vmmul_t(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0008000 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))
#define vmmul_q(vfpu_rd, vfpu_rs, vfpu_rt) (0xf0008080 | ((vfpu_rt) << 16) | (((vfpu_rs) ^ 0x20) << 8) | (vfpu_rd))


this implements the inverted bit special case I saw in mips_dis.c


fixed+added, thanks!
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Fri Oct 07, 2005 3:13 pm    Post subject: Reply with quote

This could be done a lot faster if you were on irc man, there are some very smart cookies on #pspdev who have been a tremendous help with some of these ops, especially what the difference was between vdot/vhdp, etc. Trust me when I say, having someone to talk to in realtime, is WAY better than waiting for the next forum post =)
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Fri Oct 07, 2005 6:06 pm    Post subject: Reply with quote

then it would be cool to write this down for the public in the spec - knowledge that's not distributed is lost knowledge - ;)
well, I installed an irc client now, but since I'm connecting over a call-by-call dialup I'm not online that much time...
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Sat Oct 08, 2005 6:02 pm    Post subject: Reply with quote

well dont be a stranger, join us on #pspdev, on irc.freenode.org

I almost have a full implementation of pspgum that works with the Gu commands. I have a vector demo working with vfpu handling the matrix math. But you gotta get on irc to see it =)
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Sun Oct 09, 2005 4:35 am    Post subject: Reply with quote

I did some profiling, heres some results to give you an idea how well vfpu performs:

test case:
set up gu view matrix to identity
set up gu projection matrix
set up gu model matrix with x rotation, z rotation, and translate


with pspgum * 1000 runs, cpu at 222mhz
35155 us (micro seconds)

with pspvgum (my vfpu version of pspgum) * 1000 runs, cpu at 222mhz
3079 us

over 10x performace increase over pspgum. Any questions? =)
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sun Oct 09, 2005 4:46 am    Post subject: Reply with quote

:) yes: when does this gets moved to SVN? - ;)

nice done!
Back to top
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Sun Oct 09, 2005 9:43 am    Post subject: Reply with quote

holger wrote:
:) yes: when does this gets moved to SVN? - ;)

I would hold before forcing the VFPU on everyone. It may be more work to make it optional, but it will pay off.
Back to top
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Sun Oct 09, 2005 9:44 am    Post subject: Reply with quote

MrMr[iCE] wrote:
over 10x performace increase over pspgum. Any questions? =)

Have any real benchmarks? </devilsadvocate>
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Sun Oct 09, 2005 10:21 am    Post subject: Reply with quote

well im still waiting for SVN access from oobles, but here's something you can play with in the meantime.

http://bradburn.net/mr.mr/files/libpspvgum.zip

source included, also contains a small demo to try out the vfpu routines.

Quote:

Have any real benchmarks?


sorry man, I only did a simple gettimeofday difference. I dont know how to do a real benchmark..perhaps someone has code that does this?
Back to top
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Sun Oct 09, 2005 4:07 pm    Post subject: Reply with quote

I meant something along the lines of profiling a real app with and without VFPU support, but is there anything out there actively using libpspgum or any homebrew that could immediately benefit from the VFPU?
Back to top
View user's profile Send private message
MrMr[iCE]



Joined: 03 Oct 2005
Posts: 43

PostPosted: Sun Oct 09, 2005 6:33 pm    Post subject: Reply with quote

I guess we'll need someone to adapt the vfpu stuff into an existing app...I dont have anything to do a benchmark with besides my little 3d tests.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sun Oct 09, 2005 8:31 pm    Post subject: Reply with quote

mrbrown wrote:
holger wrote:
:) yes: when does this gets moved to SVN? - ;)

I would hold before forcing the VFPU on everyone. It may be more work to make it optional, but it will pay off.


mmh... this would prevent e.g. a inline-libm, most functions are implementable in a single asm instruction (+load/store)...
How would you want to make this optional, do you want to provide two versions of every library to link against?
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sun Oct 09, 2005 8:35 pm    Post subject: Reply with quote

mrbrown wrote:
I meant something along the lines of profiling a real app with and without VFPU support, but is there anything out there actively using libpspgum or any homebrew that could immediately benefit from the VFPU?


a VFPU-based libm would be of benefit for all.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sun Oct 09, 2005 8:41 pm    Post subject: Reply with quote

MrMr[iCE] wrote:
Quote:

Have any real benchmarks?


sorry man, I only did a simple gettimeofday difference. I dont know how to do a real benchmark..perhaps someone has code that does this?


See e.g. sdk/debug/profiler.c and ./sdk/samples/debug/profiler/main.c, this will also show minimized cache misses and CPU stalls of fine-tuned asm.

I don't know, though, whether the PSP has a cycle-exact counter register for exact timers. Anybody else?
Back to top
View user's profile Send private message
TyRaNiD



Joined: 18 Jan 2004
Posts: 918

PostPosted: Sun Oct 09, 2005 8:51 pm    Post subject: Reply with quote

The CPU cop0 has a cycle counter which you can access using the mfc0 $v0, $9 instruction. You must be in kernel mode though to use it.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sun Oct 09, 2005 8:55 pm    Post subject: Reply with quote

our experimental VFPU-test code is running it's setup in kernel mode anyways, since we are installing an exception handler. Thanks for the hint!

Is there a list of mfc-registers somewhere, are you referring to the MIPS manuals?
Back to top
View user's profile Send private message
jsgf



Joined: 12 Jul 2005
Posts: 254

PostPosted: Tue Oct 11, 2005 8:10 am    Post subject: Reply with quote

holger wrote:
a VFPU-based libm would be of benefit for all.


Maybe. Any performance gain might be eaten by all the shuffling things around between FP and VFPU registers for simple scalar stuff. A vector version of libm would be a better match.

I would like to see a very simple, thin libvfpu which provites two things:

  1. a set of macros to make inline assembler access to the VFPU easy (like gcc/icc's xmmintrin.h for SSE)
  2. a simple lightweight context switching mechanism to allow multiple libraries to share the VFPU without stomping on each other


I envisage 2 as having calls something like:
Code:
VFPUcontext *vfpuNewContext();
void vfpuSwitchContext(VFPUcontext *ctxt, MatrixSet used);
void vfpuFreeContext(VFPUcontext *);


where MatrixSet is a simple bitmask of which sets of matrix registers you want to use. If you're the only user of the VFPU, or you're using a disjoint set of registers from the other users, then vfpuSwitchContext would be a fairly cheap no-op; otherwise it would shuffle things around for you.

Obviously this could get expensive if you thrash contexts, but if you can be careful to work in relatively large batches, then you'll still get good performance. Certainly much better performance than letting unrelated VFPU users stomp on each other.
Back to top
View user's profile Send private message Visit poster's website
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Tue Oct 11, 2005 10:45 am    Post subject: Reply with quote

jsgf wrote:
Maybe. Any performance gain might be eaten by all the shuffling things around between FP and VFPU registers for simple scalar stuff. A vector version of libm would be a better match.

That was my point, that benchmarking a few matrix ops doesn't show whether or not everything should be replaced with VFPU code. I'm with jsgf in that there should be a set of VFPU compiler intrinsics, as well as a specialized VFPU library (it can overlap with libm if you want, but the decision to use the VFPU functions should be left up to the user).

Besides that, creating a VFPU-based thread incurs considerable overhead during a context switch. If you force the VFPU everywhere, then all threads would be required to maintain a VFPU context.
Back to top
View user's profile Send private message
ector



Joined: 12 May 2005
Posts: 195

PostPosted: Tue Oct 11, 2005 5:07 pm    Post subject: Reply with quote

mrbrown wrote:

Besides that, creating a VFPU-based thread incurs considerable overhead during a context switch. If you force the VFPU everywhere, then all threads would be required to maintain a VFPU context.


Almost correct, unless I'm misunderstanding you and you're 100% right but not clear enough :)

Most platforms with heavy additional register sets (such as Gekko in the Nintendo Gamecube) perform "lazy" context switching of "extra" (such as VFPU) registers, usually managed through a per-thread enable flag (as on PSP?) or by disabling the additional register sets and enabling and context switching in the illegal instruction exception handler (such as on Gekko). (Emulating this in an efficient manner is a PAIN!!! ;)

The consequence is that having one single thread with VFPU (or whatever extra register set your processor has) is ABSOLUTELY free in terms of context switching, because the vfpu regs will just be left there, but as soon as you add another vfpu thread, you will risk incurring the heavy costs.

Thus, I agree with mrbrown that vfpu should not be forced on everyone, while attempting to clear up some things that were not completely clear in mrbrown's post :)
_________________
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Tue Oct 11, 2005 7:51 pm    Post subject: Reply with quote

"heavy cost" is relative, save'n'restore the VFPU matrix registers involves 32 read/write cycles (which can get well-tuned to use write-through using the cache policy bits of the VFPU insns), that's is not too much compared to a single cache miss that's very likely to happen on a context switch anyways.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Tue Oct 11, 2005 7:57 pm    Post subject: Reply with quote

jsgf wrote:
I would like to see a very simple, thin libvfpu which provites two things:[list=1]
[*] a set of macros to make inline assembler access to the VFPU easy (like gcc/icc's xmmintrin.h for SSE)


yes, this would be nice, but requires some work in the toolchain, so that gcc knows how to schedule the VFPU registers.

jsgf wrote:
[*] a simple lightweight context switching mechanism to allow multiple libraries to share the VFPU without stomping on each other


becomes obsolete with the above...
Back to top
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Wed Oct 12, 2005 3:34 am    Post subject: Reply with quote

holger wrote:
"heavy cost" is relative, save'n'restore the VFPU matrix registers involves 32 read/write cycles (which can get well-tuned to use write-through using the cache policy bits of the VFPU insns), that's is not too much compared to a single cache miss that's very likely to happen on a context switch anyways.

There are more than 32 VFPU registers. You've missed the control registers.

The "heavy cost" is relative to what exactly? Do you know how painful a normal thread context switch is on the PSP, without saving and restoring the VFPU context?
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Wed Oct 12, 2005 3:46 am    Post subject: Reply with quote

mrbrown wrote:
There are more than 32 VFPU registers. You've missed the control registers.


we still don't know much about them... are they accessible and modifyable from userspace?

mrbrown wrote:
The "heavy cost" is relative to what exactly? Do you know how painful a normal thread context switch is on the PSP, without saving and restoring the VFPU context?


well, the usual rules for multithreaded OSes apply. you're accessing at least the interrupt vector code area, the old context's register save area, the new context register save area, the new code segment of the new thread, the data area of the new thread. At least 5 opportunities for a cache miss, more are not unlikely, depends whatever the new thread is doing...
Back to top
View user's profile Send private message
mrbrown



Joined: 17 Jan 2004
Posts: 1536

PostPosted: Wed Oct 12, 2005 5:01 am    Post subject: Reply with quote

holger wrote:
we still don't know much about them... are they accessible and modifyable from userspace?

Haven't you disasm'd a game that uses the VFPU (such as Wipeout)? The control registers are accessible with the current VFPU assembler (they don't need the wacky register syntax).
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Wed Oct 12, 2005 6:00 am    Post subject: Reply with quote

don't know whether it's running in user- or kernelspace, but that's easy to check.

btw, what's so wacky about the register syntax? The opcode bitfields look quite consistent, only prefix codes are somewhat unusual, but may get added later, on a first shot implementation one could use them as seperate instruction (or let a preprocessor generate matching vpfx instructions).
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
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
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