/*
    TMError.c, Copyright  (c) by Christian Conrad,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
	
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Threads/mips/TMError.c,v $
 	Author(s):             Christian Conrad
 	Affiliation:           ETH Zuerich, TIK
 	Version:               $Revision: 2922 $
 	Creation Date:         
 	Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
	
*/

#include "TMError.h"
#include "Threads.h"
#include "Messages.h"
#include "TMHal.h"
#include "TMScheduler.h"


static void tmReservedInstructionError(ThreadPtr currentThread);
static void tmCPunusableError(ThreadPtr currentThread);
static void tmOverflowError(ThreadPtr currentThread);
static void tmBreakpointError(ThreadPtr currentThread);


void tmInstallErrorHandlers(void)
{
  /* Vital for correct operations
   */
  //    tmSetExceptionHandler(SYSCALL, syscallExceptionHandler);
  //    tmSetExceptionHandler(HARDWARE_INT, hwExceptionHandler);
  tmSetInterruptHandler(CLOCKINT_0, tmClockHandler, NULL);

  /* Error handling for faulting threads
   */
  tmSetExceptionHandler(RES_INSTR, tmReservedInstructionError);
  tmSetExceptionHandler(CP_UNUSABLE, tmCPunusableError);
  tmSetExceptionHandler(OVERFLOW, tmOverflowError);
  tmSetExceptionHandler(BREAKPOINT, tmBreakpointError);
}


static void tmError(ThreadId currentThread, char* errorString)
{
  Message msg;

  msg.id = TM_KILL;
  msg.from = TMTHREADID;
  msg.msg.tmKill.id = currentThread;

  ERROR(errorString);
  printRegisters();

  /* immediate in-kernel delivery without syscall
   * kSend does a schedule after the message arrived
   */
  kSend(TMTHREADID, &msg);
}

static void tmReservedInstructionError(ThreadPtr currentThread)
{
  tmError(currentThread->id, "reserved instruction");
}

static void tmCPunusableError(ThreadPtr currentThread)
{
  tmError(currentThread->id, "CP unusable");
}

static void tmOverflowError(ThreadPtr currentThread)
{
  tmError(currentThread->id, "arithmetic overflow");
}

static void tmBreakpointError(ThreadPtr currentThread)
{
  tmError(currentThread->id, "breakpoint");
}

