blur_asm.asm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. default rel global _blur_asm
  2. global blur_asm
  3. extern convulcion_matrix
  4. ; Alias para no volverme loco con los registros
  5. %define src rdi
  6. %define dst rsi
  7. %define cols rdx
  8. %define filas r14
  9. %define sigma xmm0
  10. %define radius r8
  11. %define cont_c r9
  12. %define matriz r10
  13. %define filas_faltan r11
  14. %define col_faltan r12
  15. %define basura r13
  16. %define tmp_src rbp
  17. ; Algunos defines ultiles
  18. %define PIXEL_SIZE 4
  19. ; Mascaras y esas cosas
  20. section .data
  21. section .text
  22. ;void blur_asm (
  23. ;unsigned char *src,
  24. ;unsigned char *dst,
  25. ;int filas,
  26. ;int cols,
  27. ;float sigma,
  28. ;int radius)
  29. _blur_asm:
  30. blur_asm:
  31. push rbp
  32. mov rbp, rsp ; Stack frame
  33. push r9
  34. push r10
  35. push r11
  36. push r12
  37. push r13
  38. push r14
  39. push r15
  40. .init:
  41. mov filas, rcx ;filas
  42. push src
  43. push dst
  44. push cols
  45. push filas
  46. push radius
  47. sub rsp, 16
  48. movdqu [rsp],xmm0
  49. mov rdi, radius
  50. call convulcion_matrix
  51. mov matriz, rax
  52. mov r15, matriz ;copio puntero inicial
  53. movdqu xmm0, [rsp]
  54. add rsp, 16
  55. pop radius
  56. pop filas
  57. pop cols
  58. pop dst
  59. pop src
  60. ;mov r14,rcx ;guardo rcx para loop
  61. mov r9, rdx ;salvo rdx por los mul
  62. mov rax, PIXEL_SIZE
  63. mul cols
  64. mul radius
  65. ; rax:=cols*pix_size*radius => cuantas filas debo saltear
  66. ;add src, rax
  67. add dst, rax ; Avanzo "radius" filas (col*pix_size*radius)
  68. sub filas, radius ;acomodo filas para ignorar los bordes
  69. sub filas, radius ;acomodo filas para ignorar los bordes
  70. mov cols, r9 ;recupero cols por el mul
  71. sub cols, radius ;resto radius columnas
  72. sub cols, radius ;resto radius columnas
  73. mov rax, PIXEL_SIZE
  74. mul cols
  75. mov cols, rax ;cols:=cols*pix_size
  76. .iniciarFila:
  77. ;lea src, [src+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  78. lea dst, [dst+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  79. xor cont_c,cont_c
  80. .loop:
  81. cmp cols, cont_c ; Comparo tamaño con el contador
  82. je .finFila ; Si ya recorri la imagen voy al final
  83. mov filas_faltan, radius
  84. add filas_faltan, radius
  85. inc filas_faltan ; 2r+1 filas
  86. mov tmp_src, src
  87. pxor xmm10,xmm10
  88. mov matriz, r15
  89. .loopInterno:
  90. mov col_faltan, radius
  91. add col_faltan, radius
  92. inc col_faltan ; 2r+1 columnas
  93. mov basura, rdx
  94. mov rax,PIXEL_SIZE
  95. mul col_faltan ;destruyo rdx
  96. mov col_faltan, rax
  97. mov rdx, basura ;salvo rdx
  98. .loopFila:
  99. ;levanto 4px
  100. movdqu xmm2, [src] ; Cargo 4 pix de la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  101. cmp col_faltan, 3
  102. jg .normal ;no qiuero shiftear
  103. je .tres ;quiero borrar 3 elem
  104. ;quiero borrar 1 elem
  105. .uno:
  106. ;shift (4-faltantes) bytes
  107. psrldq xmm2, 1;ok, borre los que no queria
  108. jmp .normal
  109. .tres:
  110. psrldq xmm2, 3;ok, borre los que no queria
  111. .normal:
  112. ;desempaqueto cada pixel a un registro (cada elem como dword)
  113. pxor xmm3,xmm3
  114. pxor xmm4,xmm4
  115. pxor xmm5,xmm5
  116. pxor xmm6,xmm6
  117. pxor xmm7,xmm7
  118. pxor xmm8,xmm8
  119. punpcklbw xmm3, xmm2 ;pix a,b
  120. punpckhbw xmm4, xmm2 ;pix c,d
  121. punpcklwd xmm5, xmm3 ;pix a
  122. punpckhwd xmm6, xmm3 ;pix b
  123. punpcklwd xmm7, xmm4 ;pix c
  124. punpckhwd xmm8, xmm4 ;pix d
  125. ;cargo 1 elem de matriz como single
  126. movdqu xmm9, [matriz] ;traje 4 float.
  127. pshufd xmm11, xmm9, 0x00
  128. pshufd xmm12, xmm9, 0x55
  129. pshufd xmm13, xmm9, 0xAA
  130. pshufd xmm14, xmm9, 0xFF
  131. ;acomodo los registros
  132. psrldq xmm5, 3
  133. psrldq xmm6, 3
  134. psrldq xmm7, 3
  135. psrldq xmm8, 3
  136. ;int2float
  137. CVTDQ2PS xmm5,xmm5
  138. CVTDQ2PS xmm6,xmm6
  139. CVTDQ2PS xmm7,xmm7
  140. CVTDQ2PS xmm8,xmm8
  141. ;multiplico cada pixel por su coeficiente de la matriz(float)
  142. mulps xmm5, xmm11
  143. mulps xmm6, xmm12
  144. mulps xmm7, xmm13
  145. mulps xmm8, xmm14
  146. ;acumulo
  147. addps xmm10, xmm5
  148. addps xmm10, xmm6
  149. addps xmm10, xmm7
  150. addps xmm10, xmm8
  151. ;actualizo cuantos faltan
  152. sub col_faltan, 4*PIXEL_SIZE
  153. cmp col_faltan, 0
  154. jle .finFilaInterna
  155. cmp col_faltan, 4
  156. jle .retroceder ;me faltan entre 0 y 4 pixeles, retrocedo suficiente para que me falten 4 exactos
  157. add src, PIXEL_SIZE*4 ; Incremento 4 pixeles
  158. add matriz, PIXEL_SIZE*4
  159. jmp .loopFila
  160. .retroceder:
  161. lea src, [src-(4-col_faltan)]
  162. jmp .loopFila
  163. .finFilaInterna:
  164. dec filas_faltan
  165. cmp filas_faltan, 0
  166. je .sumar
  167. jmp .loopInterno
  168. ;avanzo ancho img - (2k+1 pix)
  169. ;faltan >0 filas? jmp .loopInterno
  170. .sumar:
  171. xor rax,rax
  172. .write:
  173. ;packusdw xmm10,xmm10
  174. ;packuswb xmm10,xmm10
  175. CVTPS2DQ xmm10,xmm10
  176. ;me quedan 4 int dword<=255, necesito moverlos a 4byte en la parte baja
  177. movd [dst], xmm10 ; Escribo en el destino
  178. .endLoop:
  179. mov src, tmp_src
  180. add src, PIXEL_SIZE ; Incremento 1 pixel
  181. add dst, PIXEL_SIZE
  182. add cont_c, PIXEL_SIZE
  183. jmp .loop
  184. .finFila:
  185. dec filas
  186. cmp filas, qword 0
  187. je .fin
  188. lea src, [src+PIXEL_SIZE*radius] ;agrego radius a la columna (termino la fila)
  189. lea dst, [dst+PIXEL_SIZE*radius]
  190. jmp .iniciarFila
  191. .fin:
  192. pop r15
  193. pop r14
  194. pop r13
  195. pop r12
  196. pop r11
  197. pop r10
  198. pop r9
  199. pop rbp
  200. ret