Advertisement
Guest User

Untitled

a guest
Mar 29th, 2015
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.47 KB | None | 0 0
  1. /*******************************************************************************
  2. *
  3. * TEST XLAT
  4. * 2015 slawek
  5. *
  6. * Test sprawdzający które rozwiązanie jest najszybsze: instrukcja switch,
  7. * wyszukiwanie wartości w tablicy, operacje na bitach czy może użycie XLAT?
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <stdint.h>
  14. #include <time.h>
  15.  
  16. #define BOOL int
  17. #define TRUE 1
  18. #define FALSE 0
  19.  
  20. static double cpuclock = 2.0E9;
  21.  
  22. #define N 100000000
  23. static uint8_t data [N];
  24. static uint8_t buffer[N];
  25. static uint8_t sample[N];
  26.  
  27. uint8_t* test_switch_dumb (uint8_t* buffer, uint32_t size);
  28. uint8_t* test_switch_smart(uint8_t* buffer, uint32_t size);
  29. uint8_t* test_lookup (uint8_t* buffer, uint32_t size);
  30. uint8_t* test_bits (uint8_t* buffer, uint32_t size);
  31. uint8_t* test_xlat (uint8_t* buffer, uint32_t size);
  32. uint8_t* test_xlat_alt (uint8_t* buffer, uint32_t size);
  33.  
  34.  
  35. #define TEST(FN,SETUP) test(#FN,FN,SETUP)
  36. BOOL test(char* name, uint8_t* (*fn)(uint8_t*, uint32_t), BOOL setup)
  37. {
  38. uint32_t i;
  39. clock_t t1,t2;
  40. BOOL result = TRUE;
  41.  
  42. if ( setup )
  43. for ( i = 0; i < N; i++ )
  44. data[i] = rand() % 8;
  45.  
  46. for ( i = 0; i < N; i++ )
  47. buffer[i] = data[i];
  48.  
  49. t1 = clock();
  50. fn(buffer,N);
  51. t2 = clock();
  52.  
  53. if ( setup )
  54. for ( i = 0; i < N; i++ )
  55. sample[i] = buffer[i];
  56.  
  57. for ( i = 0; i < N; i++ )
  58. if ( buffer[i] != sample[i] )
  59. {
  60. result = FALSE;
  61. break;
  62. }
  63.  
  64. printf("%-20s : %10.2lf clk : %-10s\n", name, (t2-t1)/(double)CLOCKS_PER_SEC/(double)N*cpuclock, result ? "pass" : "fail");
  65. return result;
  66. }
  67.  
  68.  
  69. /*
  70. * "Referencyjna" implementacja operacji
  71. */
  72. uint8_t* test_switch_dumb(uint8_t* buffer, uint32_t size)
  73. {
  74. uint32_t i;
  75.  
  76. for ( i = 0; i < size; i++ )
  77. {
  78. switch(buffer[i])
  79. {
  80. case 2:
  81. case 3:
  82. buffer[i] = buffer[i] + 2;
  83. break;
  84. case 4:
  85. case 5:
  86. buffer[i] = buffer[i] - 2;
  87. break;
  88. }
  89. }
  90. return buffer;
  91. }
  92.  
  93.  
  94. /*
  95. * Implementacja za pomocą switch oraz różnych trików.
  96. */
  97. uint8_t* test_switch_smart(uint8_t* buffer, uint32_t size)
  98. {
  99. uint8_t* p = buffer;
  100.  
  101. while(size--)
  102. {
  103. switch(*p)
  104. {
  105. case 2:
  106. case 3:
  107. *p += 2;
  108. break;
  109. case 4:
  110. case 5:
  111. *p -= 2;
  112. break;
  113. }
  114. p++;
  115. }
  116.  
  117. return buffer;
  118. }
  119.  
  120. /*
  121. * Implementacja "na tablicy", ale z poziomu C.
  122. */
  123.  
  124. uint8_t* test_lookup(uint8_t* buffer, uint32_t size)
  125. {
  126. const uint8_t mask = 0x07;
  127. const uint8_t table[] = { 0,1,4,5,2,3,6,7 };
  128. uint8_t* p = buffer;
  129.  
  130. while(size--)
  131. {
  132. *p = table[*p & mask];
  133. p++;
  134. }
  135.  
  136. return buffer;
  137. }
  138.  
  139. /*
  140. * Bitów męczenie. BTW, wpisanie stałej packed jako liczby stwarza problem
  141. * z endian'ami.
  142. */
  143. uint8_t* test_bits(uint8_t* buffer, uint32_t size)
  144. {
  145. int j = 0;
  146.  
  147. uint8_t* p = buffer;
  148.  
  149. const uint8_t mask1 = 0x7;
  150. const uint32_t mask2 = 0xF;
  151. const uint32_t packed = (0UL << 0) | (1UL << 4) | (4UL << 8) | (5UL << 12)
  152. | (2UL << 16) | (3UL << 20) | (6UL << 24) | (7UL << 28);
  153.  
  154. while(size--)
  155. {
  156. *p = (packed >> ((*p & mask1) << 2)) & mask2;
  157. p++;
  158. }
  159. return buffer;
  160. }
  161.  
  162. /*
  163. * Bitów męczenie, przesunięcie o 3
  164. */
  165. uint8_t* test_bits_alt(uint8_t* buffer, uint32_t size)
  166. {
  167. int j = 0;
  168.  
  169. uint8_t* p = buffer;
  170.  
  171. const uint32_t mask = 0x7;
  172. const uint32_t packed = (0UL << 0) | (1UL << 3) | (4UL << 6) | (5UL << 9)
  173. | (2UL << 12) | (3UL << 15) | (6UL << 18) | (7UL << 21);
  174.  
  175. while(size--)
  176. {
  177. *p = (packed >> (*p * 3)) & mask;
  178. p++;
  179. }
  180. return buffer;
  181. }
  182.  
  183.  
  184. int main(void)
  185. {
  186. printf("CPU clock [Hz] : ");
  187. scanf ("%lf", &cpuclock);
  188.  
  189. srand((unsigned)time(NULL));
  190.  
  191. TEST(test_switch_dumb, TRUE );
  192. TEST(test_switch_smart, FALSE);
  193. TEST(test_bits, FALSE);
  194. TEST(test_bits_alt, FALSE);
  195. TEST(test_lookup, FALSE);
  196. TEST(test_xlat, FALSE);
  197. TEST(test_xlat_alt, FALSE);
  198.  
  199. printf("\n");
  200. system("pause");
  201.  
  202. return 0;
  203. }
  204.  
  205. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
  206.  
  207. ;===============================================================================
  208. ;
  209. ; T E S T X L A T
  210. ; plik lookup.asm
  211. ; 2015 slawek
  212.  
  213. .586
  214. .model flat, C
  215.  
  216. public C test_xlat
  217. public C test_xlat_alt
  218.  
  219. .code
  220.  
  221. ;-------------------------------------------------------------------------------
  222. ; uint8_t* test_xlat(uint8_t* buffer, uint32_t buffer_size);
  223. ;
  224. ;
  225. ; Moze zastapic fragment programu w C (poniżej celowo nie uzyto +=, kroczących
  226. ; wskaznikow itp. rozwiazan jakie mozna zastosowac w jezyku C/C++)
  227. ;
  228. ; uint8_t* test_xlat(uint8_t* buffer, uint32_t bufor_size)
  229. ; {
  230. ; uint8_t i;
  231. ;
  232. ; for ( i = 0; i < size; i++ )
  233. ; {
  234. ; switch(buffer[i])
  235. ; {
  236. ; case 2:
  237. ; case 3:
  238. ; buffer[i] = buffer[i] + 2;
  239. ; break;
  240. ; case 4:
  241. ; case 5:
  242. ; buffer[i] = buffer[i] - 2;
  243. ; break;
  244. ; }
  245. ; }
  246. ; return buffer;
  247. ; }
  248. ;
  249. ;
  250. test_xlat proc uses ebx ecx esi edi buffer:ptr byte, buffer_size:dword
  251.  
  252. mov ecx,buffer_size ; zaladowanie licznika petli
  253. test ecx,ecx ; sprawdzenie czy licznik petli jest niezerowy
  254. jz L2; ; jezeli size == 0 to pomin wszystko, nic nie rob
  255.  
  256. lea ebx,table ; zaladuj do bx adres tablicy look-up
  257. mov esi,buffer ; zaladuj do ds:si wskaznik na buffer
  258. mov edi,buffer ; zaladuj do es:di wskaznik na buffer
  259. cld ; ustalenie df = 0, czyli si i di beda inkrementowane
  260.  
  261. L1:
  262.  
  263. lodsb ; zaladuj akumulator wartoscia
  264. and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
  265. ; (moze byc ew. usuniete dla zwiekszenia predkosci)
  266. xlat table ; dokonaj translacji
  267. stosb ; zapisz rezultat z powrotem
  268.  
  269. loop L1 ; zapetlenie sterowane przez ecx
  270.  
  271. L2:
  272.  
  273. mov eax,buffer ; funkcja zwraca wskaznik do bufora, ulatwi to uzycie
  274. ret ; instrukcja powrotu jako taka
  275.  
  276. test_xlat endp
  277.  
  278.  
  279. ;-------------------------------------------------------------------------------
  280. ; uint8_t* test_xlat_alt(uint8_t* buffer, uint32_t buffer_size);
  281. ;
  282. ;
  283. ; Rozwiazanie, inna implementacja niż test_xlat, ale takze uzywajaca XLAT.
  284. ;
  285. ; Moze zastapic fragment programu w C (poniżej celowo nie uzyto +=, kroczących
  286. ; wskaznikow itp. rozwiazan jakie mozna zastosowac w jezyku C/C++).
  287. ;
  288. ; uint8_t* test_xlat(uint8_t* buffer, uint32_t bufor_size)
  289. ; {
  290. ; uint8_t i;
  291. ;
  292. ; for ( i = 0; i < size; i++ )
  293. ; {
  294. ; switch(buffer[i])
  295. ; {
  296. ; case 2:
  297. ; case 3:
  298. ; buffer[i] = buffer[i] + 2;
  299. ; break;
  300. ; case 4:
  301. ; case 5:
  302. ; buffer[i] = buffer[i] - 2;
  303. ; break;
  304. ; }
  305. ; }
  306. ; return buffer;
  307. ; }
  308. ;
  309. ;
  310. test_xlat_alt proc uses ebx edx ecx buffer:ptr byte, buffer_size:dword
  311.  
  312. mov ecx,buffer_size ; zaladowanie licznika petli
  313. test ecx,ecx ; sprawdzenie czy licznik petli jest niezerowy
  314. jz L2; ; jezeli size == 0 to pomin wszystko, nic nie rob
  315.  
  316. lea ebx,table ; zaladuj do bx adres tablicy look-up
  317. mov edx,buffer ; zaladuj wskaznik na buffer
  318.  
  319. L1:
  320.  
  321. mov al,[edx][ecx] ; zaladuj akumulator wartoscia
  322. and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
  323. ; (moze byc ew. usuniete dla zwiekszenia predkosci)
  324. xlat table ; dokonaj translacji
  325. mov [edx][ecx],al ; zapisz rezultat z powrotem
  326.  
  327. loop L1 ; zapetlenie sterowane przez ecx
  328.  
  329.  
  330. mov al,[edx] ; zaladuj akumulator wartoscia
  331. and al,111B ; na wszelki wypadek ogranicz maksymalna wartosc al
  332. ; (moze byc ew. usuniete dla zwiekszenia predkosci)
  333. xlat table ; dokonaj translacji
  334. mov [edx],al ; zapisz rezultat z powrotem
  335.  
  336. L2:
  337.  
  338. mov eax,buffer ; funkcja zwraca wskaznik do bufora, ulatwi to uzycie
  339. ret ; instrukcja powrotu jako taka
  340.  
  341. test_xlat_alt endp
  342.  
  343.  
  344.  
  345.  
  346. .data
  347.  
  348. ;-------------------------------------------------------------------------------
  349. ; Dane, tj. tablica ze slownikiem potrzebnym dla xlat. Tablica moze byc krotsza
  350. ; niz 256 bajtow, wazne jest tylko aby xlat nie probowalo w czasie swego dziala-
  351. ; nia siegnac poza te tablice. BTW, mozna tego rodzaju tablice przekazywac lub
  352. ; modyfikowac z zewnatrz, ale tym razem nie bylo to porzebne.
  353.  
  354. table db 0,1,4,5,2,3,6,7
  355.  
  356. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement