PANDORA: Make GLES context compatible with latest driver (FB only, no X11)
[mupen64plus-pandora.git] / source / gles2n64 / src / gSPNeon.cpp
CommitLineData
34cf4058 1#include "gSP.h"
2#include "OpenGL.h"
3
4#ifdef __VEC4_OPT
5static 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
106static 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
187static 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
368static 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
409static 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
458static 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
540static 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
552void 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}