Repository navigation
Expand file tree
/
Copy pathlissajousAVX.s
More file actions
144 lines (120 loc) · 6.35 KB
/
Copy pathlissajousAVX.s
File metadata and controls
144 lines (120 loc) · 6.35 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
; Lissajous curve generator using AVX instructions
%macro V_COMPUTE_SINE 1
; %1 - ymm register containing the input values (x or y)
; uses ymm7, ymm8 as temporary registers
; results are stored in %1
vmovaps ymm7, %1 ; y = %1
vmulps ymm7, ymm7, ymm7 ; y^2 = ymm7
vmovaps ymm8, [c13] ; ymm8 = result of sine
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c11]
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c9]
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c7]
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c5]
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c3]
vmulps ymm8, ymm8, ymm7
vaddps ymm8, ymm8, [c1]
vmulps ymm8, ymm8, %1
vmovaps %1, ymm8
%endmacro
%macro WRITE_PIXEL_IN_BUFFER 3
; %1 - xmm register containing x coordinates
; %2 - xmm register containing y coordinates
; %3 the desired pixel index in the current xmm register (0, 1, 2, or 3)
; uses r8d, r9d, eax
vpextrd r8d, %1, %3 ; r8d = x5
vpextrd r9d, %2, %3 ; r9d = y5
mov eax, r9d
imul eax, esi
add eax, r8d
mov dword [rdi + 4*rax], 0xFFFFFFFF
%endmacro
section .data
align 32
start: dd 0.00000, 0.00025, 0.00050, 0.00075, 0.00100, 0.00125, 0.00150, 0.00175
step_8x: dd 0.00200, 0.00200, 0.00200, 0.00200, 0.00200, 0.00200, 0.00200, 0.00200 ; step = start[-1] - start[0]
half: dd 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5
; minimax polynomial (sine approximation; abs. error minimized, degree 13) coefficients
c1: dd 6.28318516, 6.28318516, 6.28318516, 6.28318516, 6.28318516, 6.28318516, 6.28318516, 6.28318516
c3: dd -41.3416550, -41.3416550, -41.3416550, -41.3416550, -41.3416550, -41.3416550, -41.3416550, -41.3416550
c5: dd 81.6010041, 81.6010041, 81.6010041, 81.6010041, 81.6010041, 81.6010041, 81.6010041, 81.6010041
c7: dd -76.5497823, -76.5497823, -76.5497823, -76.5497823, -76.5497823, -76.5497823, -76.5497823, -76.5497823
c9: dd 42.0579638, 42.0579638, 42.0579638, 42.0579638, 42.0579638, 42.0579638, 42.0579638, 42.0579638
c11: dd -15.0792949, -15.0792949, -15.0792949, -15.0792949, -15.0792949, -15.0792949, -15.0792949, -15.0792949
c13: dd 3.6550839, 3.6550839, 3.6550839, 3.6550839, 3.6550839, 3.6550839, 3.6550839, 3.6550839
section .text
DEFAULT REL
global lissajousAVX
lissajousAVX:
; --- prolog ---
push rbp
mov rbp, rsp
; --- prolog ---
mov rcx, 500 ; rcx <- iterations (t <= 1.0 - one rotation; 1 / step_8x = 500 iter) (DO NOT CHANGE)
vbroadcastss ymm0, xmm0 ; copies xmm0[0] to all 8 slots of ymm0 => ymm0 = [ A, A, A, A | A, A, A, A ]
vbroadcastss ymm1, xmm1 ; ymm1 = [ B, B, B, B | B, B, B, B ]
vbroadcastss ymm2, xmm2 ; ymm2 = [ a, a, a, a | a, a, a, a ]
vbroadcastss ymm3, xmm3 ; ymm3 = [ b, b, b, b | b, b, b, b ]
vbroadcastss ymm4, xmm4 ; ymm4 = [ delta, delta, delta, delta | delta, delta, delta, delta ]
vmovaps ymm5, [start] ; ymm5 <- [ t3 | t2 | t1 | t0 ], future [ x3 | x2 | x1 | x0 ]
vmovaps ymm6, ymm5 ; ymm6 <- [ t3 | t2 | t1 | t0 ], future [ y3 | y2 | y1 | y0 ]
vmovaps ymm15, ymm5 ; ymm15 <- [ curr_t | curr_t | curr_t | curr_t ] = [ t3 | t2 | t1 | t0 ]
vmovaps ymm14, [step_8x] ; ymm14 <- [ 0.002, 0.002, 0.002, 0.002 | 0.002, 0.002, 0.002, 0.002 ]
vcvtsi2ss xmm9, xmm9, esi ; ymm9 = [ 0 | 0 | 0 | Width ]
vbroadcastss ymm9, xmm9 ; [ Width | Width | Width | Width ]
vmulps ymm9, ymm9, [half] ; ymm14 = [ 0.5*Width | 0.5*Width | 0.5*Width | 0.5*Width ]
vcvtsi2ss xmm10, xmm10, edx ; ymm15 = [ 0 | 0 | 0 | Height ]
vbroadcastss ymm10, xmm10 ; [ 0, 0, 0, 0 | 0, 0, 0, H ] -> [ H, H, H, H | H, H, H, H ]
vmulps ymm10, ymm10, [half] ; ymm15 = [ 0.5*Height | 0.5*Height | 0.5*Height | 0.5*Height ]
mainloop:
; ================== compute x(t) ==================
vmulps ymm5, ymm5, ymm2 ; ymm5 = [ a*t3 | a*t2 | a*t1 | a*t0 ]
vaddps ymm5, ymm5, ymm4 ; ymm5 = [ a*t3+delta | a*t2+delta | a*t1+delta | a*t0+delta ]
; normalize z := a*t+delta for sine
vmovaps ymm7, ymm5
vroundps ymm7, ymm7, 0x00
vsubps ymm5, ymm5, ymm7
V_COMPUTE_SINE ymm5 ; ymm5 = [ sin(a*t3+delta) | sin(a*t2+delta) | sin(a*t1+delta) | sin(a*t0+delta) ]
vmulps ymm5, ymm5, ymm0 ; ymm5 = [ A*sin(a*t3+delta) | A*sin(a*t2+delta) | A*sin(a*t1+delta) | A*sin(a*t0+delta) ]
; ================== compute y(t) ==================
vmulps ymm6, ymm6, ymm3 ; ymm6 = [ b*t3 | b*t2 | b*t1 | b*t0 ]
; normalize z := b*t for sine
vmovaps ymm7, ymm6
vroundps ymm7, ymm7, 0x00
vsubps ymm6, ymm6, ymm7
V_COMPUTE_SINE ymm6 ; ymm6 = [ sin(b*t3) | sin(b*t2) | sin(b*t1) | sin(b*t0) ]
vmulps ymm6, ymm6, ymm1 ; ymm6 = [ B*sin(b*t3) | B*sin(b*t2) | B*sin(b*t1) | B*sin(b*t0) ]
vaddps ymm5, ymm5, ymm9 ; x = A*sin(a*t+delta) + 0.5*Width
vaddps ymm6, ymm6, ymm10 ; y = B*sin(b*t) + 0.5*Height
; ================== draw points ==================
vcvttps2dq ymm5, ymm5 ; convert x to int
vcvttps2dq ymm6, ymm6 ; convert y to int
; pixels 1-4
WRITE_PIXEL_IN_BUFFER xmm5, xmm6, 0
WRITE_PIXEL_IN_BUFFER xmm5, xmm6, 1
WRITE_PIXEL_IN_BUFFER xmm5, xmm6, 2
WRITE_PIXEL_IN_BUFFER xmm5, xmm6, 3
vextractf128 xmm11, ymm5, 1 ; xmm11 = [ x7 | x6 | x5 | x4 ]
vextractf128 xmm12, ymm6, 1 ; xmm12 = [ y7 | y6 | y5 | y4 ]
; pixels 5-8
WRITE_PIXEL_IN_BUFFER xmm11, xmm12, 0
WRITE_PIXEL_IN_BUFFER xmm11, xmm12, 1
WRITE_PIXEL_IN_BUFFER xmm11, xmm12, 2
WRITE_PIXEL_IN_BUFFER xmm11, xmm12, 3
; ================== update t ==================
vaddps ymm15, ymm15, ymm14 ; t += [step]
vmovaps ymm5, ymm15 ; ymm5 <- current t
vmovaps ymm6, ymm15 ; ymm6 <- current t
dec rcx
test rcx, rcx
jnz mainloop
end:
; --- epilog ---
mov rsp, rbp
pop rbp
; --- epilog ---
ret