Repository navigation
Expand file tree
/
Copy pathkernelConvolution.asm
More file actions
228 lines (187 loc) · 6.2 KB
/
Copy pathkernelConvolution.asm
File metadata and controls
228 lines (187 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
; -----------------------------------------------------------------------------
; Function: apply_filter_simd (Full 3x3 Convolution)
; -----------------------------------------------------------------------------
section .data
; High-Gain Laplacian (Forces thin lines to trigger the threshold)
kernel_top dw 1, 2, 1
kernel_mid dw 2, 4, 2
kernel_bottom dw 1, 2, 1
threshold_val db 255 ; Slightly higher threshold for this hot kernel
global apply_filter_simd
section .text
apply_filter_simd:
push rbp
mov rbp, rsp
; Load kernel coefficients once
vpbroadcastw ymm8, [kernel_top]
vpbroadcastw ymm9, [kernel_top + 2]
vpbroadcastw ymm10, [kernel_top + 4]
vpbroadcastw ymm11, [kernel_bottom]
vpbroadcastw ymm12, [kernel_bottom + 2]
vpbroadcastw ymm13, [kernel_bottom + 4]
vpbroadcastw ymm14, [kernel_mid]
vpbroadcastw ymm15, [kernel_mid + 2]
vpbroadcastw ymm7, [kernel_mid + 4]
mov r8, 1 ; r8 = current_row (y)
.row_loop:
mov rax, r8
imul rax, rdx ; offset = y * width
lea r9, [rdi + rax] ; Current input row
lea r12, [rsi + rax] ; Output row
; FIX: Calculate Above/Below pointers correctly
mov r13, r9
sub r13, rdx ; r13 = Row ABOVE
mov r14, r9
add r14, rdx ; r14 = Row BELOW
mov r11, 1 ; r11 = current_col (x)
.col_loop:
mov r10, rdx
sub r10, r11
cmp r10, 18
jl .scalar_fallback
; --- SIMD BLOCK (16 pixels at once) ---
; Row ABOVE
vmovdqu xmm0, [r13 + r11 - 1]
vpmovzxbw ymm0, xmm0
vpmullw ymm0, ymm0, ymm8 ; Top-Left
vmovdqu xmm1, [r13 + r11]
vpmovzxbw ymm1, xmm1
vpmullw ymm1, ymm1, ymm9 ; Top-Center
vpaddw ymm0, ymm0, ymm1
vmovdqu xmm2, [r13 + r11 + 1]
vpmovzxbw ymm2, xmm2
vpmullw ymm2, ymm2, ymm10 ; Top-Right
vpaddw ymm0, ymm0, ymm2; Mid-Left
; Row MIDDLE
vmovdqu xmm3, [r9 + r11 - 1]
vpmovzxbw ymm3, xmm3
vpmullw ymm3, ymm3, ymm14 ; Mid-Left
vpaddw ymm0, ymm0, ymm3
vmovdqu xmm4, [r9 + r11]
vpmovzxbw ymm4, xmm4
vpmullw ymm4, ymm4, ymm15 ; Mid-Center
vpaddw ymm0, ymm0, ymm4
vmovdqu xmm4, [r9 + r11 + 1]
vpmovzxbw ymm4, xmm4
vpmullw ymm4, ymm4, ymm7 ; Mid-Right
vpaddw ymm0, ymm0, ymm4
; Row BELOW
vmovdqu xmm3, [r14 + r11 - 1]
vpmovzxbw ymm3, xmm3
vpmullw ymm3, ymm3, ymm11 ; Bottom-Left
vpaddw ymm0, ymm0, ymm3
vmovdqu xmm4, [r14 + r11]
vpmovzxbw ymm4, xmm4
vpmullw ymm4, ymm4, ymm12 ; Bottom-Center
vpaddw ymm0, ymm0, ymm4
vmovdqu xmm5, [r14 + r11 + 1]
vpmovzxbw ymm5, xmm5
vpmullw ymm5, ymm5, ymm13 ; Bottom-Right
vpaddw ymm0, ymm0, ymm5
; Absolute value
vpabsw ymm0, ymm0
; --- NEW: 16-bit Threshold Comparison ---
; Load the 8-bit threshold and convert it to a 16-bit broadcast
movzx eax, byte [rel threshold_val]
vmovd xmm6, eax
vpbroadcastw ymm6, xmm6 ; Broadcast threshold as 16-bit words
; Compare ymm0 > threshold (Safe, because both are positive 16-bit numbers)
vpcmpgtw ymm0, ymm0, ymm6 ; If true: 0xFFFF, If false: 0x0000
; Now pack the 16-bit masks into 8-bit masks
vpacksswb ymm0, ymm0, ymm0 ; 0xFFFF becomes 0xFF (255 - White)
vpermq ymm0, ymm0, 0xD8 ; Fix the lane crossing
vmovdqu [r12 + r11], xmm0 ; Store direct black and white result
add r11, 16 ; Next 16 pixels
jmp .col_loop
.scalar_fallback:
; 1. Check if we have reached the end of the width
cmp r11, rdx
jge .next_row
; 2. Initialize accumulator in R10 (using R10 as a signed sum)
xor r10, r10 ; Clear sum
; --- Process ROW ABOVE (R13) ---
; Top-Left
movzx ax, byte [r13 + r11 - 1]
movsx bx, [rel kernel_top]
imul ax, bx
movsx eax, ax ; Sign extend to 32-bit
add r10d, eax
; Top-Center
movzx ax, byte [r13 + r11]
movsx bx, [rel kernel_top + 2]
imul ax, bx
movsx eax, ax
add r10d, eax
; Top-Right
movzx ax, byte [r13 + r11 + 1]
movsx bx, [rel kernel_top + 4]
imul ax, bx
movsx eax, ax
add r10d, eax
; --- Process MIDDLE ROW (R9) ---
; Mid-Left
movzx ax, byte [r9 + r11 - 1]
movsx bx, [rel kernel_mid]
imul ax, bx
movsx eax, ax
add r10d, eax
; Mid-Center
movzx ax, byte [r9 + r11]
movsx bx, [rel kernel_mid + 2]
imul ax, bx
movsx eax, ax
add r10d, eax
; Mid-Right
movzx ax, byte [r9 + r11 + 1]
movsx bx, [rel kernel_mid + 4]
imul ax, bx
movsx eax, ax
add r10d, eax
; --- Process ROW BELOW (R14) ---
; Bottom-Left
movzx ax, byte [r14 + r11 - 1]
movsx bx, [rel kernel_bottom]
imul ax, bx
movsx eax, ax
add r10d, eax
; Bottom-Center
movzx ax, byte [r14 + r11]
movsx bx, [rel kernel_bottom + 2]
imul ax, bx
movsx eax, ax
add r10d, eax
; Bottom-Right
movzx ax, byte [r14 + r11 + 1]
movsx bx, [rel kernel_bottom + 4]
imul ax, bx
movsx eax, ax
add r10d, eax
; --- Post-Processing: Absolute Value and Clamping ---
test r10d, r10d
jns .is_positive
neg r10d ; قدر مطلق
.is_positive:
; آستانهگذاری ساده
movzx ecx, byte [rel threshold_val] ; Fill extra bits with zeroes
cmp r10d, ecx
ja .make_white ; اگر بزرگتر بود برو به بخش سفید کردن
mov r10b, 0 ; سیاه
jmp .no_clamp
.make_white:
mov r10b, 255 ; سفید
.no_clamp:
; Store the result back to memory
mov [r12 + r11], r10b
; Advance to next pixel
inc r11
jmp .scalar_fallback ; Don't let it slip to the next row
.next_row:
inc r8
mov r10, rcx
dec r10
cmp r8, r10
jl .row_loop
vzeroupper
leave
ret
section .note.GNU-stack noalloc noexec nowrite progbits