blur_asm.asm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. movdqu xmm0, [rsp]
  53. add rsp, 16
  54. pop radius
  55. pop filas
  56. pop cols
  57. pop dst
  58. pop src
  59. ;mov r14,rcx ;guardo rcx para loop
  60. mov r9, rdx ;salvo rdx por los mul
  61. mov rax, PIXEL_SIZE
  62. mul cols
  63. mul radius
  64. ; rax:=cols*pix_size*radius => cuantas filas debo saltear
  65. ;add src, rax
  66. add dst, rax ; Avanzo "radius" filas (col*pix_size*radius)
  67. sub filas, radius ;acomodo filas para ignorar los bordes
  68. sub filas, radius ;acomodo filas para ignorar los bordes
  69. mov cols, r9 ;recupero cols por el mul
  70. sub cols, radius ;resto radius columnas
  71. sub cols, radius ;resto radius columnas
  72. mov rax, PIXEL_SIZE
  73. mul cols
  74. mov cols, rax ;cols:=cols*pix_size
  75. .iniciarFila:
  76. ;lea src, [src+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  77. lea dst, [dst+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  78. xor cont_c,cont_c
  79. .loop:
  80. cmp cols, cont_c ; Comparo tamaño con el contador
  81. je .finFila ; Si ya recorri la imagen voy al final
  82. mov filas_faltan, radius
  83. add filas_faltan, radius
  84. inc filas_faltan ; 2r+1 filas
  85. mov tmp_src, src
  86. .loopInterno:
  87. mov col_faltan, radius
  88. add col_faltan, radius
  89. inc col_faltan ; 2r+1 columnas
  90. mov basura, rdx
  91. mov rax,PIXEL_SIZE
  92. mul col_faltan ;destruyo rdx
  93. mov col_faltan, rax
  94. mov rdx, basura ;salvo rdx
  95. .loopFila:
  96. ;levanto 4px
  97. movdqu xmm2, [src] ; Cargo 4 pix de la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  98. cmp col_faltan, 3
  99. jg .normal ;no qiuero shiftear
  100. je .tres ;quiero borrar 3 elem
  101. ;quiero borrar 1 elem
  102. .uno:
  103. ;shift (4-faltantes) bytes
  104. psrldq xmm2, 1;ok, borre los que no queria
  105. jmp .normal
  106. .tres:
  107. psrldq xmm2, 3;ok, borre los que no queria
  108. .normal:
  109. ;desempaqueto cada pixel a un registro (cada elem como dword)
  110. punpcklbw xmm2, xmm3
  111. punpckhbw xmm2, xmm4
  112. punpcklwd xmm3, xmm5
  113. punpckhwd xmm3, xmm6
  114. punpcklwd xmm4, xmm7
  115. punpckhwd xmm4, xmm8
  116. ;cargo 1 elem de matriz como single
  117. movd xmm9, [matriz]
  118. ;TODO lo clono con mascara a los 4 elem del xmm
  119. ;multiplico cada pixel por su coeficiente de la matriz(float)
  120. mulps xmm5, xmm9
  121. mulps xmm6, xmm9
  122. mulps xmm7, xmm9
  123. mulps xmm8, xmm9
  124. ;acumulo
  125. addps xmm10, xmm5
  126. addps xmm10, xmm6
  127. addps xmm10, xmm7
  128. addps xmm10, xmm8
  129. ;actualizo cuantos faltan
  130. sub col_faltan, 4*PIXEL_SIZE
  131. cmp col_faltan, 0
  132. jle .finFilaInterna
  133. cmp col_faltan, 4
  134. jle .retroceder ;me faltan entre 0 y 4 pixeles, retrocedo suficiente para que me falten 4 exactos
  135. add src, PIXEL_SIZE*4 ; Incremento 4 pixeles
  136. jmp .loopFila
  137. .retroceder:
  138. lea src, [src-(4-col_faltan)]
  139. jmp .loopFila
  140. .finFilaInterna:
  141. dec filas_faltan
  142. cmp filas_faltan, 0
  143. je .sumar
  144. jmp .loopInterno
  145. ;avanzo ancho img - (2k+1 pix)
  146. ;faltan >0 filas? jmp .loopInterno
  147. .sumar:
  148. .write:
  149. movdqu [dst], xmm10 ; Escribo en el destino
  150. .endLoop:
  151. mov src, tmp_src
  152. add src, PIXEL_SIZE ; Incremento 1 pixel
  153. add dst, PIXEL_SIZE
  154. add cont_c, PIXEL_SIZE
  155. jmp .loop
  156. .finFila:
  157. dec filas
  158. cmp filas, qword 0
  159. je .fin
  160. lea src, [src+PIXEL_SIZE*radius] ;agrego radius a la columna (termino la fila)
  161. lea dst, [dst+PIXEL_SIZE*radius]
  162. jmp .iniciarFila
  163. .fin:
  164. pop r15
  165. pop r14
  166. pop r13
  167. pop r12
  168. pop r11
  169. pop r10
  170. pop r9
  171. pop rbp
  172. ret