| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- ; asmsyntax=nasm
- default rel global _blur_asm
- global blur_asm
- extern convulcion_matrix
- ; Alias para no volverme loco con los registros
- %define src rdi
- %define dst rsi
- %define cols rdx
- %define filas r14
- %define sigma xmm0
- %define radius r8
- %define cont_c r9
- %define matriz r10
- %define filas_faltan r11
- %define col_faltan r12
- %define basura r13
- %define tmp_src rbp
- ; Algunos defines ultiles
- %define PIXEL_SIZE 4
- ; Mascaras y esas cosas
- section .data
- cosa: db 0,4,8,12,255,255,255,255,255,255,255,255,255,255,255,255
- section .text
- ;void blur_asm (
- ;unsigned char *src,
- ;unsigned char *dst,
- ;int filas,
- ;int cols,
- ;float sigma,
- ;int radius)
- _blur_asm:
- blur_asm:
- push rbp
- mov rbp, rsp ; Stack frame
- push r9
- push r10
- push r11
- push r12
- push r13
- push r14
- push r15
- .init:
- mov filas, rcx ;filas
- push src
- push dst
- push cols
- push filas
- push radius
- sub rsp, 16
- movdqu [rsp],xmm0
- mov rdi, radius
- call convulcion_matrix
- mov matriz, rax
- mov r15, matriz ;copio puntero inicial
- movdqu xmm0, [rsp]
- add rsp, 16
- pop radius
- pop filas
- pop cols
- pop dst
- pop src
- ;mov r14,rcx ;guardo rcx para loop
- mov r9, rdx ;salvo rdx por los mul
- mov rax, PIXEL_SIZE
- mul cols
- mul radius
- ; rax:=cols*pix_size*radius => cuantas filas debo saltear
- ;add src, rax
- add dst, rax ; Avanzo "radius" filas (col*pix_size*radius)
- sub filas, radius ;acomodo filas para ignorar los bordes
- sub filas, radius ;acomodo filas para ignorar los bordes
- mov cols, r9 ;recupero cols por el mul
- sub cols, radius ;resto radius columnas
- sub cols, radius ;resto radius columnas
- mov rax, PIXEL_SIZE
- mul cols
- mov cols, rax ;cols:=cols*pix_size
- .iniciarFila:
- ;lea src, [src+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
- lea dst, [dst+PIXEL_SIZE*radius] ;avanzo radius pixeles (borde)
- xor cont_c,cont_c
- .loop:
- cmp cols, cont_c ; Comparo tamaño con el contador
- je .finFila ; Si ya recorri la imagen voy al final
- mov filas_faltan, radius
- add filas_faltan, radius
- inc filas_faltan ; 2r+1 filas
- mov tmp_src, src
- pxor xmm10,xmm10
- mov matriz, r15
- .loopInterno:
- mov col_faltan, radius
- add col_faltan, radius
- inc col_faltan ; 2r+1 columnas
- mov basura, rdx
- mov rax,PIXEL_SIZE
- mul col_faltan ;destruyo rdx
- mov col_faltan, rax
- mov rdx, basura ;salvo rdx
- .loopFila:
- ;levanto 4px
- movdqu xmm2, [src] ; Cargo 4 pix de la imagen 1 => xmm0 = |B(P1)|G(P1)|R(P1)|A(P1)|B(P2)|G(P2)|......|
- cmp col_faltan, 3
- jg .normal ;no qiuero shiftear
- je .tres ;quiero borrar 3 elem
- ;quiero borrar 1 elem
- .uno:
- ;shift (4-faltantes) bytes
- psrldq xmm2, 1;ok, borre los que no queria
- jmp .normal
- .tres:
- psrldq xmm2, 3;ok, borre los que no queria
- .normal:
- ;desempaqueto cada pixel a un registro (cada elem como dword)
- pxor xmm3,xmm3
- pxor xmm4,xmm4
- pxor xmm5,xmm5
- pxor xmm6,xmm6
- pxor xmm7,xmm7
- pxor xmm8,xmm8
- punpcklbw xmm3, xmm2 ;pix a,b
- punpckhbw xmm4, xmm2 ;pix c,d
- punpcklwd xmm5, xmm3 ;pix a
- punpckhwd xmm6, xmm3 ;pix b
- punpcklwd xmm7, xmm4 ;pix c
- punpckhwd xmm8, xmm4 ;pix d
- ;cargo 1 elem de matriz como single
- movdqu xmm9, [matriz] ;traje 4 float.
- pshufd xmm11, xmm9, 0x00
- pshufd xmm12, xmm9, 0x55
- pshufd xmm13, xmm9, 0xAA
- pshufd xmm14, xmm9, 0xFF
- ;acomodo los registros
- psrldq xmm5, 3
- psrldq xmm6, 3
- psrldq xmm7, 3
- psrldq xmm8, 3
- ;int2float
- CVTDQ2PS xmm5,xmm5
- CVTDQ2PS xmm6,xmm6
- CVTDQ2PS xmm7,xmm7
- CVTDQ2PS xmm8,xmm8
- ;multiplico cada pixel por su coeficiente de la matriz(float)
- mulps xmm5, xmm11
- mulps xmm6, xmm12
- mulps xmm7, xmm13
- mulps xmm8, xmm14
- ;acumulo
- addps xmm10, xmm5
- addps xmm10, xmm6
- addps xmm10, xmm7
- addps xmm10, xmm8
-
- ;actualizo cuantos faltan
- sub col_faltan, 4*PIXEL_SIZE
- cmp col_faltan, 0
- jle .finFilaInterna
- cmp col_faltan, 4
- jle .retroceder ;me faltan entre 0 y 4 pixeles, retrocedo suficiente para que me falten 4 exactos
- add src, PIXEL_SIZE*4 ; Incremento 4 pixeles
- add matriz, PIXEL_SIZE*4
- jmp .loopFila
- .retroceder:
- lea src, [src-(4-col_faltan)]
- jmp .loopFila
-
- .finFilaInterna:
- dec filas_faltan
- cmp filas_faltan, 0
- je .sumar
- jmp .loopInterno
- ;avanzo ancho img - (2k+1 pix)
- ;faltan >0 filas? jmp .loopInterno
- .sumar:
- xor rax,rax
- .write:
- ;packusdw xmm10,xmm10
- ;packuswb xmm10,xmm10
- CVTPS2DQ xmm10,xmm10
- ;me quedan 4 int dword<=255, necesito moverlos a 4byte en la parte baja
- movdqu xmm11, [cosa] ;uso xmm11 de tmp
- pshufb xmm10, xmm11
- movd [dst], xmm10 ; Escribo en el destino
- .endLoop:
- mov src, tmp_src
- add src, PIXEL_SIZE ; Incremento 1 pixel
- add dst, PIXEL_SIZE
- add cont_c, PIXEL_SIZE
- jmp .loop
- .finFila:
- dec filas
- cmp filas, qword 0
- je .fin
- lea src, [src+PIXEL_SIZE*radius] ;agrego radius a la columna (termino la fila)
- lea dst, [dst+PIXEL_SIZE*radius]
- jmp .iniciarFila
- .fin:
- pop r15
- pop r14
- pop r13
- pop r12
- pop r11
- pop r10
- pop r9
- pop rbp
- ret
|