65816-llvm-mos/benchmarks/particles.c
2026-05-25 21:00:32 -05:00

68 lines
2.1 KiB
C

// Game-like particle system: 32 particles, i16 position + velocity in a
// 320x200 box, bounce on walls. Mimics the inner loop of an action
// game's sprite update (position += velocity + wall collision).
//
// Each particle is (px, py, vx, vy). Initial positions deterministic
// pseudo-random (so the bench is reproducible).
//
// particleStep() runs one tick. Returns a checksum of all px values
// so the result isn't dead-code-eliminated.
#define N_PARTICLES 32
#define W 320
#define H 200
static short px[N_PARTICLES];
static short py[N_PARTICLES];
static short vx[N_PARTICLES];
static short vy[N_PARTICLES];
// volatile to defeat GlobalOpt's narrowing to i1 (causes a backend
// i32-load-from-i1 isel gap — see memory: feedback_i1_load_custom.md).
static volatile short initialized = 0;
static void particleInit(void) {
// Deterministic pseudo-random init: linear congruential.
unsigned short seed = 12345;
for (short i = 0; i < N_PARTICLES; i++) {
seed = (unsigned short)(seed * 25173 + 13849);
px[i] = (short)(seed % W);
seed = (unsigned short)(seed * 25173 + 13849);
py[i] = (short)(seed % H);
seed = (unsigned short)(seed * 25173 + 13849);
vx[i] = (short)((seed % 7) - 3); // -3..+3
seed = (unsigned short)(seed * 25173 + 13849);
vy[i] = (short)((seed % 7) - 3);
if (vx[i] == 0) {
vx[i] = 1;
}
if (vy[i] == 0) {
vy[i] = 1;
}
}
initialized = 1;
}
unsigned long particleStep(void) {
if (!initialized) {
particleInit();
}
unsigned long sum = 0;
for (short i = 0; i < N_PARTICLES; i++) {
short nx = (short)(px[i] + vx[i]);
short ny = (short)(py[i] + vy[i]);
if (nx < 0 || nx >= W) {
vx[i] = (short)(-vx[i]);
nx = px[i];
}
if (ny < 0 || ny >= H) {
vy[i] = (short)(-vy[i]);
ny = py[i];
}
px[i] = nx;
py[i] = ny;
sum += (unsigned long)(unsigned short)nx;
}
return sum;
}