/*
  TMHal.h, Copyright  (c) by Silvio Dragone & David Reist,
  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.
*/

#ifndef __TMHAL_H
#define __TMHAL_H

#include "tm-include.h"
#include "cpu.h"
#include "Exception.h"
#include "SupportSA1100.h"

#define MAXNBOFINTERRUPTS    8
#define MAXNBOFEXCEPTIONS    7

/* THREADRETURNADDR is defined inside TMHal.h to allow portability.... :-) */
#define THREADRETURNADDR     0

#define STATUS_INT_ENABLE_KERNEL_PREV (SYSTEM_MODE)
#define STATUS_INT_ENABLE_USER_PREV   (USER_MODE)

/* Processor dependent thread information */
typedef struct ProcContext_t
{
  Register argument[4];          /* R0 - R3, argument and result (a0 - a3) */
  Register saveGPR[6];           /* R4 - R9, callee saves (v0 - v5) */
  Register stackLimit;           /* R10, stack limit (sl/v7) */
  Register framePointer;         /* R11, frame pointer (fp) */
  Register scratchRegister;      /* R12, scratch register (ip) */
  Register stackPointer;         /* R13, stack pointer (sp) */
  Register linkRegister;         /* R14, return address (lr) */
  Register programCounter;       /* PC, program counter */
  Register statusRegister;       /* CPSR, current prg status register */
}
ProcContext;

/* Saving and restoring current thread context (assembler procedures) */
void saveContext(ProcContextPtr contextPtr);
void restoreContext(ProcContextPtr contextPtr);
void excRestoreContext(ProcContextPtr contextPtr);
void disableInterrupts(void);
void enableInterrupts(void);

/* operations on the thread context are machine dependent and
 * encapsulated in the following functions. On CISC machines
 * most of these ops must be implemented using the current SP of
 * the context.
 */
void tmSetReturnValue(ProcContextPtr contextPtr, Register value);
void tmSetStackPointer(ProcContextPtr contextPtr, Register value);
void tmSetReturnAddress(ProcContextPtr contextPtr, Register value);
void tmSetProgramCounter(ProcContextPtr contextPtr, Register value);
void tmSetStatusRegister(ProcContextPtr contextPtr, Register value);
void tmSetFramePointer(ProcContextPtr contextPtr, Register value);
void tmSetArgument0(ProcContextPtr contextPtr, Register value);
void tmSetArgument1(ProcContextPtr contextPtr, Register value);
void tmSetMachineDependentRegisters(ProcContextPtr contextPtr, AddressSpace space);

void enableInterruptInContext( InterruptId intId, ProcContextPtr contextPtr);
void disableInterruptInContext( InterruptId intId, ProcContextPtr contextPtr);
void enableAllInterruptsInContext( ProcContextPtr contextPtr);

/* Copies the exception vector table to the right position. */
void tmInstallExceptionCode(void);

/* Syscall exception handler (Software interrupt handler) */
void syscallExceptionHandler(ThreadId threadId);

/* Automatic exit of a thread when stack underflow occurs */
void automaticThreadExit(void);
void endAutomaticThreadExit(void);

void ExceptionVectorTable(void);
void ExceptionAddressTable(void);

void msgAdjust(ThreadPtr pFromOrToThread, Message *msg, Boolean ToKernel);

void powerSaver(void);

void tmAdjustMachineDependentRegisters(ProcContextPtr contextPtr, AddressSpace space);

void moveMessageToPD(Thread* threadPtr, Message* msgPtr, Message* destPtr);


#endif
