7extern int kputs(
char *s);
9typedef unsigned long long u64;
10typedef unsigned int u32;
11typedef unsigned short u16;
12typedef unsigned char u8;
14static inline u32 cycles(
void)
17 __asm__ __volatile__(
"mfc0 %0, $9" :
"=r"(v) : :
"memory");
21#define BUF_BYTES (64 * 1024)
26static u32 checksum(
const void *p, u32 bytes)
31 for (u32 i = 0; i < bytes; i++)
32 h = (h ^ b[i]) * 16777619u;
36static u32 rng_state = 12345;
40 rng_state = rng_state * 1664525u + 1013904223u;
41 return rng_state >> 8;
45__attribute__((noinline))
static void bench_memcpy_mmi(
void *dst,
const void *src, u32 bytes)
50 for (u32 i = 0; i < bytes / 64; i++) {
52 "lq $8, 0(%1)\n\tlq $9, 16(%1)\n\tlq $10, 32(%1)\n\tlq $11, 48(%1)\n\t"
53 "sq $8, 0(%0)\n\tsq $9, 16(%0)\n\tsq $10, 32(%0)\n\tsq $11, 48(%0)"
56 :
"$8",
"$9",
"$10",
"$11",
"memory");
62__attribute__((noinline))
static void bench_memset_mmi(
void *dst, u32 bytes)
66 for (u32 i = 0; i < bytes / 64; i++) {
68 "pcpyld $8, %1, %1\n\tsq $8, 0(%0)\n\tsq $8, 16(%0)\n\tsq $8, 32(%0)\n\tsq $8, 48(%0)"
70 :
"r"(d),
"r"(0x0101010101010101ull)
76__attribute__((noinline))
static void bench_memcpy_libc(
void *dst,
const void *src, u32 bytes)
78 memcpy(dst, src, bytes);
81__attribute__((noinline))
static void bench_memcpy_loop(u32 *dst,
const u32 *src, u32 words)
83 for (u32 i = 0; i < words; i++)
88__attribute__((noinline))
static u32 bench_packet_build(u64 *out, u32 vertices)
92 *p++ = 0x1000000000008001ull | ((u64)vertices << 0);
94 for (u32 i = 0; i < vertices; i++) {
95 u32 x = (i * 37) & 0x1ff, y = (i * 91) & 0x1ff, z = i * 3;
96 u32 r = (i * 5) & 0xff, g = (i * 11) & 0xff, b = (i * 17) & 0xff;
98 *p++ = (u64)r | ((u64)g << 8) | ((u64)b << 16) | (0x80ull << 24);
100 *p++ = ((u64)(x << 4)) | ((u64)(y << 4) << 16) | ((u64)z << 32);
103 return (u32)(p - out);
107__attribute__((noinline))
static u32 bench_decompress(u8 *out,
const u8 *in, u32 in_len)
110 const u8 *end = in + in_len;
121 u32 len = (tag & 0x7f) + 3;
122 u32 dist = ((u32)in[0] << 8 | in[1]) + 1;
123 const u8 *m = o - dist;
130 return (u32)(o - out);
134static u32 make_compressed(u8 *out)
139 for (u32 i = 0; i < 2000; i++) {
140 u32 n = 4 + (rng() & 7);
143 for (u32 k = 0; k < n; k++)
147 u32 len = 3 + (rng() & 15), dist = rng() % 48;
149 *o++ = (u8)(0x80 | (len - 3));
150 *o++ = (u8)(dist >> 8);
155 return (u32)(o - out);
158#include "inflate_data.h"
162#define INF_FAST_BITS 9
167 u16 fast[1 << INF_FAST_BITS];
171 const u8 *in, *in_end;
175static const u16 inf_len_base[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
176 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
177static const u8 inf_len_extra[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
178 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
179static const u16 inf_dist_base[30] = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
180 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
181static const u8 inf_dist_extra[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
182 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
183static const u8 inf_clen_order[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
187 while (s->bitcnt <= 24) {
188 u32 b = s->in < s->in_end ? *s->in++ : 0;
190 s->bitbuf |= b << s->bitcnt;
200 v = s->bitbuf & ((1u << n) - 1);
208 u16 offs[16], next[16];
211 memset(h->count, 0,
sizeof(h->count));
212 memset(h->fast, 0,
sizeof(h->fast));
213 for (u32 i = 0; i < n; i++)
217 for (u32 len = 1; len < 15; len++)
218 offs[len + 1] = offs[len] + h->count[len];
219 for (u32 len = 1; len < 16; len++) {
220 code = (code + h->count[len - 1]) << 1;
221 next[len] = (u16)code;
223 for (u32 i = 0; i < n; i++) {
228 h->symbol[offs[len]++] = (u16)i;
229 if (len <= INF_FAST_BITS) {
230 u32 c = next[len], rev = 0;
232 for (u32 b = 0; b < len; b++)
233 rev |= ((c >> b) & 1) << (len - 1 - b);
234 for (u32 k = rev; k < (1u << INF_FAST_BITS); k += 1u << len)
235 h->fast[k] = (u16)((len << 9) | i);
243 u32 e, code = 0, first = 0, index = 0;
246 e = h->fast[s->bitbuf & ((1u << INF_FAST_BITS) - 1)];
248 s->bitbuf >>= e >> 9;
252 for (u32 len = 1; len < 16; len++) {
253 u32
count = h->count[len];
255 code |= s->bitbuf & 1;
258 if (code - first <
count)
259 return h->symbol[index + code - first];
261 first = (first +
count) << 1;
267static struct inf_huff inf_lit, inf_dist;
269__attribute__((noinline))
static u32 bench_inflate(u8 *out,
const u8 *in, u32 in_len)
271 struct inf_state s = {in, in + in_len, 0, 0};
278 last = inf_bits(&s, 1);
279 type = inf_bits(&s, 2);
283 s.bitbuf >>= s.bitcnt & 7;
284 s.bitcnt -= s.bitcnt & 7;
285 n = inf_bits(&s, 16);
288 *o++ = (u8)inf_bits(&s, 8);
303 bench_inflate_table(&inf_lit, lens, 288);
304 for (i = 0; i < 30; i++)
306 bench_inflate_table(&inf_dist, lens, 30);
309 u32 hlit = inf_bits(&s, 5) + 257, hdist = inf_bits(&s, 5) + 1, hclen = inf_bits(&s, 4) + 4;
313 for (i = 0; i < hclen; i++)
314 lens[inf_clen_order[i]] = (u8)inf_bits(&s, 3);
315 bench_inflate_table(&inf_lit, lens, 19);
316 for (i = 0; i < hlit + hdist;) {
317 u32 sym = inf_decode(&s, &inf_lit), rep, val = 0;
325 rep = 3 + inf_bits(&s, 2);
326 }
else if (sym == 17) {
327 rep = 3 + inf_bits(&s, 3);
329 rep = 11 + inf_bits(&s, 7);
334 bench_inflate_table(&inf_lit, lens, hlit);
335 bench_inflate_table(&inf_dist, lens + hlit, hdist);
338 u32 sym = inf_decode(&s, &inf_lit);
342 }
else if (sym == 256) {
349 len = inf_len_base[sym] + inf_bits(&s, inf_len_extra[sym]);
350 sym = inf_decode(&s, &inf_dist);
351 dist = inf_dist_base[sym] + inf_bits(&s, inf_dist_extra[sym]);
358 return (u32)(o - out);
361#define PARTICLES 1024
363static float px[PARTICLES], py[PARTICLES], pz[PARTICLES];
364static float vx[PARTICLES], vy[PARTICLES], vz[PARTICLES];
366static void init_particles(u32 seed)
369 for (u32 i = 0; i < PARTICLES; i++) {
370 px[i] = (float)(rng() & 15) - 8.0f;
371 py[i] = (float)(rng() & 15);
372 pz[i] = (float)(rng() & 15) - 8.0f;
373 vx[i] = (float)(rng() & 7) - 4.0f;
375 vz[i] = (float)(rng() & 7) - 4.0f;
379__attribute__((noinline))
static float bench_physics(u32 frames)
382 const float dt = 1.0f / 60.0f;
384 for (u32 f = 0; f < frames; f++) {
385 for (u32 i = 0; i < PARTICLES; i++) {
392 vy[i] = -vy[i] * 0.8f;
394 float d2 = px[i] * px[i] + pz[i] * pz[i];
396 float inv = 1.0f / sqrtf(d2);
397 vx[i] = -px[i] * inv;
398 vz[i] = -pz[i] * inv;
402 for (u32 i = 0; i < PARTICLES; i++)
403 energy += vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i];
410static u32 fb[FB_W * FB_H];
412__attribute__((noinline))
static void bench_raster(u32 triangles)
414 for (u32 t = 0; t < triangles; t++) {
415 int x0 = (int)(rng() % FB_W), y0 = (int)(rng() % FB_H);
416 int x1 = (int)(rng() % FB_W), y1 = (int)(rng() % FB_H);
417 int x2 = (int)(rng() % FB_W), y2 = (int)(rng() % FB_H);
419 int minx = x0 < x1 ? (x0 < x2 ? x0 : x2) : (x1 < x2 ? x1 : x2);
420 int maxx = x0 > x1 ? (x0 > x2 ? x0 : x2) : (x1 > x2 ? x1 : x2);
421 int miny = y0 < y1 ? (y0 < y2 ? y0 : y2) : (y1 < y2 ? y1 : y2);
422 int maxy = y0 > y1 ? (y0 > y2 ? y0 : y2) : (y1 > y2 ? y1 : y2);
423 int area = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0);
427 for (
int y = miny; y <= maxy; y++) {
428 for (
int x = minx; x <= maxx; x++) {
429 int w0 = (x1 - x0) * (y - y0) - (x - x0) * (y1 - y0);
430 int w1 = (x2 - x1) * (y - y1) - (x - x1) * (y2 - y1);
431 int w2 = (x0 - x2) * (y - y2) - (x - x2) * (y0 - y2);
433 if (area > 0 ? (w0 >= 0 && w1 >= 0 && w2 >= 0) : (w0 <= 0 && w1 <= 0 && w2 <= 0))
434 fb[y * FB_W + x] = color;
442static void report(
const char *name, u32 cyc, u32 sum)
444 snprintf(line,
sizeof(line),
"bench %s %u %08x\n", name, cyc, sum);
449#define TIMED_SETUP(name, setup, call, sum) \
451 u32 best = 0xffffffffu; \
452 for (int rep = 0; rep < 3; rep++) { \
457 u32 t1 = cycles() - t0; \
462 report(name, best, sum); \
465#define TIMED(name, call, sum) TIMED_SETUP(name, (void)0, call, sum)
469 static u8 comp[16384], plain[65536];
470 static u64 packets[8192];
473 for (u32 i = 0; i < BUF_BYTES; i++)
474 src_buf[i] = (u8)(i * 7 + (i >> 8));
476 TIMED(
"memcpy_mmi", bench_memcpy_mmi(dst_buf, src_buf, BUF_BYTES), checksum(dst_buf, BUF_BYTES));
477 memset(dst_buf, 0,
sizeof(dst_buf));
478 TIMED(
"memcpy_libc", bench_memcpy_libc(dst_buf, src_buf, BUF_BYTES), checksum(dst_buf, BUF_BYTES));
479 memset(dst_buf, 0,
sizeof(dst_buf));
480 TIMED(
"memcpy_loop", bench_memcpy_loop((u32 *)dst_buf, (
const u32 *)src_buf, BUF_BYTES / 4), checksum(dst_buf, BUF_BYTES));
481 TIMED(
"memset_mmi", bench_memset_mmi(dst_buf, BUF_BYTES), checksum(dst_buf, BUF_BYTES));
482 TIMED(
"packet_build", bench_packet_build(packets, 2000), checksum(packets, 2000 * 32));
484 comp_len = make_compressed(comp);
485 TIMED(
"decompress", bench_decompress(plain, comp, comp_len), checksum(plain, 4096));
486 TIMED(
"inflate", bench_inflate(plain, inflate_in,
sizeof(inflate_in)), checksum(plain, INFLATE_OUT_BYTES));
489 u32 seed = rng_state;
493 TIMED_SETUP(
"physics", init_particles(seed), e = bench_physics(30), (memcpy(&bits, &e,
sizeof(bits)), bits));
496 u32 seed = rng_state;
498 TIMED_SETUP(
"raster", rng_state = seed, bench_raster(200), checksum(fb,
sizeof(fb)));
501 kputs(
"ee-bench: PASS\n");
502 printf(
"[ps2rig] exit=0\n");
u32 count
start sector of fragmented bd/file