sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
vuhw.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (c) 2009 Lion
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <libvux.h>
12#ifndef _EE
13#include <string.h>
14#endif
15
16void Vu0IdMatrix(VU_MATRIX *m)
17{
18 Vu0ResetMatrix(m);
19}
20
21void Vu0ResetMatrix(VU_MATRIX *m)
22{
23#ifdef _EE
24 __asm__ __volatile__(
25#if __GNUC__ > 3
26 "vmr32.xyzw $vf18, $vf0 \n"
27 "sqc2 $vf0, 0x30(%0) \n"
28 "vmr32.xyzw $vf17, $vf18 \n"
29 "sqc2 $vf18, 0x20(%0) \n"
30 "vmr32.xyzw $vf16, $vf17 \n"
31 "sqc2 $vf17, 0x10(%0) \n"
32 "sqc2 $vf16, 0x00(%0) \n"
33#else
34 "vmr32.xyzw vf18, vf00 \n"
35 "sqc2 vf00, 0x30(%0) \n"
36 "vmr32.xyzw vf17, vf18 \n"
37 "sqc2 vf18, 0x20(%0) \n"
38 "vmr32.xyzw vf16, vf17 \n"
39 "sqc2 vf17, 0x10(%0) \n"
40 "sqc2 vf16, 0x00(%0) \n"
41#endif
42
43 : : "r"(m)
44 );
45#else
46 memset(m, 0, sizeof(*m));
47 m->m[3][3] = 1.0f;
48 m->m[2][2] = 1.0f;
49 m->m[1][1] = 1.0f;
50 m->m[0][0] = 1.0f;
51#endif
52}
53
54#if 0
55void VuxRotMatrix(VU_MATRIX *m, VU_VECTOR *r)
56{
57 VU_MATRIX mx,my,mz, m0;
58
59 VuxResetMatrix(m);
60 mx = my = mz = m0 = *m;
61
62
63 VuxRotMatrixX(&mx, r->x);
64 VuxRotMatrixY(&my, r->y);
65 VuxRotMatrixZ(&mz, r->z);
66
67 VuxMulMatrix(&mx, &my, &m0);
68 VuxMulMatrix(&m0, &mz, m);
69}
70#endif
71
72void Vu0TransMatrix(VU_MATRIX *m, VU_VECTOR *t)
73{
74
75#ifdef _EE
76 __asm__ __volatile__ (
77#if __GNUC__ > 3
78 "lqc2 $vf1, 0(%1) \n" // load 1 qword from 't' to vu's vf1
79 "sqc2 $vf1, 48(%0) \n" // store vf1 data in 'm' with 48 bytes offset which is m[3][0]
80#else
81 "lqc2 vf1, 0(%1) \n" // load 1 qword from 't' to vu's vf1
82 "sqc2 vf1, 48(%0) \n" // store vf1 data in 'm' with 48 bytes offset which is m[3][0]
83#endif
84
85 : : "r" (m), "r" (t)
86 );
87#else
88 *(VU_VECTOR *)(&m->m[3][0]) = *t;
89#endif
90}
91
92void Vu0TransMatrixXYZ(VU_MATRIX *m,float x, float y, float z)
93{
94 VU_VECTOR t;
95
96 t.x = x;
97 t.y = y;
98 t.z = z;
99 t.w = 1.0f;
100
101 Vu0TransMatrix(m, &t);
102}
103
104/*
105 THIS SCALE IS CROP, CLEAN IT UP ************************(99999999(****************************
106 */
107
108void Vu0ScaleMatrix(VU_MATRIX *m, VU_VECTOR *s)
109{
110
111#ifdef _EE
112 __asm__ __volatile__ (
113#if __GNUC__ > 3
114 "lqc2 $vf1, 0(%1) \n" // load 1 qword from 't' to vu's vf1
115 "lqc2 $vf10, 0(%0) \n" // load m[0][0]
116 "lqc2 $vf11, 16(%0) \n" // load m[1][0]
117 "lqc2 $vf12, 32(%0) \n" // load m[2][0]
118 // "lqc2 $vf123,48(%0) \n" // load m[3][0]
119
120 "vmulx.x $vf10, $vf10, $vf1x \n" // multiply [0][0] by s->x and store in [0][0]
121 "vmuly.y $vf11, $vf11, $vf1y \n"
122 "vmulz.z $vf12, $vf12, $vf1z \n"
123
124
125 "sqc2 $vf10, 0(%0) \n" // store v m[0][0]
126 "sqc2 $vf11, 16(%0) \n" // store v m[1][0]
127 "sqc2 $vf12, 32(%0) \n" // store v m[2][0]
128// "sqc2 $vf1, 48(%0) \n" // store v m[3][0]
129#else
130 "lqc2 vf1, 0(%1) \n" // load 1 qword from 't' to vu's vf1
131 "lqc2 vf10, 0(%0) \n" // load m[0][0]
132 "lqc2 vf11, 16(%0) \n" // load m[1][0]
133 "lqc2 vf12, 32(%0) \n" // load m[2][0]
134 // "lqc2 vf123,48(%0) \n" // load m[3][0]
135
136 "vmulx.x vf10, vf10, vf1x \n" // multiply [0][0] by s->x and store in [0][0]
137 "vmuly.y vf11, vf11, vf1y \n"
138 "vmulz.z vf12, vf12, vf1z \n"
139
140
141 "sqc2 vf10, 0(%0) \n" // store v m[0][0]
142 "sqc2 vf11, 16(%0) \n" // store v m[1][0]
143 "sqc2 vf12, 32(%0) \n" // store v m[2][0]
144// "sqc2 vf1, 48(%0) \n" // store v m[3][0]
145#endif
146
147 : : "r" (m), "r" (s)
148 );
149#else
150 m->m[0][0] *= s->x;
151 m->m[1][1] *= s->y;
152 m->m[2][2] *= s->z;
153#endif
154
155}
156
157void Vu0ScaleMatrixXYZ(VU_MATRIX *m, float x, float y, float z)
158{
159 VU_VECTOR s;
160 s.x = x;
161 s.y = y;
162 s.z = z;
163 s.w = 1.0f;
164
165 Vu0ScaleMatrix(m, &s);
166
167}
168
169void Vu0MulMatrix(VU_MATRIX *m0, VU_MATRIX *m1, VU_MATRIX *out)
170{
171
172#ifdef _EE
173 __asm__ __volatile__ (
174#if __GNUC__ > 3
175 "lqc2 $vf1, 0x00(%0) \n"
176 "lqc2 $vf2, 0x10(%0) \n"
177 "lqc2 $vf3, 0x20(%0) \n"
178 "lqc2 $vf4, 0x30(%0) \n"
179 "lqc2 $vf5, 0x00(%1) \n"
180 "lqc2 $vf6, 0x10(%1) \n"
181 "lqc2 $vf7, 0x20(%1) \n"
182 "lqc2 $vf8, 0x30(%1) \n"
183 "vmulax.xyzw $ACC, $vf5, $vf1 \n"
184 "vmadday.xyzw $ACC, $vf6, $vf1 \n"
185 "vmaddaz.xyzw $ACC, $vf7, $vf1 \n"
186 "vmaddw.xyzw $vf1, $vf8, $vf1 \n"
187 "vmulax.xyzw $ACC, $vf5, $vf2 \n"
188 "vmadday.xyzw $ACC, $vf6, $vf2 \n"
189 "vmaddaz.xyzw $ACC, $vf7, $vf2 \n"
190 "vmaddw.xyzw $vf2, $vf8, $vf2 \n"
191 "vmulax.xyzw $ACC, $vf5, $vf3 \n"
192 "vmadday.xyzw $ACC, $vf6, $vf3 \n"
193 "vmaddaz.xyzw $ACC, $vf7, $vf3 \n"
194 "vmaddw.xyzw $vf3, $vf8, $vf3 \n"
195 "vmulax.xyzw $ACC, $vf5, $vf4 \n"
196 "vmadday.xyzw $ACC, $vf6, $vf4 \n"
197 "vmaddaz.xyzw $ACC, $vf7, $vf4 \n"
198 "vmaddw.xyzw $vf4, $vf8, $vf4 \n"
199 "sqc2 $vf1, 0x00(%2) \n"
200 "sqc2 $vf2, 0x10(%2) \n"
201 "sqc2 $vf3, 0x20(%2) \n"
202 "sqc2 $vf4, 0x30(%2) \n"
203#else
204 "lqc2 vf1, 0x00(%0) \n"
205 "lqc2 vf2, 0x10(%0) \n"
206 "lqc2 vf3, 0x20(%0) \n"
207 "lqc2 vf4, 0x30(%0) \n"
208 "lqc2 vf5, 0x00(%1) \n"
209 "lqc2 vf6, 0x10(%1) \n"
210 "lqc2 vf7, 0x20(%1) \n"
211 "lqc2 vf8, 0x30(%1) \n"
212 "vmulax.xyzw ACC, vf5, vf1 \n"
213 "vmadday.xyzw ACC, vf6, vf1 \n"
214 "vmaddaz.xyzw ACC, vf7, vf1 \n"
215 "vmaddw.xyzw vf1, vf8, vf1 \n"
216 "vmulax.xyzw ACC, vf5, vf2 \n"
217 "vmadday.xyzw ACC, vf6, vf2 \n"
218 "vmaddaz.xyzw ACC, vf7, vf2 \n"
219 "vmaddw.xyzw vf2, vf8, vf2 \n"
220 "vmulax.xyzw ACC, vf5, vf3 \n"
221 "vmadday.xyzw ACC, vf6, vf3 \n"
222 "vmaddaz.xyzw ACC, vf7, vf3 \n"
223 "vmaddw.xyzw vf3, vf8, vf3 \n"
224 "vmulax.xyzw ACC, vf5, vf4 \n"
225 "vmadday.xyzw ACC, vf6, vf4 \n"
226 "vmaddaz.xyzw ACC, vf7, vf4 \n"
227 "vmaddw.xyzw vf4, vf8, vf4 \n"
228 "sqc2 vf1, 0x00(%2) \n"
229 "sqc2 vf2, 0x10(%2) \n"
230 "sqc2 vf3, 0x20(%2) \n"
231 "sqc2 vf4, 0x30(%2) \n"
232#endif
233 : : "r" (m0), "r" (m1), "r" (out)
234 );
235#else
236 memset(out, 0, sizeof(*out));
237 int i;
238 for (i = 0; i < 4; i += 1)
239 {
240 int j;
241 for (j = 0; j < 4; j += 1)
242 {
243 int k;
244 for (k = 0; k < 4; k += 1)
245 {
246 out->m[i][k] += m1->m[j][k] * m0->m[i][j];
247 }
248 }
249 }
250#endif
251}
252
253void Vu0InverseMatrix(VU_MATRIX *in, VU_MATRIX *out)
254{
255 (void)in;
256 (void)out;
257}
258
259void Vu0ApplyMatrix(VU_MATRIX *m, VU_VECTOR *v0, VU_VECTOR *out)
260{
261#ifdef _EE
262 __asm__ __volatile__(
263#if __GNUC__ > 3
264 "lqc2 $vf20, 0x00(%1) \n"
265 "lqc2 $vf16, 0x00(%0) \n"
266 "lqc2 $vf17, 0x10(%0) \n"
267 "lqc2 $vf18, 0x20(%0) \n"
268 "lqc2 $vf19, 0x30(%0) \n"
269 "vmulax.xyzw $ACC, $vf16,$vf20 \n"
270 "vmadday.xyzw $ACC, $vf17,$vf20 \n"
271 "vmaddaz.xyzw $ACC, $vf18,$vf20 \n"
272 "vmaddw.xyzw $vf20, $vf19,$vf20 \n"
273 "sqc2 $vf20,0x00(%2) \n"
274#else
275 "lqc2 vf20, 0x00(%1) \n"
276 "lqc2 vf16, 0x00(%0) \n"
277 "lqc2 vf17, 0x10(%0) \n"
278 "lqc2 vf18, 0x20(%0) \n"
279 "lqc2 vf19, 0x30(%0) \n"
280 "vmulax.xyzw ACC, vf16,vf20 \n"
281 "vmadday.xyzw ACC, vf17,vf20 \n"
282 "vmaddaz.xyzw ACC, vf18,vf20 \n"
283 "vmaddw.xyzw vf20, vf19,vf20 \n"
284 "sqc2 vf20,0x00(%2) \n"
285#endif
286 : : "r"(m), "r"(v0), "r"(out)
287 );
288#else
289 out->x = m->m[0][0] * v0->x + m->m[1][0] * v0->y + m->m[2][0] * v0->z + m->m[3][0] * v0->w;
290 out->y = m->m[0][1] * v0->x + m->m[1][1] * v0->y + m->m[2][1] * v0->z + m->m[3][1] * v0->w;
291 out->z = m->m[0][2] * v0->x + m->m[1][2] * v0->y + m->m[2][2] * v0->z + m->m[3][2] * v0->w;
292 out->w = m->m[0][3] * v0->x + m->m[1][3] * v0->y + m->m[2][3] * v0->z + m->m[3][3] * v0->w;
293#endif
294
295}
296
297void Vu0ApplyRotMatrix(VU_MATRIX *m, VU_VECTOR *v0, VU_VECTOR *out)
298{
299#ifdef _EE
300 __asm__ __volatile__(
301#if __GNUC__ > 3
302 "lqc2 $vf20, 0x00(%1) \n"
303 "lqc2 $vf16, 0x00(%0) \n"
304 "lqc2 $vf17, 0x10(%0) \n"
305 "lqc2 $vf18, 0x20(%0) \n"
306 "vmulax.xyz $ACC, $vf16,$vf20 \n"
307 "vmadday.xyz $ACC, $vf17,$vf20 \n"
308 "vmaddz.xyz $vf20, $vf18,$vf20 \n"
309 "vmulw.w $vf20, $vf0, $vf0 \n" // out->w = 1.0f
310 "sqc2 $vf20, 0x00(%2) \n" // copy result to out
311#else
312 "lqc2 vf20, 0x00(%1) \n"
313 "lqc2 vf16, 0x00(%0) \n"
314 "lqc2 vf17, 0x10(%0) \n"
315 "lqc2 vf18, 0x20(%0) \n"
316 "vmulax.xyz ACC, vf16,vf20 \n"
317 "vmadday.xyz ACC, vf17,vf20 \n"
318 "vmaddz.xyz vf20, vf18,vf20 \n"
319 "vmulw.w vf20, vf0, vf0 \n" // out->w = 1.0f
320 "sqc2 vf20, 0x00(%2) \n" // copy result to out
321#endif
322 : : "r"(m), "r"(v0), "r"(out)
323 );
324#else
325 out->x = m->m[0][0] * v0->x + m->m[1][0] * v0->y + m->m[2][0] * v0->z;
326 out->y = m->m[0][1] * v0->x + m->m[1][1] * v0->y + m->m[2][1] * v0->z;
327 out->z = m->m[0][2] * v0->x + m->m[1][2] * v0->y + m->m[2][2] * v0->z;
328 out->w = 1.0f;
329#endif
330
331}
332
333void Vu0CopyMatrix(VU_MATRIX *dest, VU_MATRIX *src)
334{
335
336#ifdef _EE
337 __asm__ __volatile__ (
338#if __GNUC__ > 3
339 "lqc2 $vf1, 0(%1) \n" // load 1 qword from ee
340 "lqc2 $vf2, 16(%1) \n" // load 1 qword from ee
341 "lqc2 $vf3, 32(%1) \n" // load 1 qword from ee
342 "lqc2 $vf4, 48(%1) \n" // load 1 qword from ee
343
344 "sqc2 $vf1, 0(%0) \n" // store 1 qword in ee
345 "sqc2 $vf2, 16(%0) \n" // store 1 qword in ee
346 "sqc2 $vf3, 32(%0) \n" // store 1 qword in ee
347 "sqc2 $vf4, 48(%0) \n" // store 1 qword in ee
348#else
349 "lqc2 vf1, 0(%1) \n" // load 1 qword from ee
350 "lqc2 vf2, 16(%1) \n" // load 1 qword from ee
351 "lqc2 vf3, 32(%1) \n" // load 1 qword from ee
352 "lqc2 vf4, 48(%1) \n" // load 1 qword from ee
353
354 "sqc2 vf1, 0(%0) \n" // store 1 qword in ee
355 "sqc2 vf2, 16(%0) \n" // store 1 qword in ee
356 "sqc2 vf3, 32(%0) \n" // store 1 qword in ee
357 "sqc2 vf4, 48(%0) \n" // store 1 qword in ee
358#endif
359
360 : : "r" (dest), "r" (src)
361 );
362#else
363 *dest = *src;
364#endif
365}
366
367float Vu0DotProduct(VU_VECTOR *v0, VU_VECTOR *v1)
368{
369 float ret=0;
370
371#ifdef _EE
372 // "r" is a GPR constraint - qmfc2 copies vf3's raw bit pattern into a
373 // GPR, it's not a real int<->float conversion. GCC tolerated binding
374 // that straight to a float-typed C variable; clang requires an
375 // integer-typed operand for "r", so the raw bits go into a temp GPR
376 // value first and get reinterpreted as float via union afterward.
377 union { unsigned int i; float f; } raw;
378 __asm__ __volatile__ (
379#if __GNUC__ > 3
380 "lqc2 $vf1, 0(%1) \n" // load 1 qword from ee
381 "lqc2 $vf2, 0(%2) \n" // load 1 qword from ee
382
383 "vmul.xyz $vf3, $vf1, $vf2 \n" // mul v0 by v1
384
385 "vaddy.x $vf3, $vf3, $vf3y \n" // add x+y and store in x
386 "vaddz.x $vf3, $vf3, $vf3z \n" // add z+x and store in x
387
388 "qmfc2 %0, $vf3 \n" // copy vector to ee reg
389#else
390 "lqc2 vf1, 0(%1) \n" // load 1 qword from ee
391 "lqc2 vf2, 0(%2) \n" // load 1 qword from ee
392
393 "vmul.xyz vf3, vf1, vf2 \n" // mul v0 by v1
394
395 "vaddy.x vf3, vf3, vf3y \n" // add x+y and store in x
396 "vaddz.x vf3, vf3, vf3z \n" // add z+x and store in x
397
398 "qmfc2 %0, vf3 \n" // copy vector to ee reg
399#endif
400 : "=r" (raw.i) : "r" (v0), "r" (v1)
401 );
402 ret = raw.f;
403#else
404 ret = (v0->x * v1->x + v0->y * v1->y + v0->z * v1->z);
405#endif
406
407 return ret;
408}