ARM系统调用作为c ++模板

时间:2014-03-24 19:07:31

标签: c++ templates arm inline-assembly system-calls

我需要在newlib存根中调用一些系统调用,而当前的实现使用的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;
}

现在我可以打电话给malloc使用

void *ptr = syscall<SYS_MALLOC, void*>(0x1000);

分配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;
}

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

syscall<FWRITE, int>(ptr, 1, len, f)

但不知何故,r0设为1,r1设为ptr ...... 我也试过没有优化的编译,只是寄存器的顺序改变了一点,但它仍然是错误的顺序。我知道我可以做“mov r0,%[param1]”等但这会阻止优化,从而导致代码变慢。

它是GCC中的一个错误(4.8.2)还是我忽略了什么?

1 个答案:

答案 0 :(得分:4)

这是bug 33661,相当陈旧。几年前我自己遇到过它。