//#include <stdio.h>
#include <stdlib.h>
//#include <string.h>

int fibonacci(int f0, int f1, int *pDst, int len)
{
	int i;

	i = 0;

	pDst[i++] = f0;
	pDst[i++] = f1;

	for (; i < len; i++)
	{
		pDst[i] = pDst[i-2] + pDst[i-1];
	}

	return i;
}

#define	NUM_ELEMENTS	100
#define	NUM_RUNS		1000

typedef struct _sstat_t
{
	char v1;
	int v2;
	char v3;
	short v4;

} __attribute__ ((__packed__)) stat_t;

void test_func(stat_t *pObj)
{
	int *pReg = (int*)0x80000000;


	*pReg = (int)pObj->v4;

}

char sein(void)
{
	volatile char *pUART_stat = (char*)0x80000008;
	volatile char *pUART_data = (char*)0x80000004;

	while(!(0x10 & *pUART_stat));

	return *pUART_data;
}

void saus(char c)
{
	volatile char *pUART_stat = (char*)0x80000008;
	volatile char *pUART_data = (char*)0x80000004;

	while((0x02 & *pUART_stat) != 0);

	*pUART_data = c;
}

int sputs(char *pStr)
{
	char *start;
	start = pStr;

	while(*pStr)
		saus(*(pStr++));

	return pStr - start;
}

void print_word(int word)
{
	int i;
	unsigned char c, nibble;

	for (i=0; i < 8; i++)

	{
		nibble = (char)((word >> 28) & 0xF);
		word <<= 4;

		if (nibble < 10)
			c = nibble + '0';
		else
			c = nibble + 'A' - 10;

		saus(c);
	}

}

int main (void)
{
	int buf[NUM_ELEMENTS], result, i, j, diff, num_right_elements, num_right_runs;
	int fill, cnt, *pReg = (int*)0x80000000;
	volatile char *pUART_data = (char*)0x80000004;
	volatile char *pUART_ctrl = (char*)0x80000008;
	volatile char *pUART_baud = (char*)0x80000009;
	int testbuf[2] = {0x12345678, 0x5555aaaa};
	stat_t stat = {0x0D, 0xFF5A3FC1, 0x1E, 0x0F07};
	char msg[] = "MIPS R3000 CPU\r\nReady\r\n";
	char msg2[32];
	char baud;
	char *pPtr;
	long long product;
	int op1, op2;

	div_t div_res;

	*pUART_baud = 0x35;
	*pUART_ctrl = 0x55;

	cnt = 0;
	fill = 0xAAAAAAAA;
	memset(msg2, 0, sizeof(msg2));
	memcpy(msg2, msg, strlen(msg));

	srand(0x19701031);
	for (i=0; i < sizeof(msg2)-1; i++)
		msg2[i] = sein();

	sputs(msg2);
	test_func(&stat);

//	div_res = div(testbuf[1], testbuf[0]);
	while (1)
	{
		num_right_runs = 0;
		for (i=0; i < NUM_RUNS; i++)
		{
			for (j=0;  j < NUM_ELEMENTS; j++)
				buf[j] = fill;

			fill = ((fill ^ i) - 1) << 1;
			num_right_elements = 2;
			result = fibonacci(i, i+1, buf, NUM_ELEMENTS);
			for (j=2;  j < NUM_ELEMENTS; j++)
			{
				diff = buf[j] - buf[j-1];
				if (diff == buf[j-2])
					num_right_elements++;
			}
			if (num_right_elements == NUM_ELEMENTS)
				num_right_runs++;
		}

		if (num_right_runs == NUM_RUNS)
		{
			*pReg = cnt & 0x3FFFFFFF;
			cnt++;
		}
		else
		{
			*pReg = 0x40000000 | cnt;
			saus('X');
		}
		op1 = (int)-cnt;
		op2 = (int)((op1 & 8) << 28) ^ rand();
		product = (long long)op1 * (long long)op2;
		print_word((int)op1);
		saus(' ');
		saus('x');
		saus(' ');
		print_word((int)op2);
		saus(' ');
		saus('=');
		saus(' ');
		print_word((int)(product >> 32));
		print_word((int)product);
		saus(13);
		saus(10);

	}
	return 0;
}

