/*
 * Copyright(C) Paul und Scherer (mct.de/mct.net)
 *
 * This example demonstrates how to...
 *
 *  ... install exception handlers.
 */

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

/*
 * By default, all exception vectors are initialized with _exit,
 * so the program simply stops executing. As the vector table is
 * located in RAM (immediately after the exception entry points,
 * at the beginning of the data segment) it may be rewritten, to
 * make the vectors point to dedicated handlers.
 */
extern char _bdata;
#define UND_VEC	(*((long *)&_bdata+ 9))	// undefined instruction
#define PAB_VEC	(*((long *)&_bdata+11))	// prefetch abort
#define DAB_VEC	(*((long *)&_bdata+12))	// data abort

/*
 * Print the kind of exception and abort.
 */
static void
quit(char *msg)
{
	printf("--EXCEPTION: %s\n", msg);
	abort();
}

/*
 * Exception handlers
 *
 * Note: Stackframe depends
 * on the kind of exception.
 */
static void __attribute__((interrupt("UNDEF")))
und_eh(void)
{
	quit("Undefined instruction");
}
static void __attribute__((interrupt("ABORT")))
pab_eh(void)
{
	quit("Prefetch abort");
}
static void __attribute__((interrupt("ABORT")))
dab_eh(void)
{
	quit("Data abort");
}

/*
 * Without exceptions the program ends normally.
 * On any exception, the corresponding exception
 * handler is called.
 */
int
main(void)
{
	UND_VEC = (long)und_eh;			// set UND EH addr
	PAB_VEC = (long)pab_eh;			//     PAB EH addr
	DAB_VEC = (long)dab_eh;			//     DAB EH addr

	puts("Start...");

	/*
	 * Un-comment one of the three lines
	 * below to generate an exception...
	 *
	 * (1) Jumping to address 0 -> UND
	 * (2) Jumping to address 1 -> PAB
	 * (3) Writing to the Flash -> DAB
	 */
//	((void(*)())0)();			// (1)
//	((void(*)())1)();			// (2)
//	*(int *)0x40 = 0;			// (3)

	puts("... end.");

	return 0;
}

