//*****************************************************************************
// SatMemTst
// =========
// Simon Moore, May 2010
//
// This (rather hacky) code tests out the Saturation-Add with memory test
// custom instruction.  Saturation-Add operations can be performed on
// values held in NIOS registers or in custom registers within the custom
// instruction block.  Similarly, the destination register can be a NIOS
// register or a custom register.
// Please remember that this design is simply illustrative rather than being
// directly useful.
//*****************************************************************************

#include <stdio.h>
#include <system.h>

void tst_sataddmem()
{
	int a,b;
	int j,r,k;
	int aval[4];
	int correct[16];
	aval[0] = 3;
	aval[1] = 0;
	aval[2] = -1;
	aval[3] = -3;
	printf("Test direct satuation add computation\n");
	for(j=k=0; j<4; j++) {
		a=aval[j];
		for(b=-3; b<=6; b+=3) {
			r=ALT_CI_MKCUSTOMINSTRUCTION_SATURATIONADDMEM_INST(a,b);
			printf("%d+%d=%d   0x%08x+0x%08x=0x%08x\n",a,b,r,a,b,r);
			correct[k]=r;
			k++;
		}
	}

	printf("\nTest saturation add memory\n");
	b=0;
	a=3;
	// write values
	a++; asm volatile ( "custom 0, c0, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a++; asm volatile ( "custom 0, c1, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a++; asm volatile ( "custom 0, c2, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a++; asm volatile ( "custom 0, c3, %0, %1" : /* no output */ : "r" (a), "r" (b) );

	// read back values
	asm volatile ( "custom 0, %0, %1, c3" : "=r" (a) : "r" (b) );	printf("read=%d\n",a);
	asm volatile ( "custom 0, %0, %1, c2" : "=r" (a) : "r" (b) );	printf("read=%d\n",a);
	asm volatile ( "custom 0, %0, %1, c1" : "=r" (a) : "r" (b) );	printf("read=%d\n",a);
	asm volatile ( "custom 0, %0, %1, c0" : "=r" (a) : "r" (b) );	printf("read=%d\n",a);

	printf("\nTest saturation add via memory\n");
	b=0;
	j=0;
	// write values
	a=aval[j]; j++; asm volatile ( "custom 0, c0, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a=aval[j]; j++; asm volatile ( "custom 0, c1, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a=aval[j]; j++; asm volatile ( "custom 0, c2, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	a=aval[j]; j++; asm volatile ( "custom 0, c3, %0, %1" : /* no output */ : "r" (a), "r" (b) );

	a=0;
	b=-3; asm volatile ( "custom 0, c4, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	b+=3; asm volatile ( "custom 0, c5, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	b+=3; asm volatile ( "custom 0, c6, %0, %1" : /* no output */ : "r" (a), "r" (b) );
	b+=3; asm volatile ( "custom 0, c7, %0, %1" : /* no output */ : "r" (a), "r" (b) );

#define printresults printf("read = %d = 0x%08x %s (expected %d)\n",a,a,a==correct[k] ? "PASS": "FAIL",correct[k]);
	// read back values
	k=0; asm volatile ( "custom 0, %0, c0, c4" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c0, c5" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c0, c6" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c0, c7" : "=r" (a) );	printresults;

	k++; asm volatile ( "custom 0, %0, c1, c4" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c1, c5" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c1, c6" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c1, c7" : "=r" (a) );	printresults;

	k++; asm volatile ( "custom 0, %0, c2, c4" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c2, c5" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c2, c6" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c2, c7" : "=r" (a) );	printresults;

	k++; asm volatile ( "custom 0, %0, c3, c4" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c3, c5" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c3, c6" : "=r" (a) );	printresults;
	k++; asm volatile ( "custom 0, %0, c3, c7" : "=r" (a) );	printresults;
}

int main()
{
  printf("The Start\n");

  tst_sataddmem();

  printf("The End\n");
  return 0;
}
