ARM syscall作为C ++模板

Fab*_*ian 3 c++ templates arm system-calls inline-assembly

我需要在newlib存根中调用一些syscall,并且当前的实现使用C宏,随着时间的流逝,它们变得难以理解且令人恐惧。(而且我讨厌宏...)但是,我对C ++模板的实现仅对一个参数有效:

template <int nr, typename RETTYPE, typename PARAM1> 
    inline RETTYPE syscall(PARAM1 p1)
{
  register PARAM1 r0 asm("r0") = p1;
  asm volatile("svc %[nr]\n"
    : "=r" (r0)
    : [nr] "i" (nr), "r" (r0)
    : "memory", "r1", "r2", "r3", "r12", "lr");
  return (RETTYPE) r0;
}
Run Code Online (Sandbox Code Playgroud)

现在我可以使用

void *ptr = syscall<SYS_MALLOC, void*>(0x1000);
Run Code Online (Sandbox Code Playgroud)

分配0x1000字节。

我对四个参数的实现:

template <int nr, typename RETTYPE, typename PARAM1, typename PARAM2, typename PARAM3, typename PARAM4> 
    inline RETTYPE syscall(PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4)
{
  register PARAM1 r0 asm("r0") = p1;
  register PARAM2 r1 asm("r1") = p2;
  register PARAM3 r2 asm("r2") = p3;
  register PARAM4 r3 asm("r3") = p4;

  asm volatile("svc %[nr]\n"
    : "=r" (r0)
    : [nr] "i" (nr), "r" (r0), "r" (r1), "r" (r2), "r" (r3)
    : "memory", "r12", "lr");

  return (RETTYPE) r0;
}
Run Code Online (Sandbox Code Playgroud)

不起作用,“ swi”指令中寄存器的内容是任意的。GCC不知何故不再尊重“寄存器”变量。示例:我在svc指令上设置了一个断点并执行

syscall<FWRITE, int>(ptr, 1, len, f)
Run Code Online (Sandbox Code Playgroud)

但是以某种方式将r0设置为1,将r1设置为ptr ...我也尝试了不进行优化的编译,只是寄存器的顺序有所改变,但这仍然是错误的顺序。我知道我可以执行“ mov r0,%[param1]”等操作,但这会阻止优化,因此导致代码变慢。

是GCC(4.8.2)中的错误,还是我忽略了某些内容?

Tim*_*win 5

这是错误33661,它很旧。我几年前遇到了它。