#ifndef __ARMI_H
#define __ARMI_H

#include <stdio.h>

/* test macros to generate and output the result of a single instruction */
#define TESTINST2(instruction, RMval, RD, RM, carryin) \
{ \
	unsigned int out; \
	unsigned int cpsr; \
\
	__asm__ volatile( \
		"movs %3,%3;" \
		"msrne cpsr_f,#(1<<29);" \
		"msreq cpsr_f,#0;" \
		"mov " #RD ",%0;" \
		"mov " #RM ",%2;" \
		instruction ";" \
		"mov %0," #RD ";" \
		"mov %2," #RM ";" \
		"mrs %1,cpsr;" \
		: "=&r" (out), "=&r" (cpsr) \
		: "r" (RMval), "r" (carryin) \
		: #RD, #RM, "cc", "memory" \
	); \
	printf("instruction '%s' rd 0x%08x rm 0x%08x, carryin %d, cpsr 0x%08x %c%c%c%c\n", \
		instruction, out, RMval, \
		carryin ? 1 : 0, \
		cpsr, \
		((1<<31) & cpsr) ? 'N' : ' ', \
		((1<<30) & cpsr) ? 'Z' : ' ', \
		((1<<29) & cpsr) ? 'C' : ' ', \
		((1<<28) & cpsr) ? 'V' : ' ' \
		); \
}

#define TESTINST3(instruction, RMval, RNval, RD, RM, RN, carryin) \
{ \
	unsigned int out; \
	unsigned int cpsr; \
\
	__asm__ volatile( \
		"movs %4,%4;" \
		"msrne cpsr_f,#(1<<29);" \
		"msreq cpsr_f,#0;" \
		"mov " #RD ",%0;" \
		"mov " #RM ",%2;" \
		"mov " #RN ",%3;" \
		instruction ";" \
		"mov %0," #RD ";" \
		"mov %2," #RM ";" \
		"mov %3," #RN ";" \
		"mrs %1,cpsr;" \
		: "=&r" (out), "=&r" (cpsr) \
		: "r" (RMval), "r" (RNval), "r" (carryin) \
		: #RD, #RM, #RN, "cc", "memory" \
	); \
	printf("instruction '%s' rd 0x%08x rm 0x%08x, rn 0x%08x, carryin %d, cpsr 0x%08x %c%c%c%c\n", \
		instruction, out, RMval, RNval, \
		carryin ? 1 : 0, \
		cpsr, \
		((1<<31) & cpsr) ? 'N' : ' ', \
		((1<<30) & cpsr) ? 'Z' : ' ', \
		((1<<29) & cpsr) ? 'C' : ' ', \
		((1<<28) & cpsr) ? 'V' : ' ' \
		); \
}

#define TESTINST4(instruction, RMval, RNval, RSval, RD, RM, RN, RS, carryin) \
{ \
	unsigned int out; \
	unsigned int cpsr; \
\
	__asm__ volatile( \
		"movs %5,%5;" \
		"msrne cpsr_f,#(1<<29);" \
		"msreq cpsr_f,#0;" \
		"mov " #RD ",%0;" \
		"mov " #RM ",%2;" \
		"mov " #RN ",%3;" \
		"mov " #RS ",%4;" \
		instruction ";" \
		"mov %0," #RD ";" \
		"mov %2," #RM ";" \
		"mov %3," #RN ";" \
		"mov %4," #RS ";" \
		"mrs %1,cpsr;" \
		: "=&r" (out), "=&r" (cpsr) \
		: "r" (RMval), "r" (RNval), "r" (RSval), "r" (carryin) \
		: #RD, #RM, #RN, #RS, "cc", "memory" \
	); \
	printf("instruction '%s' rd 0x%08x rm 0x%08x, rn 0x%08x rs 0x%08x, carryin %d, cpsr 0x%08x %c%c%c%c\n", \
		instruction, out, RMval, RNval, RSval, \
		carryin ? 1 : 0, \
		cpsr, \
		((1<<31) & cpsr) ? 'N' : ' ', \
		((1<<30) & cpsr) ? 'Z' : ' ', \
		((1<<29) & cpsr) ? 'C' : ' ', \
		((1<<28) & cpsr) ? 'V' : ' ' \
		); \
}
#endif

