So, ich habe die Assembler-Optimierung zum laufen bekommen (beim casten von 16bit auf 32bit wird aus 0x0400-> 0x04000000, das DO-Bit ist damit 22 von rechts/Intel bzw. 9 von links/Motorola
), aber leider hat das zu keiner Geschwindigkeitsverbesserung geführt (ob ev. die Proz-last kleiner war habe ich nicht gemessen).
Gemessen habe ich das, indem ich ein 10MB über FTP geladen habe. Vielleicht liegt darin ja auch ein Fehler.
Folgender Code war sogar langsamer (10MB->37Sek, ca.260KB/s):
Code: Alles auswählen
static __inline__ int set_bit_from_bit( const unsigned int dest_nr,
unsigned int dest,
const unsigned int src_nr,
const unsigned int src)
{
__asm__ __volatile__("\n\
rlwinm %[src] ,%[src],32-%[src_nr],0,31 \n\
rlwimi %[dest],%[src],%[dest_nr],31-%[dest_nr],31-%[dest_nr] \n"
: [dest] "=&r" (dest)
: [src] "r" (src), [dest_nr] "i" (dest_nr), [src_nr] "i" (src_nr)
: "cc");
return dest;
}
void mmc_read_block_low_level(unsigned int *dest)
{
volatile cpm8xx_t *cp = (cpm8xx_t *) &immap->im_cpm;
volatile iop8xx_t *cpi = (iop8xx_t *) &immap->im_ioport;
volatile unsigned long * data =(volatile unsigned long *)&cpi->iop_padat;
unsigned long clk_high = cp->cp_pbdat | SD_CLK;
unsigned long clk_low = cp->cp_pbdat & ~SD_CLK;
unsigned int i;
unsigned int in;
cpi->iop_padat |= SD_DI;
for(i = 0; i<128; i++)
{
in = 0x00;
/* xx ns delay after clock before reading SD_DO is needed -
insert NOPs or move the clocksetting within the macro */
#define GET_THIS_BIT(n) cp->cp_pbdat = clk_high; \
in = set_bit_from_bit((n), in, SD_DO_NUM+16, *data); \
cp->cp_pbdat = clk_low;
GET_THIS_BIT(31);
...
GET_THIS_BIT(0);
*dest++ = in; /* endianness ok? */
}
}
und ergibt diesen Assembler-Code
Code: Alles auswählen
GET_THIS_BIT(31);
32c: 91 07 01 04 stw r8,260(r7)
330: 80 0b 00 00 lwz r0,0(r11)
334: 54 00 50 3e rotlwi r0,r0,10
338: 50 09 f8 00 rlwimi r9,r0,31,0,0
33c: 90 c7 01 04 stw r6,260(r7)
GET_THIS_BIT(30);
340: 91 07 01 04 stw r8,260(r7)
344: 80 0b 00 00 lwz r0,0(r11)
348: 54 00 50 3e rotlwi r0,r0,10
34c: 50 09 f0 42 rlwimi r9,r0,30,1,1
350: 90 c7 01 04 stw r6,260(r7)
Dann habe ich das lwz in lhz umgewandelt, und siehe es ging schon schneller (10MB->32Sek, ca.310KB/s):
Code: Alles auswählen
static __inline__ int set_bit_from_bit( const unsigned int dest_nr,
unsigned int dest,
const unsigned int src_nr,
const unsigned int src)
{
__asm__ __volatile__("\n\
rlwinm %[src] ,%[src],32-%[src_nr],0,31 \n\
rlwimi %[dest],%[src],%[dest_nr],31-%[dest_nr],31-%[dest_nr] \n"
: [dest] "=&r" (dest)
: [src] "r" (src), [dest_nr] "i" (dest_nr), [src_nr] "i" (src_nr)
: "cc");
return dest;
}
void mmc_read_block_low_level(unsigned int *dest)
{
volatile cpm8xx_t *cp = (cpm8xx_t *) &immap->im_cpm;
volatile iop8xx_t *cpi = (iop8xx_t *) &immap->im_ioport;
//volatile unsigned long * data =(volatile unsigned long *)&cpi->iop_padat;
unsigned long clk_high = cp->cp_pbdat | SD_CLK;
unsigned long clk_low = cp->cp_pbdat & ~SD_CLK;
unsigned int i;
unsigned int in;
cpi->iop_padat |= SD_DI;
for(i = 0; i<128; i++)
{
in = 0x00;
/* xx ns delay after clock before reading SD_DO is needed -
insert NOPs or move the clocksetting within the macro */
#define GET_THIS_BIT(n) cp->cp_pbdat = clk_high; \
in = set_bit_from_bit((n), in, SD_DO_NUM, cpi->iop_padat); \
cp->cp_pbdat = clk_low;
GET_THIS_BIT(31);
...
GET_THIS_BIT(0);
*dest++ = in; /* endianness ok? */
}
}
ergibt folgenden Assembler-Code:
Code: Alles auswählen
51c: 91 4b 01 04 stw r10,260(r11)
520: a0 07 00 06 lhz r0,6(r7)
524: 54 00 d0 3e rotlwi r0,r0,26
528: 50 09 36 72 rlwimi r9,r0,6,25,25
52c: 91 0b 01 04 stw r8,260(r11)
Die ganze Sache als byte geht genauso schnell (32Sec)
.
Code: Alles auswählen
static __inline__ int set_bit_from_bit( const unsigned int dest_nr,
unsigned int dest,
const unsigned int src_nr,
const unsigned int src)
{
__asm__ __volatile__("\n\
rlwinm %[src] ,%[src],32-%[src_nr],0,31 \n\
rlwimi %[dest],%[src],%[dest_nr],31-%[dest_nr],31-%[dest_nr] \n"
: [dest] "=&r" (dest)
: [src] "r" (src), [dest_nr] "i" (dest_nr), [src_nr] "i" (src_nr)
: "cc");
return dest;
}
void mmc_read_block_low_level(unsigned char *dest)
{
volatile cpm8xx_t *cp = (cpm8xx_t *) &immap->im_cpm;
volatile iop8xx_t *cpi = (iop8xx_t *) &immap->im_ioport;
//volatile unsigned long * data =(volatile unsigned long *)&cpi->iop_padat;
unsigned long clk_high = cp->cp_pbdat | SD_CLK;
unsigned long clk_low = cp->cp_pbdat & ~SD_CLK;
unsigned int i;
unsigned int in;
cpi->iop_padat |= SD_DI;
for(i = 0; i<512; i++)
{
in = 0x00;
/* xx ns delay after clock before reading SD_DO is needed -
insert NOPs or move the clocksetting within the macro */
#define GET_THIS_BIT(n) cp->cp_pbdat = clk_high; \
in = set_bit_from_bit((n), in, SD_DO_NUM, cpi->iop_padat); \
cp->cp_pbdat = clk_low;
GET_THIS_BIT(7);
GET_THIS_BIT(6);
GET_THIS_BIT(5);
GET_THIS_BIT(4);
GET_THIS_BIT(3);
GET_THIS_BIT(2);
GET_THIS_BIT(1);
GET_THIS_BIT(0);
*dest++ = in; /* endianness ok? */
}
}
Das ist aber nur so schnell wie die bisherige Optimierung 10 (braucht sogar nur 31 Sekunden), da sieht der Assembler-Code wie folgt aus:
Code: Alles auswählen
cp->cp_pbdat = clk_high; //4
26c: 91 4b 01 04 stw r10,260(r11)
result <<= 1;result |= ((cpi->iop_padat & SD_DO)?0x01:0x00);
270: a0 08 00 06 lhz r0,6(r8)
274: 55 29 d7 fe rlwinm r9,r9,26,31,31
278: 54 63 08 3c rlwinm r3,r3,1,0,30
cp->cp_pbdat = clk_low;
27c: 90 eb 01 04 stw r7,260(r11)
280: 7d 23 1b 78 or r3,r9,r3
Das sieht doch ziemlich identisch aus und hat sogar 1 Assembler-Befehl mehr. Das rlwinm muss demnach schneller sein als rotlwi/rlwimi, oder das Nadelöhr ist noch wo anders.
Wie es aussieht werden wir so wohl nicht schneller werden. Eventuell kann man im Assembler-Code noch ein Befehl einsparen (ungetestet),
Code: Alles auswählen
stw r10,260(r11)
lhz r0,6(r7)
rlwimi r9,r0,9,0,0
stw r8,260(r11)
stw r10,260(r11)
lhz r0,6(r7)
rlwimi r9,r0,8,1,1
stw r8,260(r11)
..
stw r10,260(r11)
lhz r0,6(r7)
rlwimi r9,r0,0,9,9
stw r8,260(r11)
stw r10,260(r11)
lhz r0,6(r7)
rlwimi r9,r0,31,10,10
stw r8,260(r11)
...
aber obs was bringt?
Sollte irgendwo anders ein Nadelöhr sein, würde auch eine SMC-Optimierung nichts bringen. Hat jemand eine Ahnung???
Günther
Ich habe das file soeben als mmc2test.c (diesmal in Head ()) eingescheckt. Ev. Könnte jemand das file mmc3.c in newmake löschen, ich war zu doof dazu (ev. habe ich auch keine Rechte). Hoffe das ist jetzt besser