#ifndef __L4__AMD64__SYSCALLS_H__
#define __L4__AMD64__SYSCALLS_H__
#include __L4_INC_ARCH(vregs.h)
#include __L4_INC_ARCH(specials.h)
#include <l4/message.h>
#include __L4_INC_ARCH(kdebug.h)
typedef struct {
    L4_Word_t rax;
    L4_Word_t rdx;
} __L4_Return_t;
L4_INLINE void * L4_KernelInterface (L4_Word_t *ApiVersion,
				     L4_Word_t *ApiFlags,
				     L4_Word_t *KernelId)
{
    void * base_address;
    __asm__ __volatile__ (
	"/* L4_KernelInterface() */ 			\n"
	"	lock; nop				\n"
	: 
	"=a" (base_address),
	"=c" (*ApiVersion),
	"=d" (*ApiFlags),
	"=S" (*KernelId)
	
	
	);
    return base_address;
}
typedef void (*__L4_Nop_t)(void);
typedef L4_Word_t (*__L4_ExchangeRegisters_t)( L4_Word_t, L4_Word_t, L4_Word_t,
	L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_ExchangeRegisters_t __L4_ExchangeRegisters;
L4_INLINE L4_ThreadId_t L4_ExchangeRegisters (L4_ThreadId_t dest,
					      L4_Word_t control,
					      L4_Word_t sp,
					      L4_Word_t ip,
					      L4_Word_t flags,
					      L4_Word_t UserDefHandle,
					      L4_ThreadId_t pager,
					      L4_Word_t *old_control,
					      L4_Word_t *old_sp,
					      L4_Word_t *old_ip,
					      L4_Word_t *old_flags,
					      L4_Word_t *old_UserDefhandle,
					      L4_ThreadId_t *old_pager)
{
    L4_ThreadId_t       result;
    
    L4_Word_t       dummy;
    struct {
	L4_Word_t       r8;
	L4_Word_t       r9;
	L4_Word_t       r10;
    } args;
    args.r8 = ip;
    args.r9 = flags;
    args.r10 = UserDefHandle;
    
    __asm__ __volatile__ (
	"/* L4_ExchangeRegisters */		\n"
	"movq (%[args]), %%r8			\n"
	"movq 8(%[args]), %%r9			\n"
	"movq 16(%[args]), %%r10		\n"
	"pushq %%rbp				\n"
	"pushq %[args]				\n"
	"callq *__L4_ExchangeRegisters		\n"
	"popq %[args]				\n"
	"popq %%rbp				\n"
	"movq %%r8,   (%[args])	 		\n"
	"movq %%r9,   8(%[args])	        \n"
	"movq %%r10, 16(%[args])		\n"
	: 
	"=a" (result),				
	"=c" (dummy),					
	"=d" (*old_sp),				
	"=S" (*old_control),			
	"=D" (*old_pager)			
	: 
	[dest]		"0" (dest),		
	[args]		"1" (&args),		
	[sp]		"2" (sp),		
	[control]	"3" (control),			
	[pager]		"4" (pager)		
	: 
	"memory", "rbx", "r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
    
  *old_ip = args.r8;
  *old_flags = args.r9;    
  *old_UserDefhandle = args.r10;
  
  return result;
}
typedef L4_Word_t (*__L4_ThreadControl_t)( L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_ThreadControl_t __L4_ThreadControl;
L4_INLINE L4_Word_t L4_ThreadControl (L4_ThreadId_t dest,
				      L4_ThreadId_t SpaceSpecifier,
				      L4_ThreadId_t Scheduler,
				      L4_ThreadId_t Pager,
				      void * UtcbLocation)
{
    L4_Word_t result = 0;
    L4_Word_t dummy = 0;
    
    __asm__ __volatile__ (
	"/* L4_ThreadControl */			\n"
	"movq %%rax, %%r8			\n"
	"movq %%rcx, %%r9			\n"
	"pushq %%rbp				\n"
	"callq *__L4_ThreadControl		\n"
	"popq %%rbp				\n"
	: 
	"=a" (result),				
	"=c" (dummy),					
	"=d" (dummy),				
	"=S" (dummy),				
	"=D" (dummy)				
	: 
	[spacespec]	"0" (SpaceSpecifier),	
	[utcblocation]	"1" (UtcbLocation),	
	[scheduler]	"2" (Scheduler),	
	[pager]		"3" (Pager),			
	[dest]		"4" (dest)		
	: 
	"memory", "rbx", "r8", "r9", "r11", "r12", "r13", "r14", "r15"
	);
  
  return result;
}
typedef L4_Clock_t (*__L4_SystemClock_t)( void );
extern __L4_SystemClock_t __L4_SystemClock;
L4_INLINE  L4_Clock_t L4_SystemClock (void)
{
    L4_Clock_t ret;
    
    __asm__ __volatile__ (
	"/* L4_SystemClock */			\n"
	"pushq %%rbp				\n"
	"callq *__L4_SystemClock		\n"
	"popq %%rbp				\n"
	: 
	"=a" (ret.raw)				
	: 
	[dest]		"0" (ret.raw)		
	: 
	  "memory", "rbx", "rcx",  "rdx", "rsi", "rdi", 
	"r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
    return ret;
}
typedef L4_Word_t (*__L4_ThreadSwitch_t)( L4_Word_t );
extern __L4_ThreadSwitch_t __L4_ThreadSwitch;
L4_INLINE void L4_ThreadSwitch (L4_ThreadId_t dest)
{
    L4_Word_t dummy;
    __asm__ __volatile__ (
	"/* L4_ThreadSwitch */			\n"
	"pushq %%rbp				\n"
	"callq *__L4_ThreadSwitch		\n"
	"popq %%rbp				\n"
	: 
	"=D" (dummy)				
	: 
	[dest]		"0" (dest)		
	: 
	"memory", "rax", "rbx", "rcx",  "rdx", "rsi", 
	"r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
}
typedef __L4_Return_t (*__L4_Schedule_t)( L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_Schedule_t __L4_Schedule;
L4_INLINE L4_Word_t  L4_Schedule (L4_ThreadId_t dest,
				  L4_Word_t TimeControl,
				  L4_Word_t ProcessorControl,
				  L4_Word_t prio,
				  L4_Word_t PreemptionControl,
				  L4_Word_t * old_TimeControl)
{
    L4_Word_t result = 0;
    L4_Word_t dummy = 0;
    
    __asm__ __volatile__ (
	"/* L4_Schedule */			\n"
	"movq %%rax, %%r8			\n"
	"movq %%rcx, %%r9			\n"
	"pushq %%rbp				\n"
	"callq *__L4_Schedule			\n"
	"popq %%rbp				\n"
	: 
	"=a" (*old_TimeControl),		
	"=c" (dummy),					
	"=d" (dummy),				
	"=S" (dummy),				
	"=D" (dummy)				
	: 
	[procontrol]	"0" (ProcessorControl),	
	[precontrol]	"1" (PreemptionControl),
	[tcontrol]	"2" (TimeControl),	
	[prio]		"3" (prio),			
	[dest]		"4" (dest)		
	: 
	"memory", "rbx","r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
  
  return result;
}
typedef L4_Word_t (*__L4_Ipc_t)( L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_Ipc_t __L4_Ipc;
L4_INLINE L4_MsgTag_t L4_Ipc (L4_ThreadId_t to,
			      L4_ThreadId_t FromSpecifier,
			      L4_Word_t Timeouts,
			      L4_ThreadId_t * from)
{
    L4_ThreadId_t result;
    L4_Word_t * utcb = __L4_X86_Utcb ();
    
    L4_Word_t dummy;
    
    __asm__ __volatile__ (
	"/* L4_Ipc() */				\n"
	"movq	%[timeouts], %%r8		\n"
	"movq	%%rcx, %%r9			\n"
	"movq	 8(%[utcb]), %%rax		\n" 
	"movq	16(%[utcb]), %%rbx		\n" 
	"movq	24(%[utcb]), %%r10		\n" 
	"movq	32(%[utcb]), %%r12		\n" 
	"movq	40(%[utcb]), %%r13		\n" 
	"movq	48(%[utcb]), %%r14		\n" 
	"movq	56(%[utcb]), %%r15		\n" 
	"pushq	%%rbp				\n"
	"callq	*__L4_Ipc			\n"
	"popq	%%rbp				\n"
	"movq	%%r10, 24(%[utcb]) 		\n" 
	"movq	%%r12, 32(%[utcb]) 		\n" 
	"movq	%%r13, 40(%[utcb]) 		\n" 
	"movq	%%r14, 48(%[utcb]) 		\n" 
	"movq	%%r15, 56(%[utcb]) 		\n" 
	"movq	%%r9, %%rcx			\n"
	: 
	"=a" (utcb[1]),				
	"=b" (utcb[2]),							
	"=c" (utcb[0]),					
	"=d" (dummy),				
	"=S" (result)				
	
	: 
	[to]		"4" (to),		
	[utcb]		"D" (utcb),		
	[from]		"3" (FromSpecifier),	
	[utcb0]		"2" (utcb[0]),		
	[timeouts]	"r" (Timeouts)		
	: 
	  "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
	);
    if (! L4_IsNilThread (FromSpecifier)) {
	*from = result;
    }
    
    return * (L4_MsgTag_t *) (&utcb[0]);
   
}
typedef L4_Word_t (*__L4_Lipc_t)( L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_Lipc_t __L4_Lipc;
L4_INLINE L4_MsgTag_t L4_Lipc (L4_ThreadId_t to,
			       L4_ThreadId_t FromSpecifier,
			       L4_Word_t Timeouts,
			       L4_ThreadId_t * from)
{
    L4_ThreadId_t result;
    L4_Word_t * utcb = __L4_X86_Utcb ();
    L4_Word_t dummy;
    
    __asm__ __volatile__ (
	"/* L4_Ipc() */				\n"
	"movq	%[timeouts], %%r8		\n"
	"movq	%[utcb0], %%r9			\n"
	"movq	 8(%[utcb]), %%rax		\n" 
	"movq	16(%[utcb]), %%rbx		\n" 
	"movq	24(%[utcb]), %%r10		\n" 
	"movq	32(%[utcb]), %%r12		\n" 
	"movq	40(%[utcb]), %%r13		\n" 
	"movq	48(%[utcb]), %%r14		\n" 
	"movq	56(%[utcb]), %%r15		\n" 
	"pushq	%%rbp				\n"
	"callq	*__L4_Ipc			\n"
	"popq	%%rbp				\n"
	"movq	%%r9, %[utcb0]			\n"
	"movq	%%r10, 24(%[utcb]) 		\n" 
	"movq	%%r12, 32(%[utcb]) 		\n" 
	"movq	%%r13, 40(%[utcb]) 		\n" 
	"movq	%%r14, 48(%[utcb]) 		\n" 
	"movq	%%r15, 56(%[utcb]) 		\n" 
	: 
	"=a" (utcb[1]),				
	"=b" (utcb[2]),							
	"=c" (utcb[0]),					
	"=d" (dummy),				
	"=S" (result)				
	
	: 
	[to]		"4" (to),		
	[utcb]		"D" (utcb),		
	[from]		"3" (FromSpecifier),	
	[utcb0]		"2" (utcb[0]),		
	[timeouts]	"r" (Timeouts)		
	: 
	  "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
	);
    if (! L4_IsNilThread (FromSpecifier)) {
	*from = result;
    }
    
    return * (L4_MsgTag_t *) (&utcb[0]);
   
}
typedef void (*__L4_Unmap_t)( L4_Word_t );
extern __L4_Unmap_t __L4_Unmap;
L4_INLINE void L4_Unmap (L4_Word_t control)
{   
    
    L4_Word_t * utcb = __L4_X86_Utcb ();
    L4_Word_t dummy;
    
    __asm__ __volatile__ (
	"/* L4_Unmap() */			\n"
	"movq	%[utcb0], %%r9			\n"
	"movq	24(%[utcb]), %%r10		\n" 
	"movq	32(%[utcb]), %%r12		\n" 
	"movq	40(%[utcb]), %%r13		\n" 
	"movq	48(%[utcb]), %%r14		\n" 
	"movq	56(%[utcb]), %%r15		\n" 
	"pushq	%%rbp				\n"
	"callq	*__L4_Unmap			\n"
	"popq	%%rbp				\n"
	"movq	%%r10, 24(%[utcb]) 		\n" 
	"movq	%%r12, 32(%[utcb]) 		\n" 
	"movq	%%r13, 40(%[utcb]) 		\n" 
	"movq	%%r14, 48(%[utcb]) 		\n" 
	"movq	%%r15, 56(%[utcb]) 		\n" 
	"movq	%%r9, %[utcb0]			\n"
	: 
	  "=a" (utcb[1]),				
	  "=b" (utcb[2]),							
	  "=c" (utcb[0]),					
	  "=d" (dummy),	        			
	  "=D" (utcb)	        			
	  
	: 
	  [utcb1]	"0" (utcb[1]),			
	  [utcb2]	"1" (utcb[2]),			
	  [utcb0]	"2" (utcb[0]),			
	  [control]	"3" (control),        		
	  [utcb]	"4" (utcb)	       		
	: 
	  "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
	);
}
typedef __L4_Return_t (*__L4_SpaceControl_t)( L4_Word_t, L4_Word_t, L4_Word_t,
	L4_Word_t, L4_Word_t );
extern __L4_SpaceControl_t __L4_SpaceControl;
L4_INLINE L4_Word_t L4_SpaceControl (L4_ThreadId_t SpaceSpecifier,
				     L4_Word_t control,
				     L4_Fpage_t KernelInterfacePageArea,
				     L4_Fpage_t UtcbArea,
				     L4_ThreadId_t redirector,
				     L4_Word_t *old_control)
{
    L4_Word_t result = 0;
    L4_Word_t dummy = 0;
    
    __asm__ __volatile__ (
	"/* L4_SpaceControl */			\n"
	"movq %%rax, %%r8			\n"
	"movq %%rcx, %%r9			\n"
	"pushq %%rbp				\n"
	"callq *__L4_SpaceControl		\n"
	"popq %%rbp				\n"
	: 
	"=a" (result),					
	"=c" (dummy), 	  	  		  		
	"=d" (*old_control),  	  		  	
	"=S" (dummy), 	  	  		  	
	"=D" (dummy)  	  	  		  	
	: 
	[utcbarea]	"0" (UtcbArea),			
	[redirector]	"1" (redirector),		
	[kiparea]	"2" (KernelInterfacePageArea),	
	[control]	"3" (control),				
	[spacespec]	"4" (SpaceSpecifier)		
	: 
	"memory", "rbx", "r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
  
  return result;
}
typedef L4_Word_t (*__L4_ProcessorControl_t)( L4_Word_t,  L4_Word_t,
	L4_Word_t, L4_Word_t );
extern __L4_ProcessorControl_t __L4_ProcessorControl;
L4_INLINE L4_Word_t L4_ProcessorControl (L4_Word_t ProcessorNo,
					 L4_Word_t InternalFrequency,
					 L4_Word_t ExternalFrequency,
					 L4_Word_t voltage)
{
    L4_Word_t result;
    L4_Word_t dummy;
    __asm__ __volatile__ (
	"/* L4_ProcessorControl */		\n"
	"movq %%rax, %%r8			\n"
	"pushq %%rbp				\n"
	"callq *__L4_ProcessorControl		\n"
	"popq %%rbp				\n"
	: 
	"=a" (result),				
	"=d" (dummy),				
	"=S" (dummy),				
	"=D" (dummy)				
	: 
	[voltage]	"0" (voltage),		
	[exfreq]	"1" (ExternalFrequency),
	[intfreq]	"2" (InternalFrequency),	
	[procno]	"3" (ProcessorNo)	
	: 
	"memory", "rcx", "rbx", "r8", "r9", "r10",  "r11", "r12", "r13", "r14", "r15"
	);
  
  return result;
}
typedef L4_Word_t (*__L4_MemoryControl_t)( L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t, L4_Word_t );
extern __L4_MemoryControl_t __L4_MemoryControl;
L4_INLINE L4_Word_t L4_MemoryControl (L4_Word_t control,
				 const L4_Word_t * attributes)
{
    L4_Word_t result;
    L4_Word_t dummy;
    L4_Word_t * utcb = __L4_X86_Utcb ();
    __asm__ __volatile__ (
	"/* L4_MemoryControl */			\n"
	"movq   (%[attributes]), %%rcx		\n"
	"movq  8(%[attributes]), %%rsi		\n"
	"movq 16(%[attributes]), %%r8		\n"
	"movq 24(%[attributes]), %%r11		\n"
	"movq	%[utcb0], %%r9			\n"
	"movq	16(%[utcb]), %%rbx		\n" 
	"movq	24(%[utcb]), %%r10		\n" 
	"movq	32(%[utcb]), %%r12		\n" 
	"movq	40(%[utcb]), %%r13		\n" 
	"movq	48(%[utcb]), %%r14		\n" 
	"movq	56(%[utcb]), %%r15		\n" 
	"pushq	%%rbp				\n"
	"callq	*__L4_MemoryControl		\n"
	"popq	%%rbp				\n"
	
	: 
	  "=a" (utcb[1]),				
	  "=b" (dummy),						
	  "=c" (utcb[0]),					
	  "=d" (result),	        		
	  "=D" (utcb)	        			
	  
	: 
	  [utcb1]	"0" (utcb[1]),			
	  [attributes]	"1" (attributes),		
	  [utcb0]	"2" (utcb[0]),			
	  [control]	"3" (control),        		
	  [utcb]	"4" (utcb)	       		
	: 
	  "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
	);
    return result;
}
#endif