#include <stdlib.h>
#include <stdio.h>
#include "libsys.h"

void _exc_break(void)
{
	__asm
	(
		".set	noreorder\n"
		"break 0x9\n"
		".set	reorder\n"

	);
}

void _exc_syscall(void)
{
	__asm
	(
		".set	noreorder\n"
		"syscall\n"
		".set	reorder\n"

	);
}

void _exc_arith(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x7FFFFFFF\n"
		" addi  $t1, $t0, 2\n"
		".set	reorder\n"

	);
}

void _exc_store_err(void)
{
	volatile int *pSrc = (int*)sys_timer_sec;
	volatile int *pDst = (int*)0x40000001;

	*pDst = *pSrc;

}

void _exc_load_err(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x40000000\n"
		" li	$t1, 0x40000000\n"
		" lw 	$t1, 0($t1)\n"
		" lw 	$t0, 2($t0)\n"
		" lw 	$t1, 4($t0)\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_kaddr_err(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x80000000\n"
		" jr    $t0\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_iaddr_daddr_err(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x40000003\n"
		" li	$t1, 0x40000002\n"
		" jr    $t0\n"
		" lw 	$t1, 0($t1)\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_daddr_iaddr_err(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x40000003\n"
		" li	$t1, 0x40000002\n"
		" lw 	$t1, 0($t1)\n"
		" jr    $t0\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_iaddr_err(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x40000003\n"
		" jr    $t0\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_ri(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t0, 0x40010000\n"
		" li	$t1, 0x9c563442\n"
		" sw	$t1, 0($t0)\n"
		" jr    $t0\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_ibe(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t1, 0x10000000\n"
		" jr    $t1\n"
		"nop\n"
		".set	reorder\n"

	);

}

void _exc_dbe(void)
{
	__asm
	(
		".set	noreorder\n"
		" li	$t1, 0x10000000\n"
		" lw	$t0, 0($t1)\n"
		"nop\n"
		" jr    $t0\n"
		"nop\n"
		".set	reorder\n"

	);

}

void handler0(void)
{
	printf("Interrupt 0\n");
	interrupt_clr(0);
}

void handler1(void)
{
	printf("Interrupt 1\n");
	interrupt_clr(1);
}

int main(void)
{
	int buf[256];
	int i, sel;

	interrupt_register(0, handler0);
	interrupt_enable(0);
	interrupt_register(1, handler1);
	interrupt_enable(1);

	while(1)
	{
		printf("Welche exception möchten Sie testen?\n");
		printf(" 1 : Reserved instruction\n");
		printf(" 2 : Privileged address (BadVAddr = 0x80000000)\n");
		printf(" 3 : Arithmetic overflow\n");
		printf(" 4 : Syscall\n");
		printf(" 5 : Breakpoint\n");
		printf(" 6 : Load error on instruction (BadVAddr = 0x40000003)\n");
		printf(" 7 : Load error on data (BadVAddr = 0x40000002)\n");
		printf(" 8 : Store error on data (BadVAddr = 0x40000001)\n");
		printf(" 9 : Bus error on instruction\n");
		printf("10 : Bus error on data\n");
		printf("11 : SW-interrupt 0\n");
		printf("12 : SW-interrupt 1\n");
		printf("13 : Load error on instruction and Load error on data (BadVAddr = 0x40000003)\n");
		printf("14 : Load error on data and Load error on instruction (BadVAddr = 0x40000002)\n");

		scanf("%d", &sel);
		printf("Jetzt kommt die exception (%d)!\n", sel);

		switch(sel)
		{
			case 1:
			_exc_ri();
			break;

			case 2:
			_exc_kaddr_err();
			break;

			case 3:
			_exc_arith();
			break;

			case 4:
			_exc_syscall();
			break;

			case 5:
			_exc_break();
			break;

			case 6:
			_exc_iaddr_err();
			break;

			case 7:
			_exc_load_err();
			break;

			case 8:
			_exc_store_err();
			break;

			case 9:
			printf("IBE: Exception not implemented in current CPU!\nPush reset to restart!\n");
			_exc_ibe();
			break;

			case 10:
			printf("DBE: Exception not implemented in current CPU!\nPush reset to restart!\n");
			_exc_dbe();
			break;

			case 11:
			case 12:
			interrupt_set(sel-11);
			break;

			case 13:
			_exc_iaddr_daddr_err();
			break;

			case 14:
			_exc_daddr_iaddr_err();
			break;

			default:
			break;
		}
		sel = 0;
	}
	return 0;
}
