#ifndef __L4__IA64__SYSCALLS_H__
#define __L4__IA64__SYSCALLS_H__
#include __L4_INC_ARCH(vregs.h)
#include __L4_INC_ARCH(runconv.h)
#include __L4_INC_ARCH(specials.h)
#include <l4/message.h>
#include <l4/kdebug.h>
#define __L4_ASM_ENTER_KDEBUG(str) \
"{.mlx \n" \
" break.m 0x3 \n" \
" movl r0 = 9f ;; \n" \
"} \n" \
" .rodata \n" \
"9: stringz " #str " \n" \
" .previous \n"
#define __L4_ASM_CALL(func) \
" add r31 = -40, sp \n" \
" add r30 = -32, sp \n" \
" add sp = -40, sp \n" \
" mov r29 = ar.unat \n" \
" mov r28 = rp \n" \
" mov r27 = ar.pfs \n" \
" mov r26 = ar.fpsr \n" \
" ;; \n" \
" st8 [r31] = r29, 16 \n" \
" st8 [r30] = r28, 16 \n" \
" ;; \n" \
" st8 [r31] = r27 \n" \
" st8 [r30] = r26 \n" \
" \n" \
" br.call.sptk.few rp = " #func " \n" \
" \n" \
" mov r31 = sp \n" \
" add r30 = 8, sp \n" \
" ;; \n" \
" ld8 r29 = [r31], 16 \n" \
" ld8 r28 = [r30], 16 \n" \
" ;; \n" \
" ld8 r27 = [r31] \n" \
" ld8 r26 = [r30] \n" \
" ;; \n" \
" mov ar.unat = r29 \n" \
" mov rp = r28 \n" \
" mov ar.pfs = r27 \n" \
" mov ar.fpsr = r26 \n" \
" add sp = 40, sp \n" \
" ;; \n"
L4_INLINE void * L4_KernelInterface (L4_Word_t *ApiVersion,
L4_Word_t *ApiFlags,
L4_Word_t *KernelId)
{
register void * base_address asm ("r8");
register L4_Word_t api_version asm ("r9");
register L4_Word_t api_flags asm ("r10");
register L4_Word_t kernel_id asm ("r11");
__asm__ __volatile__ (
"/* L4_KernelInterface() */ \n"
"{ .mlx \n"
" break.m 0x1face \n"
" movl r0 = 0x0 ;; \n"
"} \n"
:
"=r" (base_address),
"=r" (api_version),
"=r" (api_flags),
"=r" (kernel_id));
*ApiVersion = api_version;
*ApiFlags = api_flags;
*KernelId = kernel_id;
return base_address;
}
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)
{
register L4_ThreadId_t r_dest asm ("r14") = dest;
register L4_Word_t r_control asm ("r15") = control;
register L4_Word_t r_sp asm ("r16") = sp;
register L4_Word_t r_ip asm ("r17") = ip;
register L4_Word_t r_flags asm ("r18") = flags;
register L4_Word_t r_userhandle asm ("r19") = UserDefHandle;
register L4_ThreadId_t r_pager asm ("r20") = pager;
__asm__ __volatile__ (
"/* L4_ExchangeRegisters() */ \n"
__L4_ASM_CALL(__L4_ExchangeRegisters)
:
"+r" (r_dest),
"+r" (r_control),
"+r" (r_sp),
"+r" (r_ip),
"+r" (r_flags),
"+r" (r_userhandle),
"+r" (r_pager)
:
:
__L4_CLOBBER_CALLER_REGS ("r8","r9","r10","r11"));
*old_control = r_control;
*old_sp = r_sp;
*old_ip = r_ip;
*old_flags = r_flags;
*old_UserDefHandle = r_userhandle;
*old_pager = r_pager;
return r_dest;
}
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)
{
register L4_Word_t result asm ("r8");
register L4_ThreadId_t r_dest asm ("r14") = dest;
register L4_ThreadId_t r_SpaceSpecifier asm ("r15") = SpaceSpecifier;
register L4_ThreadId_t r_Scheduler asm ("r16") = Scheduler;
register L4_ThreadId_t r_Pager asm ("r17") = Pager;
register void * r_UtcbLocation asm ("r18") = UtcbLocation;
__asm__ __volatile__ (
"/* L4_ThreadControl() */ \n"
__L4_ASM_CALL(__L4_ThreadControl)
:
"=r" (result),
"+r" (r_dest),
"+r" (r_SpaceSpecifier),
"+r" (r_Scheduler),
"+r" (r_Pager),
"+r" (r_UtcbLocation)
:
:
__L4_CLOBBER_CALLER_REGS ("r9","r10","r11","r19","r20"));
return result;
}
L4_INLINE L4_Clock_t L4_SystemClock (void)
{
register L4_Clock_t clock asm ("r8");
__asm__ __volatile__ (
"/* L4_SystemClock() */\n"
__L4_ASM_CALL(__L4_SystemClock)
:
"=r" (clock.raw)
:
:
__L4_CLOBBER_CALLER_REGS ("r9","r10","r11",
"r14","r15","r16","r17","r18","r19","r20"));
return clock;
}
L4_INLINE void L4_ThreadSwitch (L4_ThreadId_t dest)
{
register L4_ThreadId_t r_dest asm ("r14") = dest;
__asm__ __volatile__ (
"/* L4_ThreadSwitch() */\n"
__L4_ASM_CALL(__L4_ThreadSwitch)
:
"+r" (r_dest)
:
:
__L4_CLOBBER_CALLER_REGS ("r8","r9","r10","r11",
"r15","r16","r17","r18","r19","r20"));
}
L4_INLINE L4_Word_t L4_Schedule (L4_ThreadId_t dest,
L4_Word_t TimeCtrl,
L4_Word_t ProcessorCtrl,
L4_Word_t prio,
L4_Word_t PreemptionCtrl,
L4_Word_t * old_TimeCtrl)
{
register L4_Word_t result asm ("r8");
register L4_Word_t ret_TimeCtrl asm ("r9");
register L4_ThreadId_t r_dest asm ("r14") = dest;
register L4_Word_t r_TimeCtrl asm ("r15") = TimeCtrl;
register L4_Word_t r_ProcessorCtrl asm ("r16") = ProcessorCtrl;
register L4_Word_t r_prio asm ("r17") = prio;
register L4_Word_t r_PreemptionCtrl asm ("r18") = PreemptionCtrl;
__asm__ __volatile__ (
"/* L4_Schedule() */ \n"
__L4_ASM_CALL(__L4_Schedule)
:
"=r" (result),
"=r" (ret_TimeCtrl),
"+r" (r_dest),
"+r" (r_TimeCtrl),
"+r" (r_ProcessorCtrl),
"+r" (r_prio),
"+r" (r_PreemptionCtrl)
:
:
__L4_CLOBBER_CALLER_REGS ("r10","r11","r19","r20"));
*old_TimeCtrl = ret_TimeCtrl;
return result;
}
L4_INLINE L4_MsgTag_t L4_Ipc (L4_ThreadId_t to,
L4_ThreadId_t FromSpecifier,
L4_Word_t Timeouts,
L4_ThreadId_t * from)
{
register L4_ThreadId_t r_to asm ("r14") = to;
register L4_ThreadId_t r_FromSpecifier asm ("r15") = FromSpecifier;
register L4_Word_t r_Timeouts asm ("r16") = Timeouts;
register L4_ThreadId_t ret_from asm ("r9");
L4_Word_t * mrs = __L4_IA64_Utcb () + __L4_TCB_MR_OFFSET;
register L4_Word_t mr0 asm ("out0");
register L4_Word_t mr1 asm ("out1");
register L4_Word_t mr2 asm ("out2");
register L4_Word_t mr3 asm ("out3");
register L4_Word_t mr4 asm ("out4");
register L4_Word_t mr5 asm ("out5");
register L4_Word_t mr6 asm ("out6");
register L4_Word_t mr7 asm ("out7");
L4_MsgTag_t tag;
L4_Word_t ar_lc, ar_ec;
__asm__ __volatile__ (" ;; \n"
" mov %0 = ar.lc \n"
" mov %1 = ar.ec \n"
:
"=r" (ar_lc), "=r" (ar_ec));
if (! L4_IsNilThread (to))
{
r_to = to;
r_FromSpecifier = FromSpecifier;
r_Timeouts = Timeouts;
mr0 = mrs[0];
mr1 = mrs[1];
mr2 = mrs[2];
mr3 = mrs[3];
mr4 = mrs[4];
mr5 = mrs[5];
mr6 = mrs[6];
mr7 = mrs[7];
__asm__ __volatile__ (
"/* L4_Ipc() */\n"
__L4_ASM_CALL (__L4_Ipc)
:
"=r" (mr0), "=r" (mr1), "=r" (mr2), "=r" (mr3),
"=r" (mr4), "=r" (mr5), "=r" (mr6), "=r" (mr7),
"=r" (ret_from),
"+r" (r_to), "+r" (r_FromSpecifier), "+r" (r_Timeouts)
:
"0" (mr0), "1" (mr1), "2" (mr2), "3" (mr3),
"4" (mr4), "5" (mr5), "6" (mr6), "7" (mr7)
:
"r2", "r3", "r8", "r10", "r11",
"r17", "r18", "r19", "r20", "r21", "r22",
"r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
__L4_CALLER_SAVED_FP_REGS, __L4_CALLER_SAVED_PREDICATE_REGS,
__L4_CALLER_SAVED_BRANCH_REGS, __L4_CALLEE_SAVED_REGS);
}
else
{
r_to = to;
r_FromSpecifier = FromSpecifier;
r_Timeouts = Timeouts;
__asm__ __volatile__ (
"/* L4_Ipc() */\n"
__L4_ASM_CALL (__L4_Ipc)
:
"=r" (mr0), "=r" (mr1), "=r" (mr2), "=r" (mr3),
"=r" (mr4), "=r" (mr5), "=r" (mr6), "=r" (mr7),
"=r" (ret_from),
"+r" (r_to), "+r" (r_FromSpecifier), "+r" (r_Timeouts)
:
:
"r2", "r3", "r8", "r10", "r11",
"r17", "r18", "r19", "r20", "r21", "r22",
"r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
__L4_CALLER_SAVED_FP_REGS, __L4_CALLER_SAVED_PREDICATE_REGS,
__L4_CALLER_SAVED_BRANCH_REGS, __L4_CALLEE_SAVED_REGS);
}
if (! L4_IsNilThread (FromSpecifier))
{
*from = ret_from;
mrs[1] = mr1;
mrs[2] = mr2;
mrs[3] = mr3;
mrs[4] = mr4;
mrs[5] = mr5;
mrs[6] = mr6;
mrs[7] = mr7;
}
__asm__ __volatile__ (" mov ar.lc = %0 \n"
" mov ar.ec = %1 \n"
:
:
"r" (ar_lc), "r" (ar_ec));
tag.raw = mr0;
return tag;
}
L4_INLINE L4_MsgTag_t L4_Lipc (L4_ThreadId_t to,
L4_ThreadId_t FromSpecifier,
L4_Word_t Timeouts,
L4_ThreadId_t * from)
{
return L4_Ipc (to, FromSpecifier, Timeouts, from);
}
L4_INLINE void L4_Unmap (L4_Word_t control)
{
register L4_Word_t r_control asm ("r14") = control;
register L4_Word_t mr0 asm ("out0");
register L4_Word_t mr1 asm ("out1");
register L4_Word_t mr2 asm ("out2");
register L4_Word_t mr3 asm ("out3");
register L4_Word_t mr4 asm ("out4");
register L4_Word_t mr5 asm ("out5");
register L4_Word_t mr6 asm ("out6");
register L4_Word_t mr7 asm ("out7");
L4_Word_t * mrs = __L4_IA64_Utcb () + __L4_TCB_MR_OFFSET;
mr0 = mrs[0];
mr1 = mrs[1];
mr2 = mrs[2];
mr3 = mrs[3];
mr4 = mrs[4];
mr5 = mrs[5];
mr6 = mrs[6];
mr7 = mrs[7];
__asm__ __volatile__ (
"/* L4_Unmap() */\n"
__L4_ASM_CALL(__L4_Unmap)
:
"=r" (mr0), "=r" (mr1), "=r" (mr2), "=r" (mr3),
"=r" (mr4), "=r" (mr5), "=r" (mr6), "=r" (mr7),
"+r" (r_control)
:
"0" (mr0), "1" (mr1), "2" (mr2), "3" (mr3),
"4" (mr4), "5" (mr5), "6" (mr6), "7" (mr7)
:
__L4_CLOBBER_CALLER_REGS_NOOUT ("r8", "r9", "r10", "r11",
"r15", "r16", "r17", "r18",
"r19", "r20"));
mrs[0] = mr0;
mrs[1] = mr1;
mrs[2] = mr2;
mrs[3] = mr3;
mrs[4] = mr4;
mrs[5] = mr5;
mrs[6] = mr6;
mrs[7] = mr7;
}
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)
{
register L4_Word_t result asm ("r8");
register L4_Word_t ret_control asm ("r9");
register L4_ThreadId_t r_space asm ("r14") = SpaceSpecifier;
register L4_Word_t r_control asm ("r15") = control;
register L4_Fpage_t r_kiparea asm ("r16") = KernelInterfacePageArea;
register L4_Fpage_t r_utcbarea asm ("r17") = UtcbArea;
register L4_ThreadId_t r_redirector asm ("r18") = redirector;
__asm__ __volatile__ (
"/* L4_SpaceControl() */ \n"
__L4_ASM_CALL(__L4_SpaceControl)
:
"=r" (result),
"=r" (ret_control),
"+r" (r_space),
"+r" (r_control),
"+r" (r_kiparea),
"+r" (r_utcbarea),
"+r" (r_redirector)
:
:
__L4_CLOBBER_CALLER_REGS ("r10","r11","r19","r20"));
*old_control = ret_control;
return result;
}
L4_INLINE L4_Word_t L4_ProcessorControl (L4_Word_t ProcessorNo,
L4_Word_t InternalFrequency,
L4_Word_t ExternalFrequency,
L4_Word_t voltage)
{
L4_KDB_Enter ("ProcessorControl");
return 0;
}
L4_INLINE L4_Word_t L4_MemoryControl (L4_Word_t control,
const L4_Word_t * attributes)
{
register L4_Word_t result asm ("r8");
register L4_Word_t r_ctrl asm ("r14") = control;
register L4_Word_t r_att0 asm ("r15") = attributes[0];
register L4_Word_t r_att1 asm ("r16") = attributes[1];
register L4_Word_t r_att2 asm ("r17") = attributes[2];
register L4_Word_t r_att3 asm ("r18") = attributes[3];
register L4_Word_t mr0 asm ("out0");
register L4_Word_t mr1 asm ("out1");
register L4_Word_t mr2 asm ("out2");
register L4_Word_t mr3 asm ("out3");
register L4_Word_t mr4 asm ("out4");
register L4_Word_t mr5 asm ("out5");
register L4_Word_t mr6 asm ("out6");
register L4_Word_t mr7 asm ("out7");
L4_Word_t * mrs = __L4_IA64_Utcb () + __L4_TCB_MR_OFFSET;
mr0 = mrs[0];
mr1 = mrs[1];
mr2 = mrs[2];
mr3 = mrs[3];
mr4 = mrs[4];
mr5 = mrs[5];
mr6 = mrs[6];
mr7 = mrs[7];
__asm__ __volatile__ (
"/* L4_MemoryControl */ \n"
__L4_ASM_CALL(__L4_MemoryControl)
:
"=r" (result),
"+r" (mr0), "+r" (mr1), "+r" (mr2), "+r" (mr3),
"+r" (mr4), "+r" (mr5), "+r" (mr6), "+r" (mr7),
"+r" (r_ctrl),
"+r" (r_att0),
"+r" (r_att1),
"+r" (r_att2),
"+r" (r_att3)
:
:
__L4_CLOBBER_CALLER_REGS_NOOUT ("r9", "r10", "r11", "r19","r20"));
return result;
}
L4_INLINE L4_Word_t L4_PAL_Call (L4_Word_t idx,
L4_Word_t a1, L4_Word_t a2, L4_Word_t a3,
L4_Word_t *r1, L4_Word_t *r2, L4_Word_t *r3)
{
register L4_Word_t status asm ("r8");
register L4_Word_t ret1 asm ("r9");
register L4_Word_t ret2 asm ("r10");
register L4_Word_t ret3 asm ("r11");
register L4_Word_t out0 asm ("r28") = idx;
register L4_Word_t out1 asm ("r29") = a1;
register L4_Word_t out2 asm ("r30") = a2;
register L4_Word_t out3 asm ("r31") = a3;
__asm__ __volatile__ (
"/* L4_PAL_Call */ \n"
__L4_ASM_CALL(__L4_PAL_Call)
:
"=r" (status),
"=r" (ret1),
"=r" (ret2),
"=r" (ret3),
"+r" (out0),
"+r" (out1),
"+r" (out2),
"+r" (out3)
:
:
"r2", "r3", "r14", "r15", "r16", "r17", "r18", "r19",
"r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",
"out4", "out5", "out6", "out7",
__L4_CALLER_SAVED_FP_REGS, __L4_CALLER_SAVED_PREDICATE_REGS,
__L4_CALLER_SAVED_BRANCH_REGS, "ar.pfs");
*r1 = ret1;
*r2 = ret2;
*r3 = ret3;
return status;
}
L4_INLINE L4_Word_t L4_SAL_Call (L4_Word_t idx,
L4_Word_t a1, L4_Word_t a2, L4_Word_t a3,
L4_Word_t a4, L4_Word_t a5, L4_Word_t a6,
L4_Word_t *r1, L4_Word_t *r2, L4_Word_t *r3)
{
register L4_Word_t status asm ("r8");
register L4_Word_t ret1 asm ("r9");
register L4_Word_t ret2 asm ("r10");
register L4_Word_t ret3 asm ("r11");
register L4_Word_t out0 asm ("out0") = idx;
register L4_Word_t out1 asm ("out1") = a1;
register L4_Word_t out2 asm ("out2") = a2;
register L4_Word_t out3 asm ("out3") = a3;
register L4_Word_t out4 asm ("out4") = a4;
register L4_Word_t out5 asm ("out5") = a5;
register L4_Word_t out6 asm ("out6") = a6;
__asm__ __volatile__ (
"/* L4_SAL_Call */ \n"
__L4_ASM_CALL(__L4_SAL_Call)
:
"=r" (status),
"=r" (ret1),
"=r" (ret2),
"=r" (ret3),
"+r" (out0),
"+r" (out1),
"+r" (out2),
"+r" (out3),
"+r" (out4),
"+r" (out5),
"+r" (out6)
:
:
__L4_CLOBBER_CALLER_REGS_NOOUT ("r14", "r15", "r16", "r17",
"r18", "r19", "r20", "out7"));
*r1 = ret1;
*r2 = ret2;
*r3 = ret3;
return status;
}
#endif