// SPDX-License-Identifier: GPL-2.0-only
/*
 * Get values of vector registers as soon as the program starts to test if
 * is properly cleaning the values before starting a new program. Vector
 * registers are caller saved, so no function calls may happen before reading
 * the values. To further ensure consistency, this file is compiled without
 * libc and without auto-vectorization.
 *
 * To be "clean" all values must be all zeroes.
 */

#define __stringify_1(x...)	#x
#define __stringify(x...)	__stringify_1(x)

int main(int argc, char **argv)
{
	char value = 0;
	unsigned long vl;

	if (argc > 2 && strcmp(argv[2], "x"))
		asm volatile (
			// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
			// vsetvli	t4, x0, e8, m1, d1
			".4byte		0b00000000000000000111111011010111\n\t"
			"mv		%[vl], t4\n\t"
			: [vl] "=r" (vl) : : "t4"
		);
	else
		asm volatile (
			".option push\n\t"
			".option arch, +v\n\t"
			"vsetvli	%[vl], x0, e8, m1, ta, ma\n\t"
			".option pop\n\t"
			: [vl] "=r" (vl)
		);

#define CHECK_VECTOR_REGISTER(register) ({					\
	for (int i = 0; i < vl; i++) {						\
		asm volatile (							\
			".option push\n\t"					\
			".option arch, +v\n\t"					\
			"vmv.x.s %0, " __stringify(register) "\n\t"		\
			"vsrl.vi " __stringify(register) ", " __stringify(register) ", 8\n\t" \
			".option pop\n\t"					\
			: "=r" (value));					\
		if (value != 0x00) {						\
			printf("Register " __stringify(register)		\
				" values not clean! value: %u\n", value);	\
			exit(-1);						\
		}								\
	}									\
})

	CHECK_VECTOR_REGISTER(v0);
	CHECK_VECTOR_REGISTER(v1);
	CHECK_VECTOR_REGISTER(v2);
	CHECK_VECTOR_REGISTER(v3);
	CHECK_VECTOR_REGISTER(v4);
	CHECK_VECTOR_REGISTER(v5);
	CHECK_VECTOR_REGISTER(v6);
	CHECK_VECTOR_REGISTER(v7);
	CHECK_VECTOR_REGISTER(v8);
	CHECK_VECTOR_REGISTER(v9);
	CHECK_VECTOR_REGISTER(v10);
	CHECK_VECTOR_REGISTER(v11);
	CHECK_VECTOR_REGISTER(v12);
	CHECK_VECTOR_REGISTER(v13);
	CHECK_VECTOR_REGISTER(v14);
	CHECK_VECTOR_REGISTER(v15);
	CHECK_VECTOR_REGISTER(v16);
	CHECK_VECTOR_REGISTER(v17);
	CHECK_VECTOR_REGISTER(v18);
	CHECK_VECTOR_REGISTER(v19);
	CHECK_VECTOR_REGISTER(v20);
	CHECK_VECTOR_REGISTER(v21);
	CHECK_VECTOR_REGISTER(v22);
	CHECK_VECTOR_REGISTER(v23);
	CHECK_VECTOR_REGISTER(v24);
	CHECK_VECTOR_REGISTER(v25);
	CHECK_VECTOR_REGISTER(v26);
	CHECK_VECTOR_REGISTER(v27);
	CHECK_VECTOR_REGISTER(v28);
	CHECK_VECTOR_REGISTER(v29);
	CHECK_VECTOR_REGISTER(v30);
	CHECK_VECTOR_REGISTER(v31);

#undef CHECK_VECTOR_REGISTER

	return 0;
}
