blur_asm.asm 5.0 KB

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