Just so you know ,the code as is is just a mask operation and an add. The multiplies will never be at runtime because they are in a constant expression so they are free at runtime because the compiler did them.kouky posted on Feb 6 2007 at 05:28 PM said:I've found a solution:
Code:unsigned short r1,v1,b1; for (iii=0;iii<screenWH;iii++) { b1=(koukyTiles16[iii]& 31)+(koukyTiles16[iii+screenWH]& 31); v1=( (koukyTiles16[iii]& (63*32)) )+( (koukyTiles16[iii+screenWH]& (63*32)) )>>5; r1=( (koukyTiles16[iii]& (31*64*32)) )+( (koukyTiles16[iii+screenWH]& (31*64*32)) )>>11; if (b1>31)b1=31; if (v1>63)v1=63; if (r1>31)r1=31; finalTiles16[iii] =(b1)+ (v1<<5)+(r1<<11); }
but it's very heavy coding !
I wish I could optimise it
unsigned short r1,v1,b1;
int * ptr1 = koukyTiles16, *ptr2 = koukyTiles16 + screenWH;
int p1, p2;
for (iii=0;iii<screenWH;iii++)
{
p1 = *ptr1; // single dereference (hope to keep in register)
p2 = *ptr2; // single dereference
b1=(p1 & 31)+(p2 & 31); // constant 5 bits or less so internal to instruction
v1=( (p1 & (63*32)) )+( (p2 & (63*32)) )>>5;
r1=( (p1 & (31*64*32)) )+( (p2 & (31*64*32)) )>>11;
ptr1++; // move to next element in array
ptr2++; // move to next element in array
if (b1>31)b1=31;
if (v1>63)v1=63;
if (r1>31)r1=31;
finalTiles16[iii] =(b1)+ (v1<<5)+(r1<<11);
}
This condition will always be false, you're losing the carried bit because you're using shorts.Dr_Ian posted on Feb 7 2007 at 10:34 AM said:Code:unsigned short r1,v1,b1; if (r1>0xF800)r1=0xF800;
unsigned int rb, g;
for (iii=0;iii<screenWH;iii++)
{
rb=(koukyTiles16[iii] & ~0x07E0) + (koukyTiles16[iii+screenWH] & ~0x07E0);
g=(koukyTiles16[iii] & 0x07E0) + (koukyTiles16[iii+screenWH] & 0x07E0);
if ((rb&0x0020)!=0)rb=(rb&~0x001F)-1;
if ((rb&0x10000)!=0)rb|=0xF800;
if ((g&0x0800)!=0)g=0x07E0;
finalTiles16[iii] = rb | g;
}
unsigned short *dest, *src;
dest = koukyTiles16;
src = koukyTiles16 + screenWH;
for (iii=screenWH;iii!=0;--iii)
{
...*dest...*src...;
*dest = rb | g;
++dest; ++src;
}
Gary Miller posted on Feb 7 2007 at 05:17 PM said:You might try: (sorry for the bad variable names)
Code:unsigned int r1,v1,b1; int * ptr1 = koukyTiles16, *ptr2 = koukyTiles16 + screenWH; int p1, p2; for (iii=0;iii<screenWH;iii++) { p1 = *ptr1; // single dereference (hope to keep in register) p2 = *ptr2; // single dereference b1=(p1 & 31)+(p2 & 31); // constant 5 bits or less so internal to instruction v1=( (p1 & (63*32)) )+( (p2 & (63*32)) )>>5; r1=( (p1 & (31*64*32)) )+( (p2 & (31*64*32)) )>>11; ptr1++; // move to next element in array ptr2++; // move to next element in array if (b1>31)b1=31; if (v1>63)v1=63; if (r1>31)r1=31; finalTiles16[iii] =(b1)+ (v1<<5)+(r1<<11); }
I did not try this so it might not be any faster ... (could be syntax errors too)
const unsigned int mask = 0xF81F07E0 >> 1;
const unsigned int carry1 = 0x08010020;
const unsigned int carry2 = 0x80100400;
unsigned int *src = (unsigned int *)koukyTiles16;
unsigned int *dst = (unsigned int *)(koukyTiles16 + screenWH);
for (int n = screenWH; n != 0; n -= 2)
{
ss = *src++;
dd = *dst;
// .....GGG GGG..... rrrrr... ...bbbbb
d1 = (ss & ~(mask<<1)) + (dd & ~(mask<<1));
// >RRRRR.. ...>BBBB B....>gg gggg....
d2 = ((ss>>1) & mask) + ((dd>>1) & mask);
// .....GGG GGG..... rrrrr... ...bbbbb
// 1 1 1
c1 = d1 & carry1;
// >RRRRR.. ...>BBBB B....>gg gggg....
// 1 1 1
c2 = d2 & carry2;
// .....GGG GGG..... rrrrr... ...bbbbb
// >>>> >1 > >>>>1 >>>>>1 >>5
// 111 11* 11111 11111 *31
d1 = (d1 & ~c1) | ((c1 >> 5) * 31);
// _RRRRR.. ....BBBB B.....gg gggg....
// >>>>>1 >>>>> 1 >>> >>1 >>5
// 11111 1111 1 11 111* *31
d2 = (d2 & ~c2) | ((c2 >> 5) * 31);
*dst++ = d1 + (d2<<1);
}
Good point...This condition will always be false, you're losing the carried bit because you're using shorts.
int rb, v;
short *ptr1 = koukyTiles16, *ptr2 = koukyTiles16 + screenWH;
int p1, p2;
for (iii=0;iii<screenWH;iii++)
{
p1 = *(ptr1++);
p2 = *(ptr2++);
rb = (p1 & 0xF81F) + (p2 & 0xF81F);
v = (p1 & 0x07E0) + (p2 & 0x07E0);
if ((rb&0x0020)) rb = (rb & 0x1F800) | 0x001F;
if ((rb&0x10000)) rb |= 0xF800;
if ((g&0x0800)) g = 0x07E0;
finalTiles16[iii] = rb | g;;
}
In C and C++, a is exactly the same as *(a+B). Also, I believe the indirect load/store operations on ARM can automatically adjust the pointer at the same time. Together, this means that you can entirely eliminate one add per array reference here. It's not huge, but it is slightly faster. (and it's usually not worth it if you're not in a loop) Also, it allows you to easily count downwards, which is better because zero is the easiest number to compare against. (I guess you could have done that anyway... I want to think that it would have made a difference with the cache, but that sounds wrong.)kouky posted on Feb 8 2007 at 12:47 PM said:Is it a good thing to use pointers instead of regulars arrays whenever it's possible ?
Cause i'm now trying to add lot of pointers stuffs all along my software...
Is it always faster to opt for the "pointer" option ?