blur_asm.asm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. ; Algunos defines ultiles
  17. %define PIXEL_SIZE 4
  18. ; Mascaras y esas cosas
  19. section .data
  20. section .text
  21. ;void blur_asm (
  22. ;unsigned char *src,
  23. ;unsigned char *dst,
  24. ;int filas,
  25. ;int cols,
  26. ;float sigma,
  27. ;int radius)
  28. _blur_asm:
  29. blur_asm:
  30. push rbp
  31. mov rbp, rsp ; Stack frame
  32. push r9
  33. push r10
  34. push r11
  35. push r12
  36. push r13
  37. push r14
  38. push r15
  39. .init:
  40. push src
  41. push dst
  42. push cols
  43. push filas
  44. push radius
  45. sub rsp, 16
  46. movdqu [rsp],xmm0
  47. mov rdi, radius
  48. call convulcion_matrix
  49. movdqu xmm0, [rsp]
  50. add rsp, 16
  51. pop radius
  52. pop filas
  53. pop cols
  54. pop dst
  55. pop src
  56. mov r14,rcx ;guardo rcx para loop
  57. mov r9, rdx ;salvo rdx por los mul
  58. mov rax, PIXEL_SIZE
  59. mul cols
  60. mul radius
  61. ; rax:=cols*pix_size*radius => cuantas filas debo saltear
  62. ;add src, rax
  63. add dst, rax ; Avanzo "radius" filas (col*pix_size*radius)
  64. sub filas, radius ;acomodo filas para ignorar los bordes
  65. sub filas, radius ;acomodo filas para ignorar los bordes
  66. mov cols, r9 ;recupero cols por el mul
  67. sub cols, radius ;resto radius columnas
  68. sub cols, radius ;resto radius columnas
  69. mov rax, PIXEL_SIZE
  70. mul cols
  71. mov cols, rax ;cols:=cols*pix_size
  72. .iniciarFila:
  73. ;lea src, [src+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  74. lea dst, [dst+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
  75. xor cont_c,cont_c
  76. .loop:
  77. cmp cols, cont_c ; Comparo tamaño con el contador
  78. je .finFila ; Si ya recorri la imagen voy al final
  79. mov filas_faltan, radius;FIXME este radius es pixeles no bytes
  80. add filas_faltan, radius
  81. add filas_faltan, PIXEL_SIZE ; 2r+1 filas
  82. .loopInterno:
  83. mov col_faltan, radius
  84. add col_faltan, radius
  85. add col_faltan, PIXEL_SIZE ; 2r+1 columnas
  86. .loopFila:
  87. ;levanto 4px
  88. movdqu xmm2, [src] ; Cargo 4 pix de la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
  89. cmp col_faltan, 3
  90. jg .normal
  91. je .tres
  92. jl .uno
  93. .uno:
  94. ;shift (4-faltantes) bytes
  95. psrldq xmm2, 1;ok, borre los que no queria
  96. jmp .normal
  97. .tres:
  98. psrldq xmm2, 3;ok, borre los que no queria
  99. .normal:
  100. ;desempaqueto cada pixel a un registro (cada elem como dword)
  101. punpcklbw xmm2, xmm3
  102. punpckhbw xmm2, xmm4
  103. punpcklwd xmm3, xmm5
  104. punpckhwd xmm3, xmm6
  105. punpcklwd xmm4, xmm7
  106. punpckhwd xmm4, xmm8
  107. ;cargo 1 elem de matriz como single
  108. movd xmm9, [matriz]
  109. ;TODO lo clono con mascara a los 4 elem del xmm
  110. ;multiplico cada pixel por su coeficiente de la matriz(float)
  111. mulps xmm5, xmm9
  112. mulps xmm6, xmm9
  113. mulps xmm7, xmm9
  114. mulps xmm8, xmm9
  115. ;acumulo
  116. addps xmm10, xmm5
  117. addps xmm10, xmm6
  118. addps xmm10, xmm7
  119. addps xmm10, xmm8
  120. ;actualizo cuantos faltan
  121. sub col_faltan, 4*PIXEL_SIZE
  122. cmp col_faltan, 4
  123. jg .loopFila
  124. cmp col_faltan, 0
  125. jle .finFilaInterna
  126. ;me faltan entre 0 y 4 pixeles, retrocedo suficiente para que me falten 4 exactos
  127. lea src, [src-(4-col_faltan)]
  128. jmp .loopFila
  129. .finFilaInterna:
  130. dec filas_faltan
  131. cmp filas_faltan, 0
  132. je .sumar
  133. jmp .loopInterno
  134. ;avanzo ancho img - (2k+1 pix)
  135. ;faltan >0 filas? jmp .loopInterno
  136. .sumar:
  137. .write:
  138. movdqu [dst], xmm10 ; Escribo en el destino
  139. .endLoop:
  140. add src, PIXEL_SIZE ; Incremento 4 pixeles
  141. add dst, PIXEL_SIZE
  142. add cont_c, PIXEL_SIZE
  143. jmp .loop
  144. .finFila:
  145. dec filas
  146. cmp filas, qword 0
  147. je .fin
  148. lea src, [src+PIXEL_SIZE*radius] ;agrego radius a la columna (termino la fila)
  149. lea dst, [dst+PIXEL_SIZE*radius]
  150. jmp .iniciarFila
  151. .fin:
  152. pop r15
  153. pop r14
  154. pop r13
  155. pop r12
  156. pop r11
  157. pop r10
  158. pop r9
  159. pop rbp
  160. ret