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.

512 lines
12 KiB

  1. ;
  2. ; DV.ASM
  3. ;
  4. ; jforbes
  5. ;
  6. TITLE DV.ASM
  7. .386P
  8. .model FLAT
  9. _TEXT SEGMENT
  10. INCLUDE offsets.i
  11. EXTRN _MP_POS_minus2:DWORD
  12. EXTRN _dec_extra_bits:BYTE
  13. local_32_minus_extra_bits:
  14. DB 32,32,32,32,31,31,30,30
  15. DB 29,29,28,28,27,27,26,26
  16. DB 25,25,24,24,23,23,22,22
  17. DB 21,21,20,20,19,19,18,18
  18. DB 17,17,16,16,15,15,15,15
  19. DB 15,15,15,15,15,15,15,15
  20. DB 15,15,15
  21. PUBLIC _fast_decode_verbatim_block
  22. ;
  23. ; NOTES:
  24. ;
  25. ; last_offset uses 12 bytes; 4 for each of the 3 repeated offsets
  26. ;
  27. $bitbuf=0
  28. $bufposend=4
  29. $context=8
  30. $mem_window=12
  31. $last_offset=16
  32. $bitcount=28
  33. $stackvars=32
  34. ;
  35. ; fast_decode_verbatim_block(context, bufpos, amount_to_decode)
  36. ;
  37. _fast_decode_verbatim_block PROC NEAR
  38. ; save registers
  39. push edx
  40. push ecx
  41. push ebx
  42. push edi
  43. push esi
  44. push ebp
  45. ; load parameters and initialise
  46. mov edx, [esp + 28] ; context
  47. mov edi, [esp + 32] ; bufpos
  48. mov eax, [esp + 36] ; amount_to_decode
  49. mov esi, [edx + OFF_INPUT_CURPOS] ; input data ptr
  50. add eax, edi ; eax := bufpos_end = bufpos + amt
  51. sub esp, $stackvars ; allocate stack space for variables
  52. ; store variables on stack
  53. mov [esp + $context], edx ; u
  54. mov [esp + $bufposend], eax ; v
  55. mov ecx, [edx + OFF_MEM_WINDOW] ; u
  56. mov eax, [edx + OFF_BITBUF] ; v
  57. mov [esp + $mem_window], ecx ; u
  58. mov [esp + $bitbuf], eax ; v
  59. ; copy repeated offsets onto stack for quicker accessing (<128 byte offset)
  60. mov ecx, [edx + OFF_LAST_MATCHPOS_OFFSET] ; u
  61. mov ebx, [edx + OFF_LAST_MATCHPOS_OFFSET + 4] ; v
  62. mov eax, [edx + OFF_LAST_MATCHPOS_OFFSET + 8] ; u
  63. mov [esp + $last_offset], ecx ; v
  64. mov [esp + $last_offset + 4], ebx ; u
  65. mov [esp + $last_offset + 8], eax ; v
  66. ; store other variables
  67. xor ecx, ecx
  68. mov cl, BYTE PTR [edx + OFF_BITCOUNT]
  69. mov [esp + $bitcount], ecx
  70. mov edx, ecx
  71. ; start
  72. jmp SHORT loop_top
  73. ;
  74. ; end of init
  75. ;
  76. ;
  77. ; Decoder input overflow error!
  78. ;
  79. $fillbuf1:
  80. ; restore stack and return -1
  81. add esp, $stackvars
  82. pop ebp
  83. pop esi
  84. pop edi
  85. pop ebx
  86. pop ecx
  87. pop edx
  88. mov eax, -1
  89. ret 0
  90. ;
  91. ; Handle codes > table bits in length, for main tree
  92. ;
  93. main_tree_long_code:
  94. mov eax, [esp + $bitbuf] ; u
  95. shl eax, MAIN_TREE_TABLE_BITS ; u
  96. ; negation loop
  97. $L19975:
  98. neg ebx ; NP
  99. add ebx, ebx ; u
  100. add eax, eax ; v test MSB of eax
  101. ; ADC takes 3 clocks, which allows it to overshadow the 0F prefix
  102. ; in the next instruction (saving 1 clock)
  103. adc ebx, 0 ; u
  104. ; won't pair
  105. movsx ebx, WORD PTR [ecx + OFF_MAIN_TREE_LEFTRIGHT + ebx*2]
  106. test ebx, ebx ; u
  107. jl SHORT $L19975 ; v
  108. jmp SHORT back_main_tree_long_code
  109. ;
  110. ; Handle codes > table bits in length, for secondary tree
  111. ;
  112. secondary_tree_long_code:
  113. mov ecx, [esp + $bitbuf]
  114. shl ecx, SECONDARY_LEN_TREE_TABLE_BITS
  115. $L19990:
  116. neg ebp
  117. add ebp, ebp
  118. add ecx, ecx
  119. adc ebp, 0
  120. ; won't pair
  121. movsx ebp, WORD PTR [eax + OFF_SECONDARY_TREE_LEFTRIGHT + ebp*2]
  122. test ebp, ebp
  123. jl SHORT $L19990
  124. jmp back_secondary_tree_long_code
  125. ;
  126. ; loop top
  127. ;
  128. loop_top:
  129. ; DECODE_DDMTREE(c);
  130. ; ebx = table[ bitbuf >> (32-MAIN_TREE_TABLE_BITS) ]
  131. mov ecx, [esp + $context] ; u1
  132. mov eax, [esp + $bitbuf] ; v1
  133. shr eax, 32-MAIN_TREE_TABLE_BITS ; u1
  134. mov ebp, DWORD PTR [ecx + OFF_INPUT_ENDPOS] ; v1
  135. loop_top_after_char:
  136. movsx ebx, WORD PTR [ecx + OFF_MAIN_TREE_TABLE + eax*2] ; NP
  137. test ebx, ebx ; u
  138. jl SHORT main_tree_long_code ; v
  139. back_main_tree_long_code:
  140. ; check for end of input
  141. cmp ebp, esi ; u1
  142. jbe SHORT $fillbuf1 ; v1
  143. mov cl, [ebx + ecx + OFF_MAIN_TREE_LEN] ; u1 cl = len[x]
  144. xor eax, eax ; v1
  145. shl DWORD PTR [esp + $bitbuf], cl ; NP bitbuf <<= len
  146. sub dl, cl ; u1 bitcount -= len
  147. jg SHORT bitcount_gt_0 ; v1
  148. ; otherwise fill buffer
  149. mov al, [esi] ; u1
  150. mov cl, dl ; v1
  151. mov ah, [esi+1] ; u1
  152. xor cl, -1 ; v1
  153. add esi, 2 ; u1
  154. inc cl ; v1
  155. shl eax, cl ; NP
  156. or eax, [esp + $bitbuf] ; u1
  157. add dl, 16 ; v1
  158. mov [esp + $bitbuf], eax ; u1
  159. nop ; v1
  160. bitcount_gt_0:
  161. ;
  162. ; is it a match or a character?
  163. ;
  164. sub ebx, 256 ; u1
  165. jns SHORT $L19985 ; v1
  166. ;
  167. ; it's a character
  168. ;
  169. mov ebp, [esp + $mem_window] ; u1 get mem_window ptr
  170. inc edi ; v1 bufpos++
  171. mov eax, [esp + $bitbuf] ; u1 for next iteration
  172. mov ecx, [esp + $context] ; v1 for next iteration
  173. shr eax, 32-MAIN_TREE_TABLE_BITS ; u1 for next iteration
  174. mov [ebp + edi - 1], bl ; u1 store current character
  175. mov ebp, DWORD PTR [ecx + OFF_INPUT_ENDPOS] ; v1 for next iteration
  176. cmp [esp + $bufposend], edi ; u1
  177. ja SHORT loop_top_after_char ; v1
  178. jmp $cleanup
  179. m_is_3:
  180. mov ebx, 1 ; == _MP_POS_minus2[3*4]
  181. jmp skipover
  182. m_not_zero:
  183. cmp bl, 3 ; u1
  184. je SHORT m_is_3 ; v1
  185. mov eax, [esp + $last_offset] ; u1 eax = t = last[0]
  186. mov ecx, [esp + $last_offset + ebx*4] ; v1 ecx = last[m]
  187. mov [esp + $last_offset], ecx ; u1 last[0] = last[m]
  188. mov [esp + $last_offset + ebx*4], eax ; v1 last[m] = t
  189. mov ebx, ecx ; u
  190. jmp $L20003 ; too far, won't pair
  191. ;
  192. ; m = 0, 1, 2, 3
  193. ;
  194. m_is_0123:
  195. test ebx, ebx ; u1
  196. jnz SHORT m_not_zero ; v1
  197. ; m == 0
  198. mov ebx, [esp + $last_offset] ;
  199. jmp $L20003 ; NP
  200. $L19985:
  201. mov ebp, ebx ; u
  202. mov eax, [esp + $context] ; v
  203. shr ebx, 3 ; u
  204. and ebp, 7 ; v
  205. cmp ebp, 7 ; u
  206. jne SHORT $L19987 ; v
  207. mov ecx, [esp + $bitbuf] ; u
  208. shr ecx, 32-SECONDARY_LEN_TREE_TABLE_BITS ; u
  209. movsx ebp, WORD PTR [eax + OFF_SECONDARY_TREE_TABLE + ecx*2] ; NP
  210. test ebp, ebp ; u1
  211. jnge secondary_tree_long_code ; v1
  212. back_secondary_tree_long_code:
  213. mov cl, BYTE PTR [eax + OFF_SECONDARY_TREE_LEN + ebp] ; u1
  214. add ebp, 7 ; v1
  215. shl DWORD PTR [esp + $bitbuf], cl ; NP bitbuf <<= len
  216. ; if (bitcount > 0) we're ok, otherwise fill buffer
  217. sub dl, cl ; u1 bitcount -= len
  218. jg SHORT $L19987 ; v1
  219. xor eax, eax ; u1
  220. mov cl, dl ; v1
  221. ; NEG does not pair, so we replace it with XOR CL,-1 ; INC CL
  222. mov al, [esi] ; u1
  223. xor cl, -1 ; v1
  224. mov ah, [esi+1] ; u1
  225. inc cl ; v1
  226. shl eax, cl ; NP
  227. or eax, [esp + $bitbuf] ; u2
  228. add dl, 16 ; v1
  229. add esi, 2 ; u1
  230. mov [esp + $bitbuf], eax ; v1
  231. $L19987:
  232. ; if m == 3 then extra_bits == 0, and shifts don't work
  233. ; with a count of zero
  234. xor eax, eax ; u1
  235. cmp bl, 3 ; v1
  236. mov al, bl ; u1
  237. jle SHORT m_is_0123 ; v1
  238. mov cl, BYTE PTR local_32_minus_extra_bits [eax] ; u1
  239. mov ebx, [esp + $bitbuf] ; v1
  240. shr ebx, cl ; NP
  241. add ebx, _MP_POS_minus2[eax*4] ; u2
  242. mov cl, _dec_extra_bits [eax] ; v1
  243. shl DWORD PTR [esp + $bitbuf], cl ; NP
  244. ; now we can trash eax (m)
  245. sub dl, cl ; u1
  246. jg SHORT preskipover ; v1
  247. ; otherwise fill buffer
  248. ; no need to xor eax, eax since everything but the low order
  249. ; byte is already zero
  250. mov al, [esi] ; u1
  251. mov cl, dl ; v1
  252. mov ah, [esi+1] ; u1
  253. xor cl, -1 ; v1
  254. add esi, 2 ; u1
  255. inc cl ; v1
  256. shl eax, cl ; NP
  257. or eax, [esp + $bitbuf] ; u2
  258. add dl, 16 ; v1
  259. ; remember that this can execute twice, if we grab 17 bits
  260. mov [esp + $bitbuf], eax ; u1
  261. jg SHORT preskipover ; v1
  262. ;
  263. ; Second iteration
  264. ;
  265. xor eax, eax ; u1
  266. mov cl, dl ; v1
  267. mov al, [esi] ; u1
  268. xor cl, -1 ; v1
  269. mov ah, [esi+1] ; u1
  270. inc cl ; v1
  271. shl eax, cl ; NP
  272. or eax, [esp + $bitbuf] ; u2
  273. add dl, 16 ; v1
  274. mov [esp + $bitbuf], eax ; u1
  275. add esi, 2 ; v1
  276. preskipover:
  277. skipover:
  278. mov eax, [esp + $last_offset] ; u EAX = R0
  279. mov ecx, [esp + $last_offset + 4] ; v ECX = R1
  280. mov [esp + $last_offset + 4], eax ; u R1 := R0
  281. mov [esp + $last_offset + 8], ecx ; v R2 := R1
  282. mov [esp + $last_offset], ebx ; u R0 := matchpos
  283. $L20003:
  284. ;
  285. ; eax = dec_mem_window
  286. ; ebx = matchpos
  287. ; edi = bufpos
  288. ; ebp = matchlen (ebp=0 means "ML2", ebp=1 means "ML3", ...)
  289. ;
  290. mov ecx, edi ; u1 ecx = bufpos
  291. mov eax, [esp + $context] ; v1 eax = context ptr
  292. inc edi ; u1 bufpos++ for first character
  293. sub ecx, ebx ; v1 ecx := bufpos - matchpos
  294. and ecx, [eax + OFF_WINDOW_MASK] ; u1 ecx &= window_mask
  295. mov eax, [eax + OFF_MEM_WINDOW] ; v1 eax = mem_window
  296. mov bl, [eax + ecx] ; u1 AGI bl = window[src]
  297. inc ecx ; v1 for next iteration
  298. mov [eax + edi - 1], bl ; u store in window[dst]
  299. nop ; v
  300. ;
  301. ; second and later characters...
  302. ;
  303. ; eax = mem_window edx = bitbuf
  304. ; ebx = BL used for character esi = input_pos
  305. ; ecx = bufpos - matchpos
  306. ; ebp = matchlen count
  307. ; edi = bufpos
  308. ;
  309. copy_loop:
  310. inc edi ; u1
  311. mov bl, [eax + ecx] ; v1 bl = dec_window[(bp-mp)&mask]
  312. inc ecx ; u1
  313. dec ebp ; v1
  314. mov [eax + edi - 1], bl ; u1 dec_window[bufpos] = bl
  315. jge SHORT copy_loop ; v1
  316. cmp [esp + $bufposend], edi ; u1
  317. ja loop_top ; NP
  318. ; fall through
  319. $cleanup:
  320. mov ebx, DWORD PTR [esp + $context]
  321. xor eax, eax
  322. cmp edi, [esp + $bufposend]
  323. je SHORT successful
  324. mov eax, -1 ; failure
  325. successful:
  326. and edi, [ebx + OFF_WINDOW_MASK]
  327. mov [ebx + OFF_BITCOUNT], dl
  328. mov [ebx + OFF_BUFPOS], edi
  329. mov [ebx + OFF_INPUT_CURPOS], esi
  330. mov edi, [esp + $bitbuf]
  331. ; copy repeated offsets into context structure
  332. mov ecx, [esp + $last_offset]
  333. mov ebp, [esp + $last_offset + 4]
  334. mov esi, [esp + $last_offset + 8]
  335. mov [ebx + OFF_LAST_MATCHPOS_OFFSET], ecx
  336. mov [ebx + OFF_LAST_MATCHPOS_OFFSET+4], ebp
  337. mov [ebx + OFF_LAST_MATCHPOS_OFFSET+8], esi
  338. mov [ebx + OFF_BITBUF], edi
  339. ; restore stack
  340. add esp, $stackvars
  341. pop ebp
  342. pop esi
  343. pop edi
  344. pop ebx
  345. pop ecx
  346. pop edx
  347. ret 0
  348. _fast_decode_verbatim_block ENDP
  349. _TEXT ENDS
  350. END