inffasx64.asm
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
源码类别:

通讯编程

开发平台:

Visual C++

  1. ; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
  2. ; version for AMD64 on Windows using Microsoft C compiler
  3. ;
  4. ; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
  5. ; inffasx64.asm is called by inffas8664.c, which contain more info.
  6. ; to compile this file, I use option
  7. ;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
  8. ;   with Microsoft Macro Assembler (x64) for AMD64
  9. ;
  10. ;   ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
  11. ;
  12. ;   (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from 
  13. ;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
  14. ;
  15. .code
  16. inffas8664fnc PROC
  17. ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
  18. ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
  19. ;
  20. ; All registers must be preserved across the call, except for
  21. ;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
  22. mov [rsp-8],rsi
  23. mov [rsp-16],rdi
  24. mov [rsp-24],r12
  25. mov [rsp-32],r13
  26. mov [rsp-40],r14
  27. mov [rsp-48],r15
  28. mov [rsp-56],rbx
  29. mov rax,rcx
  30. mov [rax+8], rbp       ; /* save regs rbp and rsp */
  31. mov [rax], rsp
  32. mov rsp, rax          ; /* make rsp point to &ar */
  33. mov rsi, [rsp+16]      ; /* rsi  = in */
  34. mov rdi, [rsp+32]      ; /* rdi  = out */
  35. mov r9, [rsp+24]       ; /* r9   = last */
  36. mov r10, [rsp+48]      ; /* r10  = end */
  37. mov rbp, [rsp+64]      ; /* rbp  = lcode */
  38. mov r11, [rsp+72]      ; /* r11  = dcode */
  39. mov rdx, [rsp+80]      ; /* rdx  = hold */
  40. mov ebx, [rsp+88]      ; /* ebx  = bits */
  41. mov r12d, [rsp+100]    ; /* r12d = lmask */
  42. mov r13d, [rsp+104]    ; /* r13d = dmask */
  43.                                           ; /* r14d = len */
  44.                                           ; /* r15d = dist */
  45. cld
  46. cmp r10, rdi
  47. je L_one_time           ; /* if only one decode left */
  48. cmp r9, rsi
  49.     jne L_do_loop
  50. L_one_time:
  51. mov r8, r12           ; /* r8 = lmask */
  52. cmp bl, 32
  53. ja L_get_length_code_one_time
  54. lodsd                         ; /* eax = *(uint *)in++ */
  55. mov cl, bl            ; /* cl = bits, needs it for shifting */
  56. add bl, 32             ; /* bits += 32 */
  57. shl rax, cl
  58. or rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
  59. jmp L_get_length_code_one_time
  60. ALIGN 4
  61. L_while_test:
  62. cmp r10, rdi
  63. jbe L_break_loop
  64. cmp r9, rsi
  65. jbe L_break_loop
  66. L_do_loop:
  67. mov r8, r12           ; /* r8 = lmask */
  68. cmp bl, 32
  69. ja L_get_length_code    ; /* if (32 < bits) */
  70. lodsd                         ; /* eax = *(uint *)in++ */
  71. mov cl, bl            ; /* cl = bits, needs it for shifting */
  72. add bl, 32             ; /* bits += 32 */
  73. shl rax, cl
  74. or rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
  75. L_get_length_code:
  76. and r8, rdx            ; /* r8 &= hold */
  77. mov eax, [rbp+r8*4]  ; /* eax = lcode[hold & lmask] */
  78. mov cl, ah            ; /* cl = this.bits */
  79. sub bl, ah            ; /* bits -= this.bits */
  80. shr rdx, cl           ; /* hold >>= this.bits */
  81. test al, al
  82. jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
  83. mov r8, r12            ; /* r8 = lmask */
  84. shr eax, 16            ; /* output this.val char */
  85. stosb
  86. L_get_length_code_one_time:
  87. and r8, rdx            ; /* r8 &= hold */
  88. mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
  89. L_dolen:
  90. mov cl, ah            ; /* cl = this.bits */
  91. sub bl, ah            ; /* bits -= this.bits */
  92. shr rdx, cl           ; /* hold >>= this.bits */
  93. test al, al
  94. jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
  95. shr eax, 16            ; /* output this.val char */
  96. stosb
  97. jmp L_while_test
  98. ALIGN 4
  99. L_test_for_length_base:
  100. mov r14d, eax         ; /* len = this */
  101. shr r14d, 16           ; /* len = this.val */
  102. mov cl, al
  103. test al, 16
  104. jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
  105. and cl, 15             ; /* op &= 15 */
  106. jz L_decode_distance    ; /* if (!op) */
  107. L_add_bits_to_len:
  108. sub bl, cl
  109. xor eax, eax
  110. inc eax
  111. shl eax, cl
  112. dec eax
  113. and eax, edx          ; /* eax &= hold */
  114. shr rdx, cl
  115. add r14d, eax         ; /* len += hold & mask[op] */
  116. L_decode_distance:
  117. mov r8, r13           ; /* r8 = dmask */
  118. cmp bl, 32
  119. ja L_get_distance_code  ; /* if (32 < bits) */
  120. lodsd                         ; /* eax = *(uint *)in++ */
  121. mov cl, bl            ; /* cl = bits, needs it for shifting */
  122. add bl, 32             ; /* bits += 32 */
  123. shl rax, cl
  124. or rdx, rax          ; /* hold |= *((uint *)in)++ << bits */
  125. L_get_distance_code:
  126. and r8, rdx           ; /* r8 &= hold */
  127. mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */
  128. L_dodist:
  129. mov r15d, eax         ; /* dist = this */
  130. shr r15d, 16           ; /* dist = this.val */
  131. mov cl, ah
  132. sub bl, ah            ; /* bits -= this.bits */
  133. shr rdx, cl           ; /* hold >>= this.bits */
  134. mov cl, al            ; /* cl = this.op */
  135. test al, 16             ; /* if ((op & 16) == 0) */
  136. jz L_test_for_second_level_dist
  137. and cl, 15             ; /* op &= 15 */
  138. jz L_check_dist_one
  139. L_add_bits_to_dist:
  140. sub bl, cl
  141. xor eax, eax
  142. inc eax
  143. shl eax, cl
  144. dec eax                 ; /* (1 << op) - 1 */
  145. and eax, edx          ; /* eax &= hold */
  146. shr rdx, cl
  147. add r15d, eax         ; /* dist += hold & ((1 << op) - 1) */
  148. L_check_window:
  149. mov r8, rsi           ; /* save in so from can use it's reg */
  150. mov rax, rdi
  151. sub rax, [rsp+40]      ; /* nbytes = out - beg */
  152. cmp eax, r15d
  153. jb L_clip_window        ; /* if (dist > nbytes) 4.2% */
  154. mov ecx, r14d         ; /* ecx = len */
  155. mov rsi, rdi
  156. sub rsi, r15          ; /* from = out - dist */
  157. sar ecx, 1
  158. jnc L_copy_two           ; /* if len % 2 == 0 */
  159. rep     movsw
  160. mov al, [rsi]
  161. mov [rdi], al
  162. inc rdi
  163. mov rsi, r8           ; /* move in back to %rsi, toss from */
  164. jmp L_while_test
  165. L_copy_two:
  166. rep     movsw
  167. mov rsi, r8           ; /* move in back to %rsi, toss from */
  168. jmp L_while_test
  169. ALIGN 4
  170. L_check_dist_one:
  171. cmp r15d, 1            ; /* if dist 1, is a memset */
  172. jne L_check_window
  173. cmp [rsp+40], rdi      ; /* if out == beg, outside window */
  174. je L_check_window
  175. mov ecx, r14d         ; /* ecx = len */
  176. mov al, [rdi-1]
  177. mov ah, al
  178. sar ecx, 1
  179. jnc L_set_two
  180. mov [rdi], al
  181. inc rdi
  182. L_set_two:
  183. rep     stosw
  184. jmp L_while_test
  185. ALIGN 4
  186. L_test_for_second_level_length:
  187. test al, 64
  188. jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */
  189. xor eax, eax
  190. inc eax
  191. shl eax, cl
  192. dec eax
  193. and eax, edx         ; /* eax &= hold */
  194. add eax, r14d        ; /* eax += len */
  195. mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
  196. jmp L_dolen
  197. ALIGN 4
  198. L_test_for_second_level_dist:
  199. test al, 64
  200. jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */
  201. xor eax, eax
  202. inc eax
  203. shl eax, cl
  204. dec eax
  205. and eax, edx         ; /* eax &= hold */
  206. add eax, r15d        ; /* eax += dist */
  207. mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
  208. jmp L_dodist
  209. ALIGN 4
  210. L_clip_window:
  211. mov ecx, eax         ; /* ecx = nbytes */
  212. mov eax, [rsp+92]     ; /* eax = wsize, prepare for dist cmp */
  213. neg ecx                ; /* nbytes = -nbytes */
  214. cmp eax, r15d
  215. jb L_invalid_distance_too_far ; /* if (dist > wsize) */
  216. add ecx, r15d         ; /* nbytes = dist - nbytes */
  217. cmp dword ptr [rsp+96], 0
  218. jne L_wrap_around_window ; /* if (write != 0) */
  219. mov rsi, [rsp+56]     ; /* from  = window */
  220. sub eax, ecx         ; /* eax  -= nbytes */
  221. add rsi, rax         ; /* from += wsize - nbytes */
  222. mov eax, r14d        ; /* eax = len */
  223. cmp r14d, ecx
  224. jbe L_do_copy           ; /* if (nbytes >= len) */
  225. sub eax, ecx         ; /* eax -= nbytes */
  226. rep     movsb
  227. mov rsi, rdi
  228. sub rsi, r15         ; /* from = &out[ -dist ] */
  229. jmp L_do_copy
  230. ALIGN 4
  231. L_wrap_around_window:
  232. mov eax, [rsp+96]     ; /* eax = write */
  233. cmp ecx, eax
  234. jbe L_contiguous_in_window ; /* if (write >= nbytes) */
  235. mov esi, [rsp+92]     ; /* from  = wsize */
  236. add rsi, [rsp+56]     ; /* from += window */
  237. add rsi, rax         ; /* from += write */
  238. sub rsi, rcx         ; /* from -= nbytes */
  239. sub ecx, eax         ; /* nbytes -= write */
  240. mov eax, r14d        ; /* eax = len */
  241. cmp eax, ecx
  242. jbe L_do_copy           ; /* if (nbytes >= len) */
  243. sub eax, ecx         ; /* len -= nbytes */
  244. rep     movsb
  245. mov rsi, [rsp+56]     ; /* from = window */
  246. mov ecx, [rsp+96]     ; /* nbytes = write */
  247. cmp eax, ecx
  248. jbe L_do_copy           ; /* if (nbytes >= len) */
  249. sub eax, ecx         ; /* len -= nbytes */
  250. rep     movsb
  251. mov rsi, rdi
  252. sub rsi, r15         ; /* from = out - dist */
  253. jmp L_do_copy
  254. ALIGN 4
  255. L_contiguous_in_window:
  256. mov rsi, [rsp+56]     ; /* rsi = window */
  257. add rsi, rax
  258. sub rsi, rcx         ; /* from += write - nbytes */
  259. mov eax, r14d        ; /* eax = len */
  260. cmp eax, ecx
  261. jbe L_do_copy           ; /* if (nbytes >= len) */
  262. sub eax, ecx         ; /* len -= nbytes */
  263. rep     movsb
  264. mov rsi, rdi
  265. sub rsi, r15         ; /* from = out - dist */
  266. jmp L_do_copy           ; /* if (nbytes >= len) */
  267. ALIGN 4
  268. L_do_copy:
  269. mov ecx, eax         ; /* ecx = len */
  270. rep     movsb
  271. mov rsi, r8          ; /* move in back to %esi, toss from */
  272. jmp L_while_test
  273. L_test_for_end_of_block:
  274. test al, 32
  275. jz L_invalid_literal_length_code
  276. mov dword ptr [rsp+116], 1
  277. jmp L_break_loop_with_status
  278. L_invalid_literal_length_code:
  279. mov dword ptr [rsp+116], 2
  280. jmp L_break_loop_with_status
  281. L_invalid_distance_code:
  282. mov dword ptr [rsp+116], 3
  283. jmp L_break_loop_with_status
  284. L_invalid_distance_too_far:
  285. mov dword ptr [rsp+116], 4
  286. jmp L_break_loop_with_status
  287. L_break_loop:
  288. mov dword ptr [rsp+116], 0
  289. L_break_loop_with_status:
  290. ; /* put in, out, bits, and hold back into ar and pop esp */
  291. mov [rsp+16], rsi     ; /* in */
  292. mov [rsp+32], rdi     ; /* out */
  293. mov [rsp+88], ebx     ; /* bits */
  294. mov [rsp+80], rdx     ; /* hold */
  295. mov rax, [rsp]       ; /* restore rbp and rsp */
  296. mov rbp, [rsp+8]
  297. mov rsp, rax
  298. mov rsi,[rsp-8]
  299. mov rdi,[rsp-16]
  300. mov r12,[rsp-24]
  301. mov r13,[rsp-32]
  302. mov r14,[rsp-40]
  303. mov r15,[rsp-48]
  304. mov rbx,[rsp-56]
  305.     ret 0
  306. ;          :
  307. ;          : "m" (ar)
  308. ;          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
  309. ;            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
  310. ;    );
  311. inffas8664fnc  ENDP
  312. ;_TEXT ENDS
  313. END