blur_asm.asm 5.2 KB

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