155 lines
3.7 KiB
C
155 lines
3.7 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
extern void* memcpy( void*, const void*, size_t n );
|
|
|
|
/* Register offsets within memory-mapped window */
|
|
enum
|
|
{
|
|
VU_REG_VF = 0, /* Start of VF registers */
|
|
VU_REG_VI = 0x200, /* Start of VI registers */
|
|
VU_REG_MST = 0x300, /* Start of misc registers */
|
|
VU_REG_MMC = 0x310,
|
|
VU_REG_MCP = 0x320,
|
|
VU_REG_MR = 0x330,
|
|
VU_REG_MI = 0x340,
|
|
VU_REG_MQ = 0x350,
|
|
VU_REG_MP = 0x360,
|
|
VU_REG_MTPC = 0x3a0,
|
|
VU_REG_STAT = 0x3d0, /* Start of special registers */
|
|
VU_REG_CIA = 0x3e0,
|
|
VU_REG_END = 0x3f0
|
|
};
|
|
|
|
#define VU0_REGISTER_WINDOW_START 0x10000C00
|
|
#define VU1_REGISTER_WINDOW_START 0x11007000
|
|
|
|
struct sreg {
|
|
short reg;
|
|
char filler[14];
|
|
};
|
|
|
|
struct wreg {
|
|
int reg;
|
|
char filler[12];
|
|
};
|
|
|
|
struct vuregs {
|
|
float f[32][4];
|
|
struct sreg i[16];
|
|
struct wreg m[16];
|
|
} vu[2];
|
|
|
|
struct vuregs buf;
|
|
|
|
int main() {
|
|
volatile char *vu0, *vu1;
|
|
int i, j;
|
|
float f;
|
|
short s;
|
|
int v;
|
|
long long int lli;
|
|
int error = 0;
|
|
|
|
vu0 = (char *) VU0_REGISTER_WINDOW_START;
|
|
vu1 = (char *) VU1_REGISTER_WINDOW_START;
|
|
|
|
/* Write VU1 registers using friendly alignments and sizes (common case?).
|
|
* At the same time, initialize local (reference) copy of VU0 registers.
|
|
*/
|
|
printf( "Initialize VU1 registers...\n" );
|
|
for( i=0; i<32; i++ )
|
|
for( j=0; j<4; j++ ) {
|
|
vu[0].f[i][j] = i + j/10.0;
|
|
|
|
vu[1].f[i][j] = 100.0 + i + j/10.0;
|
|
((struct vuregs *) vu1)->f[i][j] = vu[1].f[i][j];
|
|
}
|
|
|
|
for( i=0; i<16; i++ ) {
|
|
vu[0].i[i].reg = i;
|
|
|
|
vu[1].i[i].reg = 100 + i;
|
|
((struct vuregs *) vu1)->i[i].reg = 100 + i;
|
|
}
|
|
|
|
for( i=0; i<12; i++ ) {
|
|
vu[0].m[i].reg = i;
|
|
|
|
vu[1].m[i].reg = 100 + i;
|
|
((struct vuregs *) vu1)->m[i].reg = 100 + i;
|
|
}
|
|
|
|
/* Blast VU0 registers across using memcpy */
|
|
printf( "Initialize VU0 registers...\n" );
|
|
memcpy( vu0, &(vu[0]), VU_REG_END );
|
|
|
|
/* Check VU0 registers using friendly alignment and sizes */
|
|
printf( "Check VU0 initial register values...\n" );
|
|
for( i=0; i<32; i++ )
|
|
for( j=0; j<4; j++ ) {
|
|
f = ((struct vuregs *) vu0)->f[i][j];
|
|
if( f != vu[0].f[i][j] ) {
|
|
printf( "vu0_vf%02d%d: got %f (%x) != %f (%x)\n", i, j,
|
|
f, *((int *) &f), vu[0].f[i][j], *((int *) &(vu[0].f[i][j])));
|
|
error++;
|
|
}
|
|
}
|
|
|
|
for( i=0; i<16; i++ ) {
|
|
s = ((struct vuregs *) vu0)->i[i].reg;
|
|
if( s != vu[0].i[i].reg ) {
|
|
printf( "vu0_vi%02d: got %d (%x) != %d (%x)\n", i,
|
|
s, s, vu[0].i[i].reg, vu[0].i[i].reg );
|
|
error++;
|
|
}
|
|
}
|
|
|
|
for( i=0; i<7; i++ ) {
|
|
v = ((struct vuregs *) vu0)->m[i].reg;
|
|
if( v != vu[0].m[i].reg ) {
|
|
printf( "vu0_misc %2d: got %d (%x) != %d (%x)\n", i,
|
|
v, v, vu[0].m[i].reg, vu[0].m[i].reg );
|
|
error++;
|
|
}
|
|
}
|
|
|
|
/* Load buf from VU1 reg window a double word at a time */
|
|
for( i=0; i<VU_REG_END; i+=8 )
|
|
*((long long int *) (((char *) &buf) + i))
|
|
= *(( long long int *) (vu1 + i));
|
|
|
|
printf( "Check VU1 initial register values...\n" );
|
|
for( i=0; i<32; i++ )
|
|
for( j=0; j<4; j++ ) {
|
|
if( buf.f[i][j] != vu[1].f[i][j] ) {
|
|
printf( "vu1_vf%02d%d: got %f (%x) != %f (%x)\n", i, j,
|
|
buf.f[i][j], *((int *) &(buf.f[i][j])),
|
|
vu[1].f[i][j], *((int *) &(vu[1].f[i][j])) );
|
|
error++;
|
|
}
|
|
}
|
|
|
|
for( i=0; i<16; i++ ) {
|
|
if( buf.i[i].reg != vu[1].i[i].reg ) {
|
|
printf( "vu1_vi%02d: got %d (%x) != %d (%x)\n", i,
|
|
buf.i[i].reg, buf.i[i].reg, vu[1].i[i].reg, vu[1].i[i].reg );
|
|
error++;
|
|
}
|
|
}
|
|
|
|
for( i=0; i<7; i++ ) {
|
|
if( buf.m[i].reg != vu[1].m[i].reg ) {
|
|
printf( "vu1_misc %d: got %d (%x) != %d (%x)\n", i,
|
|
buf.m[i].reg, buf.m[i].reg, vu[1].m[i].reg, vu[1].m[i].reg );
|
|
error++;
|
|
}
|
|
}
|
|
|
|
if( error ) {
|
|
printf( "%d errors detected\n", error );
|
|
error = 1;
|
|
}
|
|
|
|
exit( error );
|
|
}
|