34cf4058 |
1 | #include "gSP.h" |
2 | #include "OpenGL.h" |
3 | |
4 | #ifdef __VEC4_OPT |
5 | static void gSPTransformVertex4NEON(u32 v, float mtx[4][4]) |
6 | { |
7 | float *ptr = &OGL.triangles.vertices[v].x; |
8 | |
9 | #if 0 |
10 | volatile int tmp0, tmp1; |
11 | asm volatile ( |
12 | "vld1.32 {d0, d1}, [%1, :128] \n\t" //q0 = {x,y,z,w} |
13 | "add %1, %1, %4 \n\t" //q0 = {x,y,z,w} |
14 | "vld1.32 {d18, d19}, [%0, :128]! \n\t" //q9 = m |
15 | "vld1.32 {d2, d3}, [%1, :128] \n\t" //q1 = {x,y,z,w} |
16 | "add %1, %1, %4 \n\t" //q0 = {x,y,z,w} |
17 | "vld1.32 {d20, d21}, [%0, :128]! \n\t" //q10 = m |
18 | "vld1.32 {d4, d5}, [%1, :128] \n\t" //q2 = {x,y,z,w} |
19 | "add %1, %1, %4 \n\t" //q0 = {x,y,z,w} |
20 | "vld1.32 {d22, d23}, [%0, :128]! \n\t" //q11 = m |
21 | "vld1.32 {d6, d7}, [%1, :128] \n\t" //q3 = {x,y,z,w} |
22 | "vld1.32 {d24, d25}, [%0, :128] \n\t" //q12 = m |
23 | "sub %1, %1, %6 \n\t" //q0 = {x,y,z,w} |
24 | |
25 | "vmov.f32 q13, q12 \n\t" //q13 = q12 |
26 | "vmov.f32 q14, q12 \n\t" //q14 = q12 |
27 | "vmov.f32 q15, q12 \n\t" //q15 = q12 |
28 | |
29 | "vmla.f32 q12, q9, d0[0] \n\t" //q12 = q9*d0[0] |
30 | "vmla.f32 q13, q9, d2[0] \n\t" //q13 = q9*d0[0] |
31 | "vmla.f32 q14, q9, d4[0] \n\t" //q14 = q9*d0[0] |
32 | "vmla.f32 q15, q9, d6[0] \n\t" //q15 = q9*d0[0] |
33 | "vmla.f32 q12, q10, d0[1] \n\t" //q12 = q10*d0[1] |
34 | "vmla.f32 q13, q10, d2[1] \n\t" //q13 = q10*d0[1] |
35 | "vmla.f32 q14, q10, d4[1] \n\t" //q14 = q10*d0[1] |
36 | "vmla.f32 q15, q10, d6[1] \n\t" //q15 = q10*d0[1] |
37 | "vmla.f32 q12, q11, d1[0] \n\t" //q12 = q11*d1[0] |
38 | "vmla.f32 q13, q11, d3[0] \n\t" //q13 = q11*d1[0] |
39 | "vmla.f32 q14, q11, d5[0] \n\t" //q14 = q11*d1[0] |
40 | "vmla.f32 q15, q11, d7[0] \n\t" //q15 = q11*d1[0] |
41 | |
42 | "add %0, %1, %4 \n\t" //q0 = {x,y,z,w} |
43 | "add %2, %1, %5 \n\t" //q0 = {x,y,z,w} |
44 | "add %3, %1, %6 \n\t" //q0 = {x,y,z,w} |
45 | "vst1.32 {d24, d25}, [%1, :128] \n\t" //q12 |
46 | "vst1.32 {d26, d27}, [%0, :128] \n\t" //q13 |
47 | "vst1.32 {d28, d29}, [%2, :128] \n\t" //q14 |
48 | "vst1.32 {d30, d31}, [%3, :128] \n\t" //q15 |
49 | : "+&r"(mtx), "+&r"(ptr), "+r"(tmp0), "+r"(tmp1) |
50 | : "I"(sizeof(SPVertex)),"I"(2 * sizeof(SPVertex)), "I"(3 * sizeof(SPVertex)) |
51 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
52 | "d18","d19", "d20", "d21", "d22", "d23", "d24", |
53 | "d25", "d26", "d27", "d28", "d29", "d30", "d31", "memory" |
54 | ); |
55 | #else |
56 | asm volatile ( |
57 | "vld1.32 {d0, d1}, [%1] \n\t" //q0 = {x,y,z,w} |
58 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
59 | "vld1.32 {d2, d3}, [%1] \n\t" //q1 = {x,y,z,w} |
60 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
61 | "vld1.32 {d4, d5}, [%1] \n\t" //q2 = {x,y,z,w} |
62 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
63 | "vld1.32 {d6, d7}, [%1] \n\t" //q3 = {x,y,z,w} |
64 | "sub %1, %1, %3 \n\t" //q0 = {x,y,z,w} |
65 | |
66 | "vld1.32 {d18, d19}, [%0]! \n\t" //q9 = m |
67 | "vld1.32 {d20, d21}, [%0]! \n\t" //q10 = m |
68 | "vld1.32 {d22, d23}, [%0]! \n\t" //q11 = m |
69 | "vld1.32 {d24, d25}, [%0] \n\t" //q12 = m |
70 | |
71 | "vmov.f32 q13, q12 \n\t" //q13 = q12 |
72 | "vmov.f32 q14, q12 \n\t" //q14 = q12 |
73 | "vmov.f32 q15, q12 \n\t" //q15 = q12 |
74 | |
75 | "vmla.f32 q12, q9, d0[0] \n\t" //q12 = q9*d0[0] |
76 | "vmla.f32 q13, q9, d2[0] \n\t" //q13 = q9*d0[0] |
77 | "vmla.f32 q14, q9, d4[0] \n\t" //q14 = q9*d0[0] |
78 | "vmla.f32 q15, q9, d6[0] \n\t" //q15 = q9*d0[0] |
79 | "vmla.f32 q12, q10, d0[1] \n\t" //q12 = q10*d0[1] |
80 | "vmla.f32 q13, q10, d2[1] \n\t" //q13 = q10*d0[1] |
81 | "vmla.f32 q14, q10, d4[1] \n\t" //q14 = q10*d0[1] |
82 | "vmla.f32 q15, q10, d6[1] \n\t" //q15 = q10*d0[1] |
83 | "vmla.f32 q12, q11, d1[0] \n\t" //q12 = q11*d1[0] |
84 | "vmla.f32 q13, q11, d3[0] \n\t" //q13 = q11*d1[0] |
85 | "vmla.f32 q14, q11, d5[0] \n\t" //q14 = q11*d1[0] |
86 | "vmla.f32 q15, q11, d7[0] \n\t" //q15 = q11*d1[0] |
87 | |
88 | "vst1.32 {d24, d25}, [%1] \n\t" //q12 |
89 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
90 | "vst1.32 {d26, d27}, [%1] \n\t" //q13 |
91 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
92 | "vst1.32 {d28, d29}, [%1] \n\t" //q14 |
93 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
94 | "vst1.32 {d30, d31}, [%1] \n\t" //q15 |
95 | |
96 | : "+&r"(mtx), "+&r"(ptr) |
97 | : "I"(sizeof(SPVertex)), "I"(3 * sizeof(SPVertex)) |
98 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
99 | "d18","d19", "d20", "d21", "d22", "d23", "d24", |
100 | "d25", "d26", "d27", "d28", "d29", "d30", "d31", "memory" |
101 | ); |
102 | #endif |
103 | } |
104 | |
105 | //4x Transform normal and normalize |
106 | static void gSPTransformNormal4NEON(u32 v, float mtx[4][4]) |
107 | { |
108 | void *ptr = (void*)&OGL.triangles.vertices[v].nx; |
109 | asm volatile ( |
110 | "vld1.32 {d0, d1}, [%1] \n\t" //q0 = {x,y,z,w} |
111 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
112 | "vld1.32 {d2, d3}, [%1] \n\t" //q1 = {x,y,z,w} |
113 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
114 | "vld1.32 {d4, d5}, [%1] \n\t" //q2 = {x,y,z,w} |
115 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
116 | "vld1.32 {d6, d7}, [%1] \n\t" //q3 = {x,y,z,w} |
117 | "sub %1, %1, %3 \n\t" //q0 = {x,y,z,w} |
118 | |
119 | "vld1.32 {d18, d19}, [%0]! \n\t" //q9 = m |
120 | "vld1.32 {d20, d21}, [%0]! \n\t" //q10 = m+16 |
121 | "vld1.32 {d22, d23}, [%0] \n\t" //q11 = m+32 |
122 | |
123 | "vmul.f32 q12, q9, d0[0] \n\t" //q12 = q9*d0[0] |
124 | "vmul.f32 q13, q9, d2[0] \n\t" //q13 = q9*d2[0] |
125 | "vmul.f32 q14, q9, d4[0] \n\t" //q14 = q9*d4[0] |
126 | "vmul.f32 q15, q9, d6[0] \n\t" //q15 = q9*d6[0] |
127 | |
128 | "vmla.f32 q12, q10, d0[1] \n\t" //q12 += q10*q0[1] |
129 | "vmla.f32 q13, q10, d2[1] \n\t" //q13 += q10*q2[1] |
130 | "vmla.f32 q14, q10, d4[1] \n\t" //q14 += q10*q4[1] |
131 | "vmla.f32 q15, q10, d6[1] \n\t" //q15 += q10*q6[1] |
132 | |
133 | "vmla.f32 q12, q11, d1[0] \n\t" //q12 += q11*d1[0] |
134 | "vmla.f32 q13, q11, d3[0] \n\t" //q13 += q11*d3[0] |
135 | "vmla.f32 q14, q11, d5[0] \n\t" //q14 += q11*d5[0] |
136 | "vmla.f32 q15, q11, d7[0] \n\t" //q15 += q11*d7[0] |
137 | |
138 | "vmul.f32 q0, q12, q12 \n\t" //q0 = q12*q12 |
139 | "vmul.f32 q1, q13, q13 \n\t" //q1 = q13*q13 |
140 | "vmul.f32 q2, q14, q14 \n\t" //q2 = q14*q14 |
141 | "vmul.f32 q3, q15, q15 \n\t" //q3 = q15*q15 |
142 | |
143 | "vpadd.f32 d0, d0 \n\t" //d0[0] = d0[0] + d0[1] |
144 | "vpadd.f32 d2, d2 \n\t" //d2[0] = d2[0] + d2[1] |
145 | "vpadd.f32 d4, d4 \n\t" //d4[0] = d4[0] + d4[1] |
146 | "vpadd.f32 d6, d6 \n\t" //d6[0] = d6[0] + d6[1] |
147 | |
148 | "vmov.f32 s1, s2 \n\t" //d0[1] = d1[0] |
149 | "vmov.f32 s5, s6 \n\t" //d2[1] = d3[0] |
150 | "vmov.f32 s9, s10 \n\t" //d4[1] = d5[0] |
151 | "vmov.f32 s13, s14 \n\t" //d6[1] = d7[0] |
152 | |
153 | "vpadd.f32 d0, d0, d2 \n\t" //d0 = {d0[0] + d0[1], d2[0] + d2[1]} |
154 | "vpadd.f32 d1, d4, d6 \n\t" //d1 = {d4[0] + d4[1], d6[0] + d6[1]} |
155 | |
156 | "vmov.f32 q1, q0 \n\t" //q1 = q0 |
157 | "vrsqrte.f32 q0, q0 \n\t" //q0 = ~ 1.0 / sqrt(q0) |
158 | "vmul.f32 q2, q0, q1 \n\t" //q2 = q0 * q1 |
159 | "vrsqrts.f32 q3, q2, q0 \n\t" //q3 = (3 - q0 * q2) / 2 |
160 | "vmul.f32 q0, q0, q3 \n\t" //q0 = q0 * q3 |
161 | "vmul.f32 q2, q0, q1 \n\t" //q2 = q0 * q1 |
162 | "vrsqrts.f32 q3, q2, q0 \n\t" //q3 = (3 - q0 * q2) / 2 |
163 | "vmul.f32 q0, q0, q3 \n\t" //q0 = q0 * q3 |
164 | |
165 | "vmul.f32 q3, q15, d1[1] \n\t" //q3 = q15*d1[1] |
166 | "vmul.f32 q2, q14, d1[0] \n\t" //q2 = q14*d1[0] |
167 | "vmul.f32 q1, q13, d0[1] \n\t" //q1 = q13*d0[1] |
168 | "vmul.f32 q0, q12, d0[0] \n\t" //q0 = q12*d0[0] |
169 | |
170 | "vst1.32 {d0, d1}, [%1] \n\t" //d0={nx,ny,nz,pad} |
171 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
172 | "vst1.32 {d2, d3}, [%1] \n\t" //d2={nx,ny,nz,pad} |
173 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
174 | "vst1.32 {d4, d5}, [%1] \n\t" //d4={nx,ny,nz,pad} |
175 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
176 | "vst1.32 {d6, d7}, [%1] \n\t" //d6={nx,ny,nz,pad} |
177 | |
178 | : "+&r"(mtx), "+&r"(ptr) |
179 | : "I"(sizeof(SPVertex)), "I"(3 * sizeof(SPVertex)) |
180 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
181 | "d16","d17", "d18","d19", "d20", "d21", "d22", |
182 | "d23", "d24", "d25", "d26", "d27", "d28", "d29", |
183 | "d30", "d31", "memory" |
184 | ); |
185 | } |
186 | |
187 | static void gSPLightVertex4NEON(u32 v) |
188 | { |
189 | volatile float result[16]; |
190 | |
191 | volatile int i = gSP.numLights; |
192 | volatile int tmp = 0; |
193 | volatile void *ptr0 = &(gSP.lights[0].r); |
194 | volatile void *ptr1 = &(OGL.triangles.vertices[v].nx); |
195 | volatile void *ptr2 = result; |
196 | volatile void *ptr3 = gSP.matrix.modelView[gSP.matrix.modelViewi]; |
197 | asm volatile ( |
198 | "vld1.32 {d0, d1}, [%1] \n\t" //q0 = {x,y,z,w} |
199 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
200 | "vld1.32 {d2, d3}, [%1] \n\t" //q1 = {x,y,z,w} |
201 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
202 | "vld1.32 {d4, d5}, [%1] \n\t" //q2 = {x,y,z,w} |
203 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
204 | "vld1.32 {d6, d7}, [%1] \n\t" //q3 = {x,y,z,w} |
205 | "sub %1, %1, %3 \n\t" //q0 = {x,y,z,w} |
206 | |
207 | "vld1.32 {d18, d19}, [%0]! \n\t" //q9 = m |
208 | "vld1.32 {d20, d21}, [%0]! \n\t" //q10 = m+16 |
209 | "vld1.32 {d22, d23}, [%0] \n\t" //q11 = m+32 |
210 | |
211 | "vmul.f32 q12, q9, d0[0] \n\t" //q12 = q9*d0[0] |
212 | "vmul.f32 q13, q9, d2[0] \n\t" //q13 = q9*d2[0] |
213 | "vmul.f32 q14, q9, d4[0] \n\t" //q14 = q9*d4[0] |
214 | "vmul.f32 q15, q9, d6[0] \n\t" //q15 = q9*d6[0] |
215 | |
216 | "vmla.f32 q12, q10, d0[1] \n\t" //q12 += q10*q0[1] |
217 | "vmla.f32 q13, q10, d2[1] \n\t" //q13 += q10*q2[1] |
218 | "vmla.f32 q14, q10, d4[1] \n\t" //q14 += q10*q4[1] |
219 | "vmla.f32 q15, q10, d6[1] \n\t" //q15 += q10*q6[1] |
220 | |
221 | "vmla.f32 q12, q11, d1[0] \n\t" //q12 += q11*d1[0] |
222 | "vmla.f32 q13, q11, d3[0] \n\t" //q13 += q11*d3[0] |
223 | "vmla.f32 q14, q11, d5[0] \n\t" //q14 += q11*d5[0] |
224 | "vmla.f32 q15, q11, d7[0] \n\t" //q15 += q11*d7[0] |
225 | |
226 | "vmul.f32 q0, q12, q12 \n\t" //q0 = q12*q12 |
227 | "vmul.f32 q1, q13, q13 \n\t" //q1 = q13*q13 |
228 | "vmul.f32 q2, q14, q14 \n\t" //q2 = q14*q14 |
229 | "vmul.f32 q3, q15, q15 \n\t" //q3 = q15*q15 |
230 | |
231 | "vpadd.f32 d0, d0 \n\t" //d0[0] = d0[0] + d0[1] |
232 | "vpadd.f32 d2, d2 \n\t" //d2[0] = d2[0] + d2[1] |
233 | "vpadd.f32 d4, d4 \n\t" //d4[0] = d4[0] + d4[1] |
234 | "vpadd.f32 d6, d6 \n\t" //d6[0] = d6[0] + d6[1] |
235 | |
236 | "vmov.f32 s1, s2 \n\t" //d0[1] = d1[0] |
237 | "vmov.f32 s5, s6 \n\t" //d2[1] = d3[0] |
238 | "vmov.f32 s9, s10 \n\t" //d4[1] = d5[0] |
239 | "vmov.f32 s13, s14 \n\t" //d6[1] = d7[0] |
240 | |
241 | "vpadd.f32 d0, d0, d2 \n\t" //d0 = {d0[0] + d0[1], d2[0] + d2[1]} |
242 | "vpadd.f32 d1, d4, d6 \n\t" //d1 = {d4[0] + d4[1], d6[0] + d6[1]} |
243 | |
244 | "vmov.f32 q1, q0 \n\t" //q1 = q0 |
245 | "vrsqrte.f32 q0, q0 \n\t" //q0 = ~ 1.0 / sqrt(q0) |
246 | "vmul.f32 q2, q0, q1 \n\t" //q2 = q0 * q1 |
247 | "vrsqrts.f32 q3, q2, q0 \n\t" //q3 = (3 - q0 * q2) / 2 |
248 | "vmul.f32 q0, q0, q3 \n\t" //q0 = q0 * q3 |
249 | "vmul.f32 q2, q0, q1 \n\t" //q2 = q0 * q1 |
250 | "vrsqrts.f32 q3, q2, q0 \n\t" //q3 = (3 - q0 * q2) / 2 |
251 | "vmul.f32 q0, q0, q3 \n\t" //q0 = q0 * q3 |
252 | |
253 | "vmul.f32 q3, q15, d1[1] \n\t" //q3 = q15*d1[1] |
254 | "vmul.f32 q2, q14, d1[0] \n\t" //q2 = q14*d1[0] |
255 | "vmul.f32 q1, q13, d0[1] \n\t" //q1 = q13*d0[1] |
256 | "vmul.f32 q0, q12, d0[0] \n\t" //q0 = q12*d0[0] |
257 | |
258 | "vst1.32 {d0, d1}, [%1] \n\t" //d0={nx,ny,nz,pad} |
259 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
260 | "vst1.32 {d2, d3}, [%1] \n\t" //d2={nx,ny,nz,pad} |
261 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
262 | "vst1.32 {d4, d5}, [%1] \n\t" //d4={nx,ny,nz,pad} |
263 | "add %1, %1, %2 \n\t" //q0 = {x,y,z,w} |
264 | "vst1.32 {d6, d7}, [%1] \n\t" //d6={nx,ny,nz,pad} |
265 | |
266 | : "+&r"(ptr3), "+&r"(ptr1) |
267 | : "I"(sizeof(SPVertex)), "I"(3 * sizeof(SPVertex)) |
268 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
269 | "d16","d17", "d18","d19", "d20", "d21", "d22", |
270 | "d23", "d24", "d25", "d26", "d27", "d28", "d29", |
271 | "d30", "d31", "memory" |
272 | ); |
273 | asm volatile ( |
274 | |
275 | "mov %0, %5 \n\t" //r0=sizeof(light) |
276 | "mla %0, %1, %0, %2 \n\t" //r0=r1*r0+r2 |
277 | |
278 | "vmov.f32 q8, q0 \n\t" //q8=q0 |
279 | "vmov.f32 q9, q1 \n\t" //q9=q1 |
280 | "vmov.f32 q10, q2 \n\t" //q10=q2 |
281 | "vmov.f32 q11, q3 \n\t" //q11=q3 |
282 | |
283 | "vld1.32 {d0}, [%0] \n\t" //d0={r,g} |
284 | "flds s2, [%0, #8] \n\t" //d1[0]={b} |
285 | "vmov.f32 q1, q0 \n\t" //q1=q0 |
286 | "vmov.f32 q2, q0 \n\t" //q2=q0 |
287 | "vmov.f32 q3, q0 \n\t" //q3=q0 |
288 | |
289 | "vmov.f32 q15, #0.0 \n\t" //q15=0 |
290 | "vdup.f32 q15, d30[0] \n\t" //q15=d30[0] |
291 | |
292 | "cmp %1, #0 \n\t" // |
293 | "beq 2f \n\t" //(r1==0) goto 2 |
294 | |
295 | "1: \n\t" // |
296 | "vld1.32 {d8}, [%2]! \n\t" //d8={r,g} |
297 | "flds s18, [%2] \n\t" //q9[0]={b} |
298 | "add %2, %2, #4 \n\t" //q9[0]={b} |
299 | "vld1.32 {d10}, [%2]! \n\t" //d10={x,y} |
300 | "flds s22, [%2] \n\t" //d11[0]={z} |
301 | "add %2, %2, #4 \n\t" //q9[0]={b} |
302 | |
303 | "vmov.f32 q13, q5 \n\t" //q13 = q5 |
304 | "vmov.f32 q12, q4 \n\t" //q12 = q4 |
305 | |
306 | "vmul.f32 q4, q8, q13 \n\t" //q4 = q8*q13 |
307 | "vmul.f32 q5, q9, q13 \n\t" //q5 = q9*q13 |
308 | "vmul.f32 q6, q10, q13 \n\t" //q6 = q10*q13 |
309 | "vmul.f32 q7, q11, q13 \n\t" //q7 = q11*q13 |
310 | |
311 | "vpadd.f32 d8, d8 \n\t" //d8[0] = d8[0] + d8[1] |
312 | "vpadd.f32 d10, d10 \n\t" //d10[0] = d10[0] + d10[1] |
313 | "vpadd.f32 d12, d12 \n\t" //d12[0] = d12[0] + d12[1] |
314 | "vpadd.f32 d14, d14 \n\t" //d14[0] = d14[0] + d14[1] |
315 | |
316 | "vmov.f32 s17, s18 \n\t" //d8[1] = d9[0] |
317 | "vmov.f32 s21, s22 \n\t" //d10[1] = d11[0] |
318 | "vmov.f32 s25, s26 \n\t" //d12[1] = d13[0] |
319 | "vmov.f32 s29, s30 \n\t" //d14[1] = d15[0] |
320 | |
321 | "vpadd.f32 d8, d8, d10 \n\t" //d8 = {d8[0] + d8[1], d10[0] + d10[1]} |
322 | "vpadd.f32 d9, d12, d14 \n\t" //d9 = {d12[0] + d12[1], d14[0] + d14[1]} |
323 | |
324 | "vmax.f32 q4, q4, q15 \n\t" //q4=max(q4, 0) |
325 | |
326 | "vmla.f32 q0, q12, d8[0] \n\t" //q0 += |
327 | "vmla.f32 q1, q12, d8[1] \n\t" //d1 = {d4[0] + d4[1], d6[0] + d6[1]} |
328 | "vmla.f32 q2, q12, d9[0] \n\t" //d1 = {d4[0] + d4[1], d6[0] + d6[1]} |
329 | "vmla.f32 q3, q12, d9[1] \n\t" //d1 = {d4[0] + d4[1], d6[0] + d6[1]} |
330 | |
331 | "subs %1, %1, #1 \n\t" //r1=r1 - 1 |
332 | "bne 1b \n\t" //(r1!=0) goto 1 |
333 | |
334 | "2: \n\t" // |
335 | |
336 | "vmov.f32 q4, #1.0 \n\t" // |
337 | "vmin.f32 q0, q0, q4 \n\t" // |
338 | "vmin.f32 q1, q1, q4 \n\t" // |
339 | "vmin.f32 q2, q2, q4 \n\t" // |
340 | "vmin.f32 q3, q3, q4 \n\t" // |
341 | "vst1.32 {d0, d1}, [%4]! \n\t" // |
342 | "vst1.32 {d2, d3}, [%4]! \n\t" // |
343 | "vst1.32 {d4, d5}, [%4]! \n\t" // |
344 | "vst1.32 {d6, d7}, [%4] \n\t" // |
345 | |
346 | : "+&r"(tmp), "+&r"(i), "+&r"(ptr0), "+&r"(ptr1), "+&r"(ptr2) |
347 | : "I"(sizeof(SPLight)) |
348 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
349 | "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", |
350 | "d16","d17", "d18","d19", "d20", "d21", "d22", "d23", |
351 | "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", |
352 | "memory", "cc" |
353 | ); |
354 | OGL.triangles.vertices[v].r = result[0]; |
355 | OGL.triangles.vertices[v].g = result[1]; |
356 | OGL.triangles.vertices[v].b = result[2]; |
357 | OGL.triangles.vertices[v+1].r = result[4]; |
358 | OGL.triangles.vertices[v+1].g = result[5]; |
359 | OGL.triangles.vertices[v+1].b = result[6]; |
360 | OGL.triangles.vertices[v+2].r = result[8]; |
361 | OGL.triangles.vertices[v+2].g = result[9]; |
362 | OGL.triangles.vertices[v+2].b = result[10]; |
363 | OGL.triangles.vertices[v+3].r = result[12]; |
364 | OGL.triangles.vertices[v+3].g = result[13]; |
365 | OGL.triangles.vertices[v+3].b = result[14]; |
366 | } |
367 | |
368 | static void gSPBillboardVertex4NEON(u32 v) |
369 | { |
370 | int i = 0; |
371 | |
372 | #ifdef __TRIBUFFER_OPT |
373 | i = OGL.triangles.indexmap[0]; |
374 | #endif |
375 | |
376 | void *ptr0 = (void*)&OGL.triangles.vertices[v].x; |
377 | void *ptr1 = (void*)&OGL.triangles.vertices[i].x; |
378 | asm volatile ( |
379 | |
380 | "vld1.32 {d0, d1}, [%0] \n\t" //q0 = {x,y,z,w} |
381 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
382 | "vld1.32 {d2, d3}, [%0] \n\t" //q1 = {x,y,z,w} |
383 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
384 | "vld1.32 {d4, d5}, [%0] \n\t" //q2 = {x,y,z,w} |
385 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
386 | "vld1.32 {d6, d7}, [%0] \n\t" //q3 = {x,y,z,w} |
387 | "sub %0, %0, %3 \n\t" //q0 = {x,y,z,w} |
388 | |
389 | "vld1.32 {d16, d17}, [%1] \n\t" //q2={x1,y1,z1,w1} |
390 | "vadd.f32 q0, q0, q8 \n\t" //q1=q1+q1 |
391 | "vadd.f32 q1, q1, q8 \n\t" //q1=q1+q1 |
392 | "vadd.f32 q2, q2, q8 \n\t" //q1=q1+q1 |
393 | "vadd.f32 q3, q3, q8 \n\t" //q1=q1+q1 |
394 | "vst1.32 {d0, d1}, [%0] \n\t" // |
395 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
396 | "vst1.32 {d2, d3}, [%0] \n\t" // |
397 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
398 | "vst1.32 {d4, d5}, [%0] \n\t" // |
399 | "add %0, %0, %2 \n\t" //q0 = {x,y,z,w} |
400 | "vst1.32 {d6, d7}, [%0] \n\t" // |
401 | : "+&r"(ptr0), "+&r"(ptr1) |
402 | : "I"(sizeof(SPVertex)), "I"(3 * sizeof(SPVertex)) |
403 | : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
404 | "d16", "d17", "memory" |
405 | ); |
406 | } |
407 | #endif |
408 | |
409 | static void gSPTransformVertexNEON(float vtx[4], float mtx[4][4]) |
410 | { |
411 | //optimised using cycle analyser |
412 | #if 0 |
413 | volatile int tmp0, tmp1; |
414 | asm volatile ( |
415 | "vld1.32 {d0, d1}, [%3, :128] \n\t" //q0 = *v |
416 | "add %1, %0, #16 \n\t" //r1=r0+16 |
417 | "vld1.32 {d18, d19}, [%0, :128] \n\t" //q9 = m |
418 | "add %2, %0, #32 \n\t" //r2=r0+32 |
419 | "vld1.32 {d20, d21}, [%1, :128] \n\t" //q10 = m+4 |
420 | "add %0, %0, #48 \n\t" //r0=r0+48 |
421 | "vld1.32 {d22, d23}, [%2, :128] \n\t" //q11 = m+8 |
422 | "vld1.32 {d24, d25}, [%0, :128] \n\t" //q12 = m+12 |
423 | |
424 | "vmla.f32 q12, q9, d0[0] \n\t" //q12 = q12 + q9*Q0[0] |
425 | "vmul.f32 q13, q10, d0[1] \n\t" //q13 = Q10*Q0[1] |
426 | "vmul.f32 q14, q11, d1[0] \n\t" //q14 = Q11*Q0[2] |
427 | "vadd.f32 q12, q12, q13 \n\t" //q12 = q12 + q14 |
428 | "vadd.f32 q12, q12, q14 \n\t" //Q12 = q12 + q15 |
429 | |
430 | "vst1.32 {d24, d25}, [%3, :128] \n\t" //*v = q12 |
431 | |
432 | : "+r"(mtx), "+r"(tmp0), "+r"(tmp1) : "r"(vtx) |
433 | : "d0", "d1", "d18","d19","d20","d21","d22","d23","d24","d25", |
434 | "d26", "d27", "memory" |
435 | ); |
436 | |
437 | #else |
438 | asm volatile ( |
439 | "vld1.32 {d0, d1}, [%1] \n\t" //d8 = {x,y} |
440 | "vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m |
441 | "vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4 |
442 | "vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8 |
443 | "vld1.32 {d24, d25}, [%0] \n\t" //Q4 = m+12 |
444 | |
445 | "vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0] |
446 | "vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1] |
447 | "vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2] |
448 | "vadd.f32 q13, q13, q12 \n\t" //Q5 += Q3*Q0[3] |
449 | "vst1.32 {d26, d27}, [%1] \n\t" //Q4 = m+12 |
450 | |
451 | : "+r"(mtx) : "r"(vtx) |
452 | : "d0", "d1", "d18","d19","d20","d21","d22","d23","d24","d25", |
453 | "d26", "d27", "memory" |
454 | ); |
455 | #endif |
456 | } |
457 | |
458 | static void gSPLightVertexNEON(u32 v) |
459 | { |
460 | volatile float result[4]; |
461 | |
462 | volatile int tmp = 0; |
463 | volatile int i = gSP.numLights; |
464 | volatile void *ptr0 = &gSP.lights[0].r; |
465 | volatile void *ptr1 = &OGL.triangles.vertices[v].nx; |
466 | volatile void *ptr2 = result;; |
467 | volatile void *ptr3 = gSP.matrix.modelView[gSP.matrix.modelViewi]; |
468 | |
469 | asm volatile ( |
470 | "vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v |
471 | "vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m |
472 | "vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4 |
473 | "vld1.32 {d22, d23}, [%0] \n\t" //Q3 = m+8 |
474 | |
475 | "vmul.f32 q2, q9, d0[0] \n\t" //q2 = q9*Q0[0] |
476 | "vmla.f32 q2, q10, d0[1] \n\t" //Q5 += Q1*Q0[1] |
477 | "vmla.f32 q2, q11, d1[0] \n\t" //Q5 += Q2*Q0[2] |
478 | |
479 | "vmul.f32 d0, d4, d4 \n\t" //d0 = d0*d0 |
480 | "vpadd.f32 d0, d0, d0 \n\t" //d0 = d[0] + d[1] |
481 | "vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5 |
482 | |
483 | "vmov.f32 d1, d0 \n\t" //d1 = d0 |
484 | "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) |
485 | "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 |
486 | "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 |
487 | "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 |
488 | "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 |
489 | "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d3) / 2 |
490 | "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 |
491 | |
492 | "vmul.f32 q1, q2, d0[0] \n\t" //q1 = d2*d4 |
493 | |
494 | "vst1.32 {d2, d3}, [%1] \n\t" //d0={nx,ny,nz,pad} |
495 | |
496 | : "+&r"(ptr3): "r"(ptr1) |
497 | : "d0","d1","d2","d3","d18","d19","d20","d21","d22", "d23", "memory" |
498 | ); |
499 | |
500 | asm volatile ( |
501 | "mov %0, #24 \n\t" //r0=24 |
502 | "mla %0, %1, %0, %2 \n\t" //r0=r1*r0+r2 |
503 | |
504 | "vld1.32 {d0}, [%0]! \n\t" //d0={r,g} |
505 | "flds s2, [%0] \n\t" //d1[0]={b} |
506 | "cmp %0, #0 \n\t" // |
507 | "beq 2f \n\t" //(r1==0) goto 2 |
508 | |
509 | "1: \n\t" // |
510 | "vld1.32 {d4}, [%2]! \n\t" //d4={r,g} |
511 | "flds s10, [%2] \n\t" //q5[0]={b} |
512 | "add %2, %2, #4 \n\t" //r2+=4 |
513 | "vld1.32 {d6}, [%2]! \n\t" //d6={x,y} |
514 | "flds s14, [%2] \n\t" //d7[0]={z} |
515 | "add %2, %2, #4 \n\t" //r2+=4 |
516 | "vmul.f32 d6, d2, d6 \n\t" //d6=d2*d6 |
517 | "vpadd.f32 d6, d6 \n\t" //d6=d6[0]+d6[1] |
518 | "vmla.f32 d6, d3, d7 \n\t" //d6=d6+d3*d7 |
519 | "vmov.f32 d7, #0.0 \n\t" //d7=0 |
520 | "vmax.f32 d6, d6, d7 \n\t" //d6=max(d6, d7) |
521 | "vmla.f32 q0, q2, d6[0] \n\t" //q0=q0+q2*d6[0] |
522 | "sub %1, %1, #1 \n\t" //r0=r0-1 |
523 | "cmp %1, #0 \n\t" //r0=r0-1 |
524 | "bgt 1b \n\t" //(r1!=0) ? goto 1 |
525 | "b 2f \n\t" //(r1!=0) ? goto 1 |
526 | "2: \n\t" // |
527 | "vmov.f32 q1, #1.0 \n\t" // |
528 | "vmin.f32 q0, q0, q1 \n\t" // |
529 | "vst1.32 {d0, d1}, [%3] \n\t" // |
530 | |
531 | : "+&r"(tmp), "+&r"(i), "+&r"(ptr0), "+&r"(ptr2) |
532 | :: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
533 | "d16", "memory", "cc" |
534 | ); |
535 | OGL.triangles.vertices[v].r = result[0]; |
536 | OGL.triangles.vertices[v].g = result[1]; |
537 | OGL.triangles.vertices[v].b = result[2]; |
538 | } |
539 | |
540 | static void gSPBillboardVertexNEON(u32 v, u32 i) |
541 | { |
542 | asm volatile ( |
543 | "vld1.32 {d2, d3}, [%0] \n\t" //q1={x0,y0, z0, w0} |
544 | "vld1.32 {d4, d5}, [%1] \n\t" //q2={x1,y1, z1, w1} |
545 | "vadd.f32 q1, q1, q2 \n\t" //q1=q1+q1 |
546 | "vst1.32 {d2, d3}, [%0] \n\t" // |
547 | :: "r"(&OGL.triangles.vertices[v].x), "r"(&OGL.triangles.vertices[i].x) |
548 | : "d2", "d3", "d4", "d5", "memory" |
549 | ); |
550 | } |
551 | |
552 | void gSPInitNeon() |
553 | { |
554 | #ifdef __VEC4_OPT |
555 | gSPTransformVertex4 = gSPTransformVertex4NEON; |
556 | gSPTransformNormal4 = gSPTransformNormal4NEON; |
557 | gSPLightVertex4 = gSPLightVertex4NEON; |
558 | gSPBillboardVertex4 = gSPBillboardVertex4NEON; |
559 | #endif |
560 | gSPTransformVertex = gSPTransformVertexNEON; |
561 | gSPLightVertex = gSPLightVertexNEON; |
562 | gSPBillboardVertex = gSPBillboardVertexNEON; |
563 | } |