/*
 * resource_index_sim.c — host-runnable index/pairing proof for DF-4029
 * (and the u32 wrap for DF-4030).
 *
 * Replicates the SET_RESOURCE loop in r600_packet3_check()
 * (sys/dev/drm/radeon/r600_cs.c:1953-2013):
 *   reads  at idx+1+(i*7)+n      (7-dword resource slots, count%7==0)
 *   writes at idx+1+(i*8)+0 and idx+1+(i*8)+2   <-- 8-dword stride (bug)
 *
 * Shows, for k slots:
 *   1. which resource slot / trailing NOP each write lands in;
 *   2. that the mandatory trailing reloc NOPs (2 dwords each, one per
 *      resource) keep the writes inside the IB (honest scoping: this is a
 *      validated-vs-executed desync inside the IB, not a past-IB write);
 *   3. the DF-4030 u32 wrap: (size + offset) computed in u32.
 */
#include <stdio.h>
#include <stdint.h>

int main(void)
{
	int k = 6;                 /* 6 VALID_BUFFER resources */
	unsigned idx = 2;          /* packet body starts after header+offset word */
	unsigned body_last = idx + 7 * k;           /* last resource dword */
	unsigned ib_len_min = body_last + 1 + 2 * k; /* +1 offset word region end + 2 dw per NOP */

	printf("SET_RESOURCE: %d buffer slots, idx=%u, body_last=%u, "
	       "min IB length (with %d trailing 2-dw NOP relocs) = %u\n\n",
	       k, idx, body_last, k, ib_len_min);

	printf(" slot | reads at (i*7)      | writes at (i*8)      | write lands in\n");
	printf("------+---------------------+----------------------+---------------------------\n");
	for (int i = 0; i < k; i++) {
		unsigned r0 = idx + 1 + 7 * i;
		unsigned w0 = idx + 1 + 8 * i, w2 = w0 + 2;
		const char *where;
		if (w2 <= idx + 7 * (i + 1))
			where = "own/later slot body (validated as data)";
		else if (w2 < ib_len_min)
			where = "trailing reloc NOP region";
		else
			where = "*** PAST IB END ***";
		printf(" %4d | %3u..%3u            | %3u, %3u             | %s\n",
		       i, r0, r0 + 6, w0, w2, where);
	}
	printf("\nmax write index = %u < min IB length %u -> writes stay inside the\n"
	       "IB, but clobber resource words the validator ALREADY checked with\n"
	       "different values (validated/executed desync) and reloc-NOP words.\n",
	       idx + 1 + 8 * (k - 1) + 2, ib_len_min);

	/* DF-4030 wrap */
	uint32_t offset = 0xFFFFFF00u, size = 0x100u;
	uint32_t sum = size + offset;          /* r600_cs.c:2002 — u32 add */
	printf("\nDF-4030: offset=0x%08x size=0x%08x -> (size+offset) as u32 = "
	       "0x%08x -> bound check `(sum > bo_size)' %s for bo_size >= 0x1000\n",
	       offset, size, sum, (sum > 0x1000) ? "FAILS" : "PASSES (wrap)");
	return 0;
}
