Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 6. srpen 2024, 16:24:03 Předmět: |
|
|
Ladis napsal: |
Existuje nějaký emulátor PC x86, který má přesné časování? PCem? |
PCem je super, používal jsem ho 2 roky zpátky na testování pro hvdosdev
ale otázka je, jak moc je cycle-exact oproti železu - přišlo mi že pro 486DX2/66
byl pořád rychlejší, než co frca reportoval nějaká čísla na reálném hw.
bez hw je ale PCem asi nejlepší volba
EDIT: tak PCem říká, že nová verze (v4) by měla být cca o 7% rychlejší, než stará verze 3 a v4a je nejpomalejší
tady dávám gcc assembler verzi a AT&T syntaxí:
kód: |
void __attribute__ ((noinline)) make_compact_asm4()
{
asm volatile(
//dsti*4
"xor %%edi, %%edi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+0*4(,%%edi,4), %%eax\n"
"mov %0+1*4(,%%edi,4), %%ebx\n"
"mov %0+2*4(,%%edi,4), %%ecx\n"
"mov %0+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
"ror $16, %%eax\n"
"xchg %%cl, %%al\n"
"xchg %%dl, %%ah\n"
"ror $16, %%eax\n"
"ror $16, %%ebx\n"
"xchg %%ch, %%bl\n"
"xchg %%dh, %%bh\n"
"ror $16, %%ebx\n"
"ror $16, %%edx\n"
"ror $16, %%ecx\n"
"xchg %%dl, %%ch\n"
"ror $16, %%ecx\n"
"ror $16, %%edx\n"
// store packed0
"mov %%eax, %1+0*320*240/4(%%edi)\n"
// store packed1
"mov %%ebx, %1+1*320*240/4(%%edi)\n"
// store packed2
"mov %%ecx, %1+2*320*240/4(%%edi)\n"
// store packed3
"mov %%edx, %1+3*320*240/4(%%edi)\n"
"add $4, %%edi\n"
"cmp $320*240/4, %%edi\n"
"jb 1b\n"
:
: "m"(colors), "m"(packed)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%edi"
);
}
void __attribute__ ((noinline)) make_compact_asm4a()
{
asm volatile(
//dsti*4
"xor %%edi, %%edi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+0*4(,%%edi,4), %%eax\n"
"mov %0+1*4(,%%edi,4), %%ebx\n"
"mov %0+2*4(,%%edi,4), %%ecx\n"
"mov %0+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
// store packed0, lo16
"mov %%ax, %1+0*320*240/4(%%edi)\n"
"shr $16, %%eax\n"
"xchg %%cl, %%al\n"
"xchg %%dl, %%ah\n"
// store packed0, hi16
"mov %%ax, %1+0*320*240/4+2(%%edi)\n"
// store packed1, lo16
"mov %%bx, %1+1*320*240/4(%%edi)\n"
"shr $16, %%ebx\n"
"xchg %%ch, %%bl\n"
"xchg %%dh, %%bh\n"
// store packed1, hi16
"mov %%bx, %1+1*320*240/4+2(%%edi)\n"
// store packed2, lo16
"mov %%cx, %1+2*320*240/4(%%edi)\n"
// store packed3, lo16
"mov %%dx, %1+3*320*240/4(%%edi)\n"
"shr $16, %%edx\n"
"shr $16, %%ecx\n"
"xchg %%dl, %%ch\n"
// store packed2, hi16
"mov %%cx, %1+2*320*240/4+2(%%edi)\n"
// store packed3, hi16
"mov %%dx, %1+3*320*240/4+2(%%edi)\n"
"add $4, %%edi\n"
"cmp $320*240/4, %%edi\n"
"jb 1b\n"
:
: "m"(colors), "m"(packed)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%edi"
);
}
|
|
|
Návrat nahoru |
|
|
frca
Založen: 28. 07. 2007 Příspěvky: 1558
|
Zaslal: 11. srpen 2024, 22:01:27 Předmět: |
|
|
Díky, benchnu to, až se k tomu dostanu _________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 12. srpen 2024, 16:48:24 Předmět: |
|
|
frca napsal: |
Díky, benchnu to, až se k tomu dostanu |
super
mezitím jsem si uvědomil, že bswap je 1 cycle na 486 (tudíž by měl být 2x rychlejší než rol) - v pcemu jasný vítež verze 5, která ale nepoběží na 386:
kód: |
void __attribute__ ((noinline)) make_compact_asm5()
{
asm volatile(
//dsti*4
"xor %%edi, %%edi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+0*4(,%%edi,4), %%eax\n"
"mov %0+1*4(,%%edi,4), %%ebx\n"
"mov %0+2*4(,%%edi,4), %%ecx\n"
"mov %0+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
"bswap %%eax\n"
"xchg %%cl, %%ah\n"
"xchg %%dl, %%al\n"
"bswap %%eax\n"
"bswap %%ebx\n"
"xchg %%ch, %%bh\n"
"xchg %%dh, %%bl\n"
"bswap %%ebx\n"
"bswap %%edx\n"
"bswap %%ecx\n"
"xchg %%dh, %%cl\n"
"bswap %%ecx\n"
"bswap %%edx\n"
// store packed0
"mov %%eax, %1+0*320*240/4(%%edi)\n"
// store packed1
"mov %%ebx, %1+1*320*240/4(%%edi)\n"
// store packed2
"mov %%ecx, %1+2*320*240/4(%%edi)\n"
// store packed3
"mov %%edx, %1+3*320*240/4(%%edi)\n"
"add $4, %%edi\n"
"cmp $320*240/4, %%edi\n"
"jb 1b\n"
:
: "m"(colors), "m"(packed)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%edi"
);
}
|
EDIT:
ještě mě napadla jedna věc, ale nevím jestli/kolik by to pomohlo:
idea je, že už během vyrábění kompaktního bufferu by se dal třeba eax (packed0) sypat rovnou do video paměti
tím by se ušetřila první část memcpy a i trochu paměti (packed by mohl být o čtvrtinu menší)
esi registr máme v nové verzi volný, takže by se dal použít jako vga base a pak to eax zapisovat do [esi+edi]
muselo by se to samozřejmě změřit všechno
verze 5a, u mě funguje ale nedokážu změřit a porovnat:
kód: |
void __attribute__ ((noinline)) make_compact_asm5a(const void *vga)
{
asm volatile(
// dsti*4
"xor %%edi, %%edi\n"
// vga
"mov %2, %%esi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+0*4(,%%edi,4), %%eax\n"
"mov %0+1*4(,%%edi,4), %%ebx\n"
"mov %0+2*4(,%%edi,4), %%ecx\n"
"mov %0+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
"bswap %%eax\n"
"xchg %%cl, %%ah\n"
"xchg %%dl, %%al\n"
"bswap %%eax\n"
"bswap %%ebx\n"
"xchg %%ch, %%bh\n"
"xchg %%dh, %%bl\n"
"bswap %%ebx\n"
"bswap %%edx\n"
"bswap %%ecx\n"
"xchg %%dh, %%cl\n"
"bswap %%ecx\n"
"bswap %%edx\n"
// store vga
"mov %%eax, (%%esi, %%edi)\n"
// store packed0
"mov %%ebx, %1+0*320*240/4(%%edi)\n"
// store packed1
"mov %%ecx, %1+1*320*240/4(%%edi)\n"
// store packed2
"mov %%edx, %1+2*320*240/4(%%edi)\n"
"add $4, %%edi\n"
"cmp $320*240/4, %%edi\n"
"jb 1b\n"
:
: "m"(colors), "m"(packed), "m"(vga)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%esi", "%edi"
);
}
|
tzn idea zjevně připravit bit plane 0, zavolat make_compact5a s vga pointerem,
to jako side effect naplní zbylé 3 části packed pole, které pak počkračují standardním způsobem (set bitplane + memcpy), packed pole pro v5a je jenom 3/4 původního |
|
Návrat nahoru |
|
|
frca
Založen: 28. 07. 2007 Příspěvky: 1558
|
Zaslal: 25. srpen 2024, 22:16:24 Předmět: |
|
|
Na 486 66 MHz, výsledek v ms
3 6703
4 6703
4a 6428
5 6428
5a se mi nevykresluje správně (jeden bitplane je černý), asi ho neumím adaptovat na svůj example https://github.com/Franticware/dos-modex-djgpp
Je to vidět i v dosboxu.
Zatím je kandidátem 4a, který je znatelně rychlejší a pojede i na 386. _________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 26. srpen 2024, 06:16:23 Předmět: |
|
|
díky za test, zajímavé
překvapuje mě, že 5 není rychlejší než 4a (možná by se dala udělat ještě varita 4a s bswapem)
ta adaptace by mohla být cca nějak takhle (netestováno):
kód: |
void framebuf_flip(uint8_t* VGA, int vsync)
{
static int page = 0;
int target_page = page + 1;
if (target_page > 2)
target_page = 0;
VGA += target_page * 19200;
outp(SC_INDEX, MAP_MASK);
outp(SC_DATA, 1);
make_compact_asm5a(VGA);
outp(SC_INDEX, MAP_MASK);
outp(SC_DATA, 2);
memcpy(VGA, packed[0], 19200);
outp(SC_INDEX, MAP_MASK);
outp(SC_DATA, 4);
memcpy(VGA, packed[1], 19200);
outp(SC_INDEX, MAP_MASK);
outp(SC_DATA, 8);
memcpy(VGA, packed[2], 19200);
while (vsync && (inportb(SR) & VRETRACE))
;
word_out(CRTC_INDEX, PAGE_MSB, ((320 * 240) >> 10) * target_page);
while (vsync && !(inportb(SR) & VRETRACE))
;
page = target_page;
}
|
pokud bude 5a rychlejší, udělal bych ještě asi obdobu 4b z 4a
kompatibilitou s 386 bych se asi až tolik netrápil, detekce 486 z flagů je problematická a nefunguje dobře, ale není to nic co by se nedalo v nejhorším vyřešit commandline přepínačem, případně ještě zkusit chytit výjimku při nepodporované instrukci, ale do toho bych se asi nepouštěl |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 26. srpen 2024, 17:05:33 Předmět: |
|
|
taky tady ještě 5b a 4c - ještě by měl jít ušetřit 1 cycle per loop posunutím indexu a tím pádem jet add + jnz bez cmp, takový offset trik
na moderních CPU by to nemělo smysl, protože cmp+jxx dělá macro-op fusion, ale tady by to mělo ještě něco mikroždímnout
4b jsem ani tím pádem nedělal a přeskočil jsem to
u verze 4c mám trochu strach s těmi extra writy do vram, ale uvidíme
kód: |
void __attribute__ ((noinline)) make_compact_asm5b(const void *vga)
{
asm volatile(
// dsti*4 - offset
"mov $-320*240/4, %%edi\n"
// vga
"mov %2, %%esi\n"
"sub %%edi, %%esi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+320*240+0*4(,%%edi,4), %%eax\n"
"mov %0+320*240+1*4(,%%edi,4), %%ebx\n"
"mov %0+320*240+2*4(,%%edi,4), %%ecx\n"
"mov %0+320*240+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
"bswap %%eax\n"
"xchg %%cl, %%ah\n"
"xchg %%dl, %%al\n"
"bswap %%eax\n"
"bswap %%ebx\n"
"xchg %%ch, %%bh\n"
"xchg %%dh, %%bl\n"
"bswap %%ebx\n"
"bswap %%edx\n"
"bswap %%ecx\n"
"xchg %%dh, %%cl\n"
"bswap %%ecx\n"
"bswap %%edx\n"
// store vga
"mov %%eax, (%%esi, %%edi)\n"
// store packed0
"mov %%ebx, %1+1*320*240/4(%%edi)\n"
// store packed1
"mov %%ecx, %1+2*320*240/4(%%edi)\n"
// store packed2
"mov %%edx, %1+3*320*240/4(%%edi)\n"
"add $4, %%edi\n"
"jnz 1b\n"
:
: "m"(colors), "m"(packed), "m"(vga)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%esi", "%edi"
);
}
void __attribute__ ((noinline)) make_compact_asm4c(const void *vga)
{
asm volatile(
// dsti*4 - offset
"mov $-320*240/4, %%edi\n"
// vga
"mov %2, %%esi\n"
"sub %%edi, %%esi\n"
"1:\n"
// stupid at&t: disp(base, index, scale)
"mov %0+320*240+0*4(,%%edi,4), %%eax\n"
"mov %0+320*240+1*4(,%%edi,4), %%ebx\n"
"mov %0+320*240+2*4(,%%edi,4), %%ecx\n"
"mov %0+320*240+3*4(,%%edi,4), %%edx\n"
// transpose!
"xchg %%bl, %%ah\n"
// store vga, lo16
"mov %%ax, (%%esi, %%edi)\n"
"shr $16, %%eax\n"
"xchg %%cl, %%al\n"
"xchg %%dl, %%ah\n"
// store vga, hi16
"mov %%ax, 2(%%esi, %%edi)\n"
// store packed0, lo16
"mov %%bx, %1+1*320*240/4(%%edi)\n"
"shr $16, %%ebx\n"
"xchg %%ch, %%bl\n"
"xchg %%dh, %%bh\n"
// store packed0, hi16
"mov %%bx, %1+1*320*240/4+2(%%edi)\n"
// store packed1, lo16
"mov %%cx, %1+2*320*240/4(%%edi)\n"
// store packed2, lo16
"mov %%dx, %1+3*320*240/4(%%edi)\n"
"shr $16, %%edx\n"
"shr $16, %%ecx\n"
"xchg %%dl, %%ch\n"
// store packed1, hi16
"mov %%cx, %1+2*320*240/4+2(%%edi)\n"
// store packed2, hi16
"mov %%dx, %1+3*320*240/4+2(%%edi)\n"
"add $4, %%edi\n"
"jnz 1b\n"
:
: "m"(colors), "m"(packed), "m"(vga)
: "cc", "%eax", "%ebx" ,"%ecx", "%edx", "%esi", "%edi"
);
}
|
|
|
Návrat nahoru |
|
|
|