////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002 Xilinx, Inc.  All rights reserved.
//
// Xilinx, Inc.
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A 
// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR 
// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE 
// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.  
// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO 
// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO 
// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 
// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE.
// 
// Date   : 2002, November.
// Author : Raj Nagarajan (rajn@xilinx.com)
// Company: Xilinx
// Group  : Emerging Software Technologies
//
// $Id :$
//
//////////////////////////////////////////////////////////////////////////////

/***************************************************************************/
/**
 * @file mblaze_asm.h
 *
 * This contains the microblaze specific macros that are called within the
 * 'c' routines. 
 ***************************************************************************/
#ifndef _MBLAZE_ASM_H
#define _MBLAZE_ASM_H

/**
 * Save all the registers in the location pointed by scontext.
 * Also save the state of the process in register r11.
 *
 * scontext is a global variable and state is a local variable.
 */
#define SAVE_CONTEXT( scontext, state )	\
	asm("add r11,r0, %0": : "d"(state)) ;	\
	asm("lwi r12, r0, scontext") ;	\
	asm("swi r1,r12, 4") ; \
	asm("swi r2,r12, 8") ; \
	asm("swi r3,r12, 12") ; \
	asm("swi r4,r12, 16") ; \
	asm("swi r5,r12, 20") ; \
	asm("swi r6,r12, 24") ; \
	asm("swi r7,r12, 28") ; \
	asm("swi r8,r12, 32") ; \
	asm("swi r9,r12, 36") ; \
	asm("swi r10,r12, 40") ; \
	asm("swi r11,r12, 44") ; \
	asm("swi r13,r12, 52") ; \
	asm("swi r14,r12, 56") ; \
	asm("swi r15,r12, 60") ; \
	asm("swi r16,r12, 64") ; \
	asm("swi r17,r12, 68") ; \
	asm("swi r18,r12, 72") ; \
	asm("swi r19,r12, 76") ; \
	asm("swi r20,r12, 80") ; \
	asm("swi r21,r12, 84") ; \
	asm("swi r22,r12, 88") ; \
	asm("swi r23,r12, 92") ; \
	asm("swi r24,r12, 96") ; \
	asm("swi r25,r12, 100") ; \
	asm("swi r26,r12, 104") ; \
	asm("swi r27,r12, 108") ; \
	asm("swi r28,r12, 112") ; \
	asm("swi r29,r12, 116") ; \
	asm("swi r30,r12, 120") ; \
	asm("swi r31,r12, 124") ; \
	asm("mfs r31, rmsr") ; \
	asm("swi r31,r12, 128") ; 

/**
 * Restore all the registers at location pointed by scontext.
 * Check the state of the process 
 * If state = PROC_NEW,	jump to the start address (r15) of the process.
 */
#define RESTORE_CONTEXT( scontext )	\
	asm("lwi r12, r0, scontext") ; \
	asm("lwi r1,r12, 4") ; \
	asm("lwi r2,r12, 8") ; \
	asm("lwi r3,r12, 12") ; \
	asm("lwi r4,r12, 16") ; \
	asm("lwi r5,r12, 20") ; \
	asm("lwi r6,r12, 24") ; \
	asm("lwi r7,r12, 28") ; \
	asm("lwi r8,r12, 32") ; \
	asm("lwi r9,r12, 36") ; \
	asm("lwi r10,r12, 40") ; \
	asm("lwi r11,r12, 44") ; \
	asm("lwi r13,r12, 52") ; \
	asm("lwi r14,r12, 56") ; \
	asm("lwi r15,r12, 60") ; \
	asm("lwi r16,r12, 64") ; \
	asm("lwi r17,r12, 68") ; \
	asm("lwi r18,r12, 72") ; \
	asm("lwi r19,r12, 76") ; \
	asm("lwi r20,r12, 80") ; \
	asm("lwi r21,r12, 84") ; \
	asm("lwi r22,r12, 88") ; \
	asm("lwi r23,r12, 92") ; \
	asm("lwi r24,r12, 96") ; \
	asm("lwi r25,r12, 100") ; \
	asm("lwi r26,r12, 104") ; \
	asm("lwi r27,r12, 108") ; \
	asm("lwi r28,r12, 112") ; \
	asm("lwi r29,r12, 116") ; \
	asm("lwi r30,r12, 120") ; \
	asm("lwi r31,r12, 128") ; \
	asm("mts rmsr, r31") ; \
	asm("lwi r31,r12, 124") ; \
	asm("bnei r11, 12") ; \
	asm("rtid r15,0") ; \
	asm("nop") ;		

/**
 * Assign the _stack value to kernel_sp 	   
 */
#define GET_KERNEL_SP	\
	asm("la r18, r0, _stack") ;	\
	asm("swi r18, r0, kernel_sp") ;


/**
 * Save all the registers on the stack
 */
#define SAVE_ALL	\
	addi r1,r1, -128;	\
	swi r2,r1, 4;	\
	swi r3,r1, 8;	\
	swi r4,r1, 12;	\
	swi r5,r1, 16;	\
	swi r6,r1, 20;	\
	swi r7,r1, 24;	\
	swi r8,r1, 28;	\
	swi r9,r1, 32;	\
	swi r10,r1, 36;	\
	swi r11,r1, 40; \
	swi r12,r1, 44; \
	swi r13,r1, 48; \
	swi r14,r1, 52; \
	swi r15,r1, 56; \
  	swi r16,r1, 60; \
	swi r17,r1, 64; \
	swi r18,r1, 68; \
	swi r19,r1, 72; \
	swi r20,r1, 76; \
	swi r21,r1, 80; \
	swi r22,r1, 84; \
	swi r23,r1, 88; \
	swi r24,r1, 92; \
	swi r25,r1, 96; \
	swi r26,r1, 100; \
	swi r27,r1, 104; \
	swi r28,r1, 108; \
	swi r29,r1, 112; \
	swi r30,r1, 116; \
	swi r31,r1, 120; \
	mfs r31, rmsr;	 \
	swi r31,r1, 124 ;

/**
 * Restore all the registers on the stack
 */
#define RESTORE_ALL	\
	lwi r2,r1, 4;	\
	lwi r3,r1, 8;	\
	lwi r4,r1, 12;	\
	lwi r5,r1, 16;	\
	lwi r6,r1, 20;	\
	lwi r7,r1, 24;	\
	lwi r8,r1, 28;	\
	lwi r9,r1, 32;	\
	lwi r10,r1, 36;	\
	lwi r11,r1, 40; \
	lwi r12,r1, 44; \
	lwi r13,r1, 48; \
	lwi r14,r1, 52; \
	lwi r15,r1, 56; \
	lwi r16,r1, 60; \
	lwi r17,r1, 64; \
	lwi r18,r1, 68; \
	lwi r19,r1, 72; \
	lwi r20,r1, 76; \
	lwi r21,r1, 80; \
	lwi r22,r1, 84; \
	lwi r23,r1, 88; \
	lwi r24,r1, 92; \
	lwi r25,r1, 96; \
	lwi r26,r1, 100; \
	lwi r27,r1, 104; \
	lwi r28,r1, 108; \
	lwi r29,r1, 112; \
	lwi r30,r1, 116; \
	lwi r31,r1, 124; \
	mts rmsr, r31;	 \
	lwi r31,r1, 120; \
	addi r1,r1,128

/**
 * Branch to the System call handler. The syscall number is placed in 
 * register r18.
 */
#define JMP_SYSCALL_HANDLER( syscall_num )	\
	asm("addi r18, r0, %0" : : "I" (syscall_num) ) ; \
	asm("braid 0x8" ) ; \
	asm("nop") ;

#endif
