GLES2N64 (from mupen64plus-ae) plugin. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / gles2n64 / src / gSPNeon.cpp
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 }