Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

519 lines
9.8 KiB

  1. ;
  2. ; tableasm.asm
  3. ;
  4. ; Assembly version of make_table()
  5. ;
  6. ; jforbes 07/20/96
  7. ;
  8. ; Note, this is not optimised for the Pentium at all; very few
  9. ; instructions will execute two at a time.
  10. ;
  11. TITLE TABLEASM.ASM
  12. .386P
  13. .model FLAT
  14. PUBLIC _make_table
  15. ; COMDAT @_make_table
  16. _TEXT SEGMENT
  17. $start = 0
  18. $weight = $start + 72
  19. $count = $weight + 72
  20. $nchar = $count + 72
  21. $bitlen = $nchar + 4
  22. $ch = $bitlen + 4
  23. $leftright = $ch + 4
  24. $avail = $leftright + 4
  25. $k = $avail + 4
  26. $table = $k + 4
  27. $tablebits = $table + 4
  28. $jutbits = $tablebits + 4
  29. $context = $jutbits + 4
  30. $last = $context + 4
  31. _make_table PROC NEAR ; COMDAT
  32. ;
  33. ;void make_table(
  34. ; t_decoder_context *context,
  35. ; USHORT nchar,
  36. ; UBYTE *bitlen,
  37. ; USHORT tablebits,
  38. ; short *table,
  39. ; short *leftright)
  40. ; count [esp+72+68]
  41. ; weight [esp+72]
  42. ; start [esp]
  43. ; 6 regs * 4 = 24 bytes
  44. push ebx
  45. push ecx
  46. push edx
  47. push ebp
  48. push esi
  49. push edi
  50. sub esp, $last
  51. ; how to access the parameters off the stack
  52. ; skip over 24 bytes of pushed registers, and $last local
  53. ; variables, and the 4 byte return address.
  54. $parms = $last+28
  55. mov eax, [esp + $parms + 4]
  56. and eax, 65535
  57. mov [esp + $nchar], eax
  58. mov eax, [esp + $parms]
  59. mov [esp + $context], eax
  60. mov eax, [esp + $parms + 8]
  61. mov [esp + $bitlen], eax
  62. mov eax, [esp + $parms + 12]
  63. and eax, 255
  64. mov [esp + $tablebits], eax
  65. mov eax, [esp + $parms + 16]
  66. mov [esp + $table], eax
  67. mov eax, [esp + $parms + 20]
  68. mov [esp + $leftright], eax
  69. ; for (i = 1; i <= 16; i++)
  70. ; count[i] = 0;
  71. ; clear 64 bytes starting at &count[1]
  72. xor eax, eax
  73. lea edi, [esp + $count + 4]
  74. mov ecx, 16
  75. rep stosd
  76. ; for (i = 0; i < nchar; i++)
  77. ; count[bitlen[i]]++;
  78. ; Do it in reverse
  79. mov ecx, [esp + $nchar] ; u
  80. mov esi, [esp + $bitlen] ; v
  81. xor ebx, ebx ; u
  82. dec ecx ; v ecx = i
  83. loop1:
  84. mov bl, [esi + ecx] ; bl = bitlen[i]
  85. inc DWORD PTR [esp + $count + ebx*4] ; NP
  86. dec ecx ; u
  87. jge SHORT loop1 ; v
  88. ; start[1] = 0;
  89. ;
  90. ; for (i = 1; i <= 16; i++)
  91. ; start[i + 1] = start[i] + (count[i] << (16 - i));
  92. ;
  93. lea ebp, [esp + $start + 4] ; u
  94. lea esi, [esp + $count + 4] ; v
  95. xor edx, edx ; u edx = start[i]
  96. mov ecx, 15 ; v ecx = 16 - i
  97. mov [ebp], edx ; u start[1] = 0
  98. nop ; v
  99. loop2:
  100. mov eax, [esi] ; u eax = count[i]
  101. add ebp, 4 ; v
  102. shl eax, cl ; u
  103. add esi, 4 ; v
  104. add eax, edx ; u edx = start[i]
  105. ; stall
  106. mov [ebp], eax ; u start[i+1]
  107. mov edx, eax ; v edx <- start[i+1]
  108. dec ecx ; u
  109. jge SHORT loop2 ; v
  110. ; if (start[17] != 65536)
  111. mov edx, [esp + 68 + $start]
  112. cmp edx, 65536
  113. jne not_65536
  114. ; jutbits = 16 - tablebits;
  115. ;
  116. ; for (i = 1; i <= tablebits; i++)
  117. ; {
  118. ; start[i] >>= jutbits;
  119. ; weight[i] = 1 << (tablebits - i);
  120. ; }
  121. mov edx, [esp + $tablebits] ; u edx = tablebits
  122. mov eax, 1 ; v eax = i
  123. lea ecx, [edx - 1] ; u ecx = tablebits - i(=1)
  124. mov ebp, eax ; v ebp = 1
  125. shl ebp, cl ; u ebp = 1 << (tablebits - i)
  126. mov ebx, ecx ; v ebx = tablebits - i(=1)
  127. mov cl, 16 ; upper bits of ecx are zero
  128. sub ecx, edx ; ecx = jutbits = 16 - tablebits
  129. mov [esp + $jutbits], ecx
  130. loop3:
  131. shr DWORD PTR [esp + $start + eax*4], cl ; u start[i] >>= jutbits
  132. mov DWORD PTR [esp + $weight + eax*4], ebp ; v
  133. shr ebp, 1 ; u
  134. inc eax ; v i++
  135. cmp eax, edx ; u
  136. jle SHORT loop3 ; v
  137. ; while (i <= 16)
  138. ; {
  139. ; weight[i] = 1 << (16 - i);
  140. ; i++;
  141. ; }
  142. cmp al, 16 ; u
  143. jg SHORT exit_loop4 ; v
  144. loop4:
  145. mov ecx, 16 ; u
  146. mov ebx, 1 ; v
  147. sub ecx, eax ; u ecx = 16 - i
  148. inc eax ; v WAR ok
  149. shl ebx, cl ; u ebx = 1 << (16 - i)
  150. mov DWORD PTR [esp + $weight + eax*4 - 4], ebx ; v
  151. cmp al, 16 ; u
  152. jle SHORT loop4 ; v
  153. exit_loop4:
  154. ; i = start[tablebits+1] >> jutbits
  155. ; ecx = jutbits
  156. mov ecx, [esp + $jutbits]
  157. ; edx = tablebits
  158. mov edx, [esp + $tablebits]
  159. ; eax = start[tablebits+1]
  160. mov eax, [esp + $start + 4 + edx*4]
  161. ; eax = start[tablebits+1] >> jutbits
  162. shr eax, cl
  163. ; if (i != 65536)
  164. cmp eax, 65536
  165. je SHORT i_is_zero
  166. ;
  167. ; memset(&table[i], 0, sizeof(ushort)*((1 << tablebits)-i);
  168. ;
  169. ; ecx = tablebits
  170. mov ecx, edx
  171. ; edx = 1 << tablebits
  172. mov edx, 1
  173. shl edx, cl
  174. ; edx = (1 << tablebits) - i
  175. sub edx, eax
  176. ; count = (1 << tablebits) - i words
  177. mov ecx, edx
  178. ; dest = edi = &table[i]
  179. mov edi, [esp + $table]
  180. lea edi, [edi + eax*2]
  181. ; value = 0
  182. xor eax, eax
  183. rep stosw
  184. i_is_zero:
  185. ;
  186. ; avail = nchar;
  187. ;
  188. mov eax, [esp + $nchar] ; u
  189. xor edi, edi ; v edi = ch
  190. ;
  191. ; for (ch = 0; ch < nchar; ch++)
  192. ;
  193. mov [esp + $avail], eax ; u
  194. jmp SHORT main_loop ; v
  195. ; for short jump
  196. bad_table2:
  197. xor eax, eax ; return failure
  198. jmp cleanup
  199. main_loop:
  200. ; if ((len = bitlen[ch]) == 0)
  201. ; continue;
  202. ; eax = &bitlen[0]
  203. mov eax, [esp + $bitlen]
  204. ; ebp = len = bitlen[ch]
  205. movzx ebp, BYTE PTR [eax + edi]
  206. ; if (len == 0)
  207. ; continue
  208. test ebp, ebp
  209. jz loop_bottom
  210. ; nextcode = start[len] + weight[len];
  211. ; ebx = start[len]
  212. mov ebx, [esp + $start + ebp*4] ; u
  213. mov ecx, [esp + $tablebits] ; v ecx = tablebits
  214. ; ebx = nextcode = start[len] + weight[len]
  215. mov eax, ebx ; u eax = start[len]
  216. add ebx, [esp + $weight + ebp*4] ; v WAR ok
  217. ; if (len <= tablebits)
  218. cmp ebp, ecx ; u
  219. jg SHORT len_g_tablebits ; v
  220. ; if (nextcode > (1 << tablebits))
  221. ; bad_table();
  222. ; edx = 1 << tablebits
  223. mov edx, 1
  224. shl edx, cl ; u
  225. mov ecx, ebx ; v ecx = nextcode
  226. ; if (nextcode > (1 << tablebits))
  227. cmp ebx, edx ; u
  228. jg SHORT bad_table2 ; v
  229. ; for (i = start[len]; i < nextcode; i++)
  230. ; table[i] = ch;
  231. ; ecx = nextcode - start[len]
  232. sub ecx, eax ; u
  233. add eax, eax ; v WAR ok
  234. ; eax = &table[ start[len] ]
  235. add eax, [esp + $table] ; u
  236. ; start[len] = nextcode (moved up)
  237. mov [esp + $start + ebp*4], ebx ; v
  238. ; For this loop:
  239. ; eax = &table[ start[len] ]
  240. ; edi = ch
  241. ; ecx = nextcode - start[len]
  242. ;
  243. loop6:
  244. mov WORD PTR [eax], di ; table[i] = ch
  245. add eax, 2 ; i++
  246. dec ecx
  247. jnz SHORT loop6
  248. ; ch++
  249. inc edi ; moved up
  250. ; loop bottom
  251. cmp edi, [esp + $nchar]
  252. jl SHORT main_loop
  253. mov eax, 1 ; success
  254. jmp cleanup
  255. ;
  256. ; len > tablebits
  257. ;
  258. ; on entry: eax = start[len]
  259. ; ebx = nextcode
  260. ; ecx = tablebits
  261. ; ebp = len
  262. ;
  263. len_g_tablebits:
  264. mov esi, ebp ; u esi = len
  265. mov edx, eax ; v edx = start[len]
  266. sub esi, ecx ; u esi = len - tablebits
  267. add cl, 16 ; v
  268. ; edx = k << tablebits
  269. ; shift left another 16 because we want to use a DWORD
  270. ; for testing the negative bit
  271. shl edx, cl ; u
  272. mov [esp + $k], eax ; v
  273. ; start[len] = nextcode;
  274. mov [esp + $start + ebp*4], ebx ; u
  275. nop ; v
  276. ; p = &table[k >> jutbits];
  277. mov ecx, [esp + $jutbits] ; u ecx = jutbits
  278. mov ebx, [esp + $k] ; v ebx = k >> jutbits
  279. shr ebx, cl ; u
  280. mov eax, [esp + $table] ; v
  281. lea ebx, [eax + ebx*2] ; u ebx = p = &table[k >> jutbits]
  282. mov ebp, [esp + $avail] ; v ebp = avail
  283. bottom_loop:
  284. ; if (*p == 0)
  285. ; eax = &leftright[0]
  286. mov eax, [esp + $leftright]
  287. ; ecx = *p
  288. movsx ecx, WORD PTR [ebx] ; NP
  289. ; *p == 0 ?
  290. test ecx, ecx ; u
  291. jne SHORT p_not_zero ; v
  292. ; left_right[avail*2] = left_right[avail*2+1] = 0;
  293. ; *p = -avail;
  294. ; avail++;
  295. mov WORD PTR [ebx], bp ; *p = avail
  296. ; sets left and right to zero (remember that ecx == 0)
  297. mov [eax + ebp*4], ecx ; u
  298. inc ebp ; v avail++
  299. ; *p = -avail
  300. neg WORD PTR [ebx]
  301. p_not_zero:
  302. ; if ((signed short) k < 0)
  303. ; p = &right[-(*p)];
  304. ; else
  305. ; p = &left[-(*p)];
  306. ; ecx = -(*p)
  307. movsx ecx, WORD PTR [ebx]
  308. neg ecx
  309. ; ebx = p = &ptr[-(*p)]
  310. lea ebx, [ecx*4 + eax]
  311. ; if (k becomes -ve when we shift out a bit)
  312. add edx, edx
  313. jnc SHORT go_left
  314. ; right
  315. add ebx, 2
  316. go_left:
  317. dec esi ; i--
  318. jnz SHORT bottom_loop
  319. ; *p = ch;
  320. mov WORD PTR [ebx], di
  321. ; store avail
  322. mov [esp + $avail], ebp
  323. loop_bottom:
  324. ; ch++
  325. inc edi
  326. cmp edi, [esp + $nchar]
  327. jl main_loop
  328. mov eax, 1 ; success
  329. cleanup:
  330. add esp, $last
  331. pop edi
  332. pop esi
  333. pop ebp
  334. pop edx
  335. pop ecx
  336. pop ebx
  337. ret 0
  338. not_65536:
  339. test edx, edx
  340. jnz SHORT bad_table
  341. ; memset(table, 0, sizeof(ushort)*(1<<tablebits))
  342. xor eax, eax
  343. mov edi, [esp + $table]
  344. mov edx, 1
  345. mov ecx, [esp + $tablebits]
  346. dec ecx ; subtract 1 because we're doing STOSD
  347. shl edx, cl ; edx := 1 << tablebits
  348. mov ecx, edx ; store in ecx
  349. rep stosd
  350. mov eax, 1 ; success
  351. jmp SHORT cleanup
  352. bad_table:
  353. xor eax, eax ; failure
  354. jmp cleanup
  355. _make_table ENDP
  356. _TEXT ENDS
  357. END