Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*******************************************************************************
- *
- * TEST XLAT
- * 2015 slawek
- *
- * Test sprawdzający które rozwiązanie jest najszybsze: instrukcja switch,
- * wyszukiwanie wartości w tablicy, operacje na bitach czy może użycie XLAT?
- *
- *******************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <time.h>
- #define BOOL int
- #define TRUE 1
- #define FALSE 0
- static double cpuclock = 2.0E9;
- #define N 100000000
- static uint8_t data [N];
- static uint8_t buffer[N];
- static uint8_t sample[N];
- uint8_t* test_switch_dumb (uint8_t* buffer, uint32_t size);
- uint8_t* test_switch_smart(uint8_t* buffer, uint32_t size);
- uint8_t* test_lookup (uint8_t* buffer, uint32_t size);
- uint8_t* test_bits (uint8_t* buffer, uint32_t size);
- uint8_t* test_xlat (uint8_t* buffer, uint32_t size);
- uint8_t* test_xlat_alt (uint8_t* buffer, uint32_t size);
- #define TEST(FN,SETUP) test(#FN,FN,SETUP)
- BOOL test(char* name, uint8_t* (*fn)(uint8_t*, uint32_t), BOOL setup)
- {
- uint32_t i;
- clock_t t1,t2;
- BOOL result = TRUE;
- if ( setup )
- for ( i = 0; i < N; i++ )
- data[i] = rand() % 8;
- for ( i = 0; i < N; i++ )
- buffer[i] = data[i];
- t1 = clock();
- fn(buffer,N);
- t2 = clock();
- if ( setup )
- for ( i = 0; i < N; i++ )
- sample[i] = buffer[i];
- for ( i = 0; i < N; i++ )
- if ( buffer[i] != sample[i] )
- {
- result = FALSE;
- break;
- }
- printf("%-20s : %10.2lf clk : %-10s\n", name, (t2-t1)/(double)CLOCKS_PER_SEC/(double)N*cpuclock, result ? "pass" : "fail");
- return result;
- }
- /*
- * "Referencyjna" implementacja operacji
- */
- uint8_t* test_switch_dumb(uint8_t* buffer, uint32_t size)
- {
- uint32_t i;
- for ( i = 0; i < size; i++ )
- {
- switch(buffer[i])
- {
- case 2:
- case 3:
- buffer[i] = buffer[i] + 2;
- break;
- case 4:
- case 5:
- buffer[i] = buffer[i] - 2;
- break;
- }
- }
- return buffer;
- }
- /*
- * Implementacja za pomocą switch oraz różnych trików.
- */
- uint8_t* test_switch_smart(uint8_t* buffer, uint32_t size)
- {
- uint8_t* p = buffer;
- while(size--)
- {
- switch(*p)
- {
- case 2:
- case 3:
- *p += 2;
- break;
- case 4:
- case 5:
- *p -= 2;
- break;
- }
- p++;
- }
- return buffer;
- }
- /*
- * Implementacja "na tablicy", ale z poziomu C.
- */
- uint8_t* test_lookup(uint8_t* buffer, uint32_t size)
- {
- const uint8_t mask = 0x07;
- const uint8_t table[] = { 0,1,4,5,2,3,6,7 };
- uint8_t* p = buffer;
- while(size--)
- {
- *p = table[*p & mask];
- p++;
- }
- return buffer;
- }
- /*
- * Bitów męczenie. BTW, wpisanie stałej packed jako liczby stwarza problem
- * z endian'ami.
- */
- uint8_t* test_bits(uint8_t* buffer, uint32_t size)
- {
- int j = 0;
- uint8_t* p = buffer;
- const uint8_t mask1 = 0x7;
- const uint32_t mask2 = 0xF;
- const uint32_t packed = (0UL << 0) | (1UL << 4) | (4UL << 8) | (5UL << 12)
- | (2UL << 16) | (3UL << 20) | (6UL << 24) | (7UL << 28);
- while(size--)
- {
- *p = (packed >> ((*p & mask1) << 2)) & mask2;
- p++;
- }
- return buffer;
- }
- /*
- * Bitów męczenie, przesunięcie o 3
- */
- uint8_t* test_bits_alt(uint8_t* buffer, uint32_t size)
- {
- int j = 0;
- uint8_t* p = buffer;
- const uint32_t mask = 0x7;
- const uint32_t packed = (0UL << 0) | (1UL << 3) | (4UL << 6) | (5UL << 9)
- | (2UL << 12) | (3UL << 15) | (6UL << 18) | (7UL << 21);
- while(size--)
- {
- *p = (packed >> (*p * 3)) & mask;
- p++;
- }
- return buffer;
- }
- int main(void)
- {
- printf("CPU clock [Hz] : ");
- scanf ("%lf", &cpuclock);
- srand((unsigned)time(NULL));
- TEST(test_switch_dumb, TRUE );
- TEST(test_switch_smart, FALSE);
- TEST(test_bits, FALSE);
- TEST(test_bits_alt, FALSE);
- TEST(test_lookup, FALSE);
- TEST(test_xlat, FALSE);
- TEST(test_xlat_alt, FALSE);
- printf("\n");
- system("pause");
- return 0;
- }
- *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
- ;===============================================================================
- ;
- ; T E S T X L A T
- ; plik lookup.asm
- ; 2015 slawek
- .586
- .model flat, C
- public C test_xlat
- public C test_xlat_alt
- .code
- ;-------------------------------------------------------------------------------
- ; uint8_t* test_xlat(uint8_t* buffer, uint32_t buffer_size);
- ;
- ;
- ; Moze zastapic fragment programu w C (poniżej celowo nie uzyto +=, kroczących
- ; wskaznikow itp. rozwiazan jakie mozna zastosowac w jezyku C/C++)
- ;
- ; uint8_t* test_xlat(uint8_t* buffer, uint32_t bufor_size)
- ; {
- ; uint8_t i;
- ;
- ; for ( i = 0; i < size; i++ )
- ; {
- ; switch(buffer[i])
- ; {
- ; case 2:
- ; case 3:
- ; buffer[i] = buffer[i] + 2;
- ; break;
- ; case 4:
- ; case 5:
- ; buffer[i] = buffer[i] - 2;
- ; break;
- ; }
- ; }
- ; return buffer;
- ; }
- ;
- ;
- test_xlat proc uses ebx ecx esi edi buffer:ptr byte, buffer_size:dword
- mov ecx,buffer_size ; zaladowanie licznika petli
- test ecx,ecx ; sprawdzenie czy licznik petli jest niezerowy
- jz L2; ; jezeli size == 0 to pomin wszystko, nic nie rob
- lea ebx,table ; zaladuj do bx adres tablicy look-up
- mov esi,buffer ; zaladuj do ds:si wskaznik na buffer
- mov edi,buffer ; zaladuj do es:di wskaznik na buffer
- cld ; ustalenie df = 0, czyli si i di beda inkrementowane
- L1:
- lodsb ; zaladuj akumulator wartoscia
- and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
- ; (moze byc ew. usuniete dla zwiekszenia predkosci)
- xlat table ; dokonaj translacji
- stosb ; zapisz rezultat z powrotem
- loop L1 ; zapetlenie sterowane przez ecx
- L2:
- mov eax,buffer ; funkcja zwraca wskaznik do bufora, ulatwi to uzycie
- ret ; instrukcja powrotu jako taka
- test_xlat endp
- ;-------------------------------------------------------------------------------
- ; uint8_t* test_xlat_alt(uint8_t* buffer, uint32_t buffer_size);
- ;
- ;
- ; Rozwiazanie, inna implementacja niż test_xlat, ale takze uzywajaca XLAT.
- ;
- ; Moze zastapic fragment programu w C (poniżej celowo nie uzyto +=, kroczących
- ; wskaznikow itp. rozwiazan jakie mozna zastosowac w jezyku C/C++).
- ;
- ; uint8_t* test_xlat(uint8_t* buffer, uint32_t bufor_size)
- ; {
- ; uint8_t i;
- ;
- ; for ( i = 0; i < size; i++ )
- ; {
- ; switch(buffer[i])
- ; {
- ; case 2:
- ; case 3:
- ; buffer[i] = buffer[i] + 2;
- ; break;
- ; case 4:
- ; case 5:
- ; buffer[i] = buffer[i] - 2;
- ; break;
- ; }
- ; }
- ; return buffer;
- ; }
- ;
- ;
- test_xlat_alt proc uses ebx edx ecx buffer:ptr byte, buffer_size:dword
- mov ecx,buffer_size ; zaladowanie licznika petli
- test ecx,ecx ; sprawdzenie czy licznik petli jest niezerowy
- jz L2; ; jezeli size == 0 to pomin wszystko, nic nie rob
- lea ebx,table ; zaladuj do bx adres tablicy look-up
- mov edx,buffer ; zaladuj wskaznik na buffer
- L1:
- mov al,[edx][ecx] ; zaladuj akumulator wartoscia
- and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
- ; (moze byc ew. usuniete dla zwiekszenia predkosci)
- xlat table ; dokonaj translacji
- mov [edx][ecx],al ; zapisz rezultat z powrotem
- loop L1 ; zapetlenie sterowane przez ecx
- mov al,[edx] ; zaladuj akumulator wartoscia
- and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
- ; (moze byc ew. usuniete dla zwiekszenia predkosci)
- xlat table ; dokonaj translacji
- mov [edx],al ; zapisz rezultat z powrotem
- L2:
- mov eax,buffer ; funkcja zwraca wskaznik do bufora, ulatwi to uzycie
- ret ; instrukcja powrotu jako taka
- test_xlat_alt endp
- .data
- ;-------------------------------------------------------------------------------
- ; Dane, tj. tablica ze slownikiem potrzebnym dla xlat. Tablica moze byc krotsza
- ; niz 256 bajtow, wazne jest tylko aby xlat nie probowalo w czasie swego dziala-
- ; nia siegnac poza te tablice. BTW, mozna tego rodzaju tablice przekazywac lub
- ; modyfikowac z zewnatrz, ale tym razem nie bylo to porzebne.
- table db 0,1,4,5,2,3,6,7
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement