sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
main.c
1#include <stdio.h>
2#include <string.h>
3#include <kernel.h>
4
5#include <stdint.h>
6#include <string.h>
7
8extern int kputs(char *s);
9
10/* A program must never return from main on the rig: that reboots the console. */
11static int rig_failed;
12static int rig_kputs(char *s) {
13 if (strstr(s, ": FAIL")) rig_failed = 1;
14 printf("%s", s);
15 return kputs(s);
16}
17#define kputs rig_kputs
18
19#define NOINL __attribute__((noinline))
20
21static volatile uint32_t vtbl[] = {
22 0x00000000u, 0x80000000u, 0x3f800000u, 0xbf800000u, 0x3f000000u, 0x40000000u,
23 0x40400000u, 0x41200000u, 0x3dcccccdu, 0x3a83126fu, 0x1e3ce508u, 0x60ad78ecu,
24 0x7f7fc99eu, 0xff7fc99eu, 0x0082ab1eu, 0x47f12065u, 0x3f800001u, 0x4b800000u,
25 0x3eaaaaaau, 0xc0f00000u, 0x42c80000u, 0x501502f9u, 0x2edbe6ffu, 0x477fe000u,
26 0xbf400000u, 0x40200000u, 0x3fc00000u, 0x47c35000u};
27#define N ((int)(sizeof(vtbl) / sizeof(vtbl[0])))
28
29static float t[64];
30
31static uint32_t h;
32static inline void mix(uint32_t v) { h = (h ^ v) * 16777619u; }
33static inline uint32_t bits(float f) { uint32_t u; memcpy(&u, &f, 4); return u; }
34
35static void hex8(uint32_t v, char *o) {
36 for (int i = 7; i >= 0; i--) { o[i] = "0123456789abcdef"[v & 15]; v >>= 4; }
37 o[8] = 0;
38}
39static void report(const char *name) {
40 char line[64];
41 int n = 0;
42 while (name[n] && n < 40) { line[n] = name[n]; n++; }
43 line[n++] = ' ';
44 hex8(h, line + n);
45 n += 8;
46 line[n++] = '\n';
47 line[n] = 0;
48 kputs(line);
49}
50#define START() (h = 2166136261u)
51
52#define BIN(NAME, EXPR) \
53 NOINL static float NAME(float a, float b) { return EXPR; }
54BIN(k_add, a + b)
55BIN(k_sub, a - b)
56BIN(k_mul, a * b)
57BIN(k_div, a / b)
58BIN(k_max, __builtin_fmaxf(a, b))
59BIN(k_min, __builtin_fminf(a, b))
60BIN(k_tmax, a > b ? a : b)
61BIN(k_tmin, a < b ? a : b)
62BIN(k_adivsqrt, a / __builtin_sqrtf(b))
63BIN(k_lerp3, a + (b - a) * 0.25f)
64BIN(k_chain, (a * b + a) * b - a / (b + 1.5f))
65BIN(k_fma, a * b + 3.0f)
66BIN(k_msub, 3.0f - a * b)
67
68#define UN(NAME, EXPR) \
69 NOINL static float NAME(float a) { return EXPR; }
70UN(k_sqrt, __builtin_sqrtf(a))
71UN(k_rsqrt, 1.0f / __builtin_sqrtf(a))
72UN(k_neg, -a)
73UN(k_abs, __builtin_fabsf(a))
74UN(k_clamp, a < 0.f ? 0.f : (a > 1.f ? 1.f : a))
75UN(k_sq, a * a)
76UN(k_cube, a * a * a)
77UN(k_half, a * 0.5f + 0x1.921f9ep+1f)
78UN(k_recip, 1.0f / a)
79
80#define CMP(NAME, EXPR) \
81 NOINL static int NAME(float a, float b) { return EXPR; }
82CMP(c_lt, a < b)
83CMP(c_le, a <= b)
84CMP(c_gt, a > b)
85CMP(c_ge, a >= b)
86CMP(c_eq, a == b)
87CMP(c_ne, a != b)
88CMP(c_nlt, !(a < b))
89CMP(c_nle, !(a <= b))
90CMP(c_ngt, !(a > b))
91CMP(c_nge, !(a >= b))
92NOINL static float s_lt(float a, float b, float x, float y) { return a < b ? x : y; }
93NOINL static float s_le(float a, float b, float x, float y) { return a <= b ? x : y; }
94NOINL static float s_gt(float a, float b, float x, float y) { return a > b ? x : y; }
95NOINL static float s_ge(float a, float b, float x, float y) { return a >= b ? x : y; }
96NOINL static float s_eq(float a, float b, float x, float y) { return a == b ? x : y; }
97NOINL static float s_ne(float a, float b, float x, float y) { return a != b ? x : y; }
98CMP(br_lt, a < b ? 1 : 2)
99CMP(br_ge, a >= b ? 1 : 2)
100CMP(br_ule, !(a > b) ? 1 : 2)
101CMP(br_ugt, !(a <= b) ? 1 : 2)
102CMP(br_ne, a != b ? 1 : 2)
103CMP(br_eq, a == b ? 1 : 2)
104
105NOINL static int f2i(float a) { return (int)a; }
106NOINL static float i2f(int a) { return (float)a; }
107NOINL static int f2i_sat(float a) { return a > 2e9f ? 2000000000 : (a < -2e9f ? -2000000000 : (int)a); }
108
109NOINL static float dot4(const float *a, const float *b) {
110 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
111}
112NOINL static void axpy(float *y, const float *x, float a, int n) {
113 for (int i = 0; i < n; i++) y[i] += a * x[i];
114}
115NOINL static void mat4vec(float *o, const float *m, const float *v) {
116 for (int r = 0; r < 4; r++)
117 o[r] = m[r] * v[0] + m[4 + r] * v[1] + m[8 + r] * v[2] + m[12 + r] * v[3];
118}
119NOINL static float sumf(const float *a, int n) {
120 float s = 0;
121 for (int i = 0; i < n; i++) s += a[i];
122 return s;
123}
124NOINL static float lensq(const float *a, int n) {
125 float s = 0;
126 for (int i = 0; i < n; i++) s += a[i] * a[i];
127 return s;
128}
129NOINL static float norm3(const float *v) {
130 float l = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
131 return l / __builtin_sqrtf(l);
132}
133
134/* integer and memory kernels: stress the scheduler, hi/lo, delay slots */
135NOINL static uint32_t crc32_(const uint8_t *p, int n) {
136 uint32_t c = 0xffffffffu;
137 for (int i = 0; i < n; i++) {
138 c ^= p[i];
139 for (int k = 0; k < 8; k++) c = (c >> 1) ^ (0xedb88320u & (0u - (c & 1)));
140 }
141 return ~c;
142}
143NOINL static int32_t imul(int32_t a, int32_t b) { return a * b; }
144NOINL static int64_t imul64(int64_t a, int64_t b) { return a * b; }
145NOINL static int32_t idiv(int32_t a, int32_t b) { return b ? a / b : 0; }
146NOINL static int32_t imod(int32_t a, int32_t b) { return b ? a % b : 0; }
147NOINL static uint32_t udiv(uint32_t a, uint32_t b) { return b ? a / b : 0; }
148NOINL static uint32_t umod(uint32_t a, uint32_t b) { return b ? a % b : 0; }
149NOINL static int64_t idiv64(int64_t a, int64_t b) { return b ? a / b : 0; }
150NOINL static uint64_t umul64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
151NOINL static void bsort(int *a, int n) {
152 for (int i = 0; i < n; i++)
153 for (int j = 0; j + 1 < n - i; j++)
154 if (a[j] > a[j + 1]) { int x = a[j]; a[j] = a[j + 1]; a[j + 1] = x; }
155}
156NOINL static int fib(int n) { return n < 2 ? n : fib(n - 1) + fib(n - 2); }
157NOINL static int sw(int x) {
158 switch (x & 7) {
159 case 0: return x * 3;
160 case 1: return x + 100;
161 case 2: return x ^ 0x5a5a;
162 case 3: return x << 3;
163 case 4: return -x;
164 case 5: return x * x;
165 case 6: return x >> 1;
166 default: return 7;
167 }
168}
169struct S { int8_t a; int16_t b; int32_t c; int64_t d; float f; uint8_t g; };
170NOINL static int64_t structs(struct S *s, int n) {
171 int64_t acc = 0;
172 for (int i = 0; i < n; i++) {
173 acc += s[i].a + s[i].b + s[i].c + s[i].d + (int)s[i].f + s[i].g;
174 s[i].c = (int32_t)acc;
175 }
176 return acc;
177}
178NOINL static void copyl(long long *d, const long long *s, int n) { for (int i = 0; i < n; i++) d[i] = s[i]; }
179NOINL static int isum(const int *a, int n) { int s = 0; for (int i = 0; i < n; i++) s += a[i]; return s; }
180
181static uint32_t rng = 12345;
182static uint32_t next(void) { rng = rng * 1664525u + 1013904223u; return rng; }
183
184#define RUN_BIN(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix(bits(K(t[i], t[j]))); report(#K); } while (0)
185#define RUN_UN(K) do { START(); for (int i = 0; i < N; i++) mix(bits(K(t[i]))); report(#K); } while (0)
186#define RUN_CMP(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix((uint32_t)K(t[i], t[j])); report(#K); } while (0)
187#define RUN_SEL(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix(bits(K(t[i], t[j], t[i], t[j]))); report(#K); } while (0)
188
189static int test_main(void) {
190 for (int i = 0; i < N; i++) { uint32_t u = vtbl[i]; memcpy(&t[i], &u, 4); }
191 for (int i = 0; i < N; i++) {
192 char nm[8] = {'t', (char)('a' + i / 10), (char)('0' + i % 10), 0};
193 START(); mix(bits(t[i])); report(nm);
194 }
195
196 RUN_BIN(k_add); RUN_BIN(k_sub); RUN_BIN(k_mul); RUN_BIN(k_div);
197 RUN_BIN(k_max); RUN_BIN(k_min); RUN_BIN(k_tmax); RUN_BIN(k_tmin);
198 RUN_BIN(k_adivsqrt); RUN_BIN(k_lerp3); RUN_BIN(k_chain); RUN_BIN(k_fma); RUN_BIN(k_msub);
199 RUN_UN(k_sqrt); RUN_UN(k_rsqrt); RUN_UN(k_neg); RUN_UN(k_abs); RUN_UN(k_clamp);
200 RUN_UN(k_sq); RUN_UN(k_cube); RUN_UN(k_half); RUN_UN(k_recip);
201 RUN_CMP(c_lt); RUN_CMP(c_le); RUN_CMP(c_gt); RUN_CMP(c_ge); RUN_CMP(c_eq); RUN_CMP(c_ne);
202 RUN_CMP(c_nlt); RUN_CMP(c_nle); RUN_CMP(c_ngt); RUN_CMP(c_nge);
203 RUN_SEL(s_lt); RUN_SEL(s_le); RUN_SEL(s_gt); RUN_SEL(s_ge); RUN_SEL(s_eq); RUN_SEL(s_ne);
204 RUN_CMP(br_lt); RUN_CMP(br_ge); RUN_CMP(br_ule); RUN_CMP(br_ugt); RUN_CMP(br_ne); RUN_CMP(br_eq);
205
206 START(); for (int i = 0; i < N; i++) mix((uint32_t)f2i_sat(t[i])); report("f2i_sat");
207 START(); for (int i = 0; i < N; i++) if (t[i] < 1e9f && t[i] > -1e9f) mix((uint32_t)f2i(t[i])); report("f2i");
208 START(); for (int i = -200; i < 200; i++) mix(bits(i2f(i * 99991))); report("i2f");
209
210 START();
211 for (int i = 0; i + 4 <= N; i++) for (int j = 0; j + 4 <= N; j++) mix(bits(dot4(t + i, t + j)));
212 report("dot4");
213 START();
214 for (int i = 0; i + 16 <= N; i++) {
215 float o[4];
216 mat4vec(o, t + i, t + (i % 8));
217 for (int r = 0; r < 4; r++) mix(bits(o[r]));
218 }
219 report("mat4vec");
220 START();
221 {
222 float y[16];
223 for (int a = 0; a < N; a++) {
224 for (int i = 0; i < 16; i++) y[i] = t[(i + a) % N];
225 axpy(y, t, t[a], 16);
226 for (int i = 0; i < 16; i++) mix(bits(y[i]));
227 }
228 }
229 report("axpy");
230 START(); for (int n = 0; n <= 16; n++) for (int i = 0; i + n <= N; i++) mix(bits(sumf(t + i, n))); report("sumf");
231 START(); for (int n = 0; n <= 16; n++) for (int i = 0; i + n <= N; i++) mix(bits(lensq(t + i, n))); report("lensq");
232 START(); for (int i = 0; i + 3 <= N; i++) mix(bits(norm3(t + i))); report("norm3");
233
234 {
235 uint8_t buf[256];
236 for (int i = 0; i < 256; i++) buf[i] = (uint8_t)next();
237 START(); for (int n = 0; n < 256; n += 7) mix(crc32_(buf, n)); report("crc32");
238 }
239 START(); for (int i = 0; i < 300; i++) { int32_t a = (int32_t)next(), b = (int32_t)next(); mix((uint32_t)imul(a, b)); } report("imul");
240 START();
241 for (int i = 0; i < 300; i++) {
242 int64_t a = ((int64_t)next() << 32) | next(), b = ((int64_t)next() << 16) | next();
243 int64_t r = imul64(a, b);
244 mix((uint32_t)r); mix((uint32_t)(r >> 32));
245 }
246 report("imul64");
247 START(); for (int i = 0; i < 300; i++) { int32_t a = (int32_t)next(), b = (int32_t)(next() >> (i & 31)); mix((uint32_t)idiv(a, b)); mix((uint32_t)imod(a, b)); } report("idivmod");
248 START(); for (int i = 0; i < 300; i++) { uint32_t a = next(), b = next() >> (i & 31); mix(udiv(a, b)); mix(umod(a, b)); } report("udivmod");
249 START();
250 for (int i = 0; i < 100; i++) {
251 int64_t a = ((int64_t)next() << 32) | next();
252 int64_t b = (int64_t)(int32_t)next() >> (i & 15);
253 int64_t r = idiv64(a, b);
254 mix((uint32_t)r); mix((uint32_t)(r >> 32));
255 }
256 report("idiv64");
257 START(); for (int i = 0; i < 100; i++) { uint64_t r = umul64(next(), next()); mix((uint32_t)r); mix((uint32_t)(r >> 32)); } report("umul64");
258 {
259 int a[64];
260 for (int i = 0; i < 64; i++) a[i] = (int)(next() >> 8);
261 bsort(a, 64);
262 START(); for (int i = 0; i < 64; i++) mix((uint32_t)a[i]); report("bsort");
263 }
264 START(); mix((uint32_t)fib(20)); report("fib");
265 START(); for (int i = 0; i < 400; i++) mix((uint32_t)sw(i * 7 + 3)); report("switch");
266 {
267 struct S s[16];
268 for (int i = 0; i < 16; i++) {
269 s[i].a = (int8_t)next(); s[i].b = (int16_t)next(); s[i].c = (int32_t)next();
270 s[i].d = ((int64_t)next() << 32) | next(); s[i].f = (float)(int16_t)next(); s[i].g = (uint8_t)next();
271 }
272 START();
273 int64_t r = structs(s, 16);
274 mix((uint32_t)r); mix((uint32_t)(r >> 32));
275 for (int i = 0; i < 16; i++) mix((uint32_t)s[i].c);
276 report("structs");
277 }
278 {
279 long long a[32], b[32];
280 for (int i = 0; i < 32; i++) a[i] = ((long long)next() << 32) | next();
281 copyl(b, a, 32);
282 START();
283 for (int i = 0; i < 32; i++) { mix((uint32_t)b[i]); mix((uint32_t)(b[i] >> 32)); }
284 report("copyl");
285 }
286 {
287 int a[64];
288 for (int i = 0; i < 64; i++) a[i] = (int)next();
289 START(); for (int n = 0; n <= 64; n++) mix((uint32_t)isum(a, n)); report("isum");
290 }
291
292 kputs("fpdiff: PASS\n");
293 return 0;
294}
295
296int main(void) {
297 int result = test_main();
298 printf("[ps2rig] exit=%d\n", (result || rig_failed) ? 1 : 0);
299 SleepThread();
300 return 0;
301}
Definition main.c:169