2014-03-24 4 views
2

newlib 스텁에서 일부 syscalls를 호출해야하며 현재 구현에서는 읽을 수없고 끔찍한 C 매크로를 사용합니다.ARM syscall with C++ template

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

지금 내가 호출 할 수 있습니다 예를 들면 : 그러나, C++ 템플릿 내 구현이 하나 개의 매개 변수에 대한 작동 하는가 (그리고 난 ... 매크로를 싫어) 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는 더 이상 "레지스터"변수를 존중하지 않습니다. 예 : I는 SVC 명령어에 중단 점을 설정하고

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

실행 어쨌든 R0는 I는 최적화하지 않고 컴파일 시도 ... 를 ptr에하기 (1) 및 (R1)로 설정되어, 레지스터 막 순서 변경된 조금이지만 여전히 잘못된 순서입니다. 나는 "mov r0, % [param1]"등등을 할 수 있다는 것을 알고 있지만, 최적화를 막을 것이므로 느린 코드가됩니다.

GCC (4.8.2)의 버그입니까? 아니면 뭔가를 내려다 보았습니까?

+0

그 모든 것이 매우 어색해 보입니다. -/... 나는 C++ 코드에서'asm'을 피하려고합니다! –

+0

또한 'register' 키워드는 이미 잠시 동안 더 이상 사용되지 않습니다 ... –

+0

나를 믿으십시오, 할 수만 있다면, ;-) – Fabian

답변

4

이것은 bug 33661이며 다소 오래된 것입니다. 나는 몇 년 전에 나 자신과 마주 쳤다.

+0

임의의 SO 링크를 클릭하고 지원 컴파일러 버그에 대해 읽지 않는 매일 매일 인라인 조립을 위해 ... 너에게 모자를 벗고. – asveikau

+0

Great :-( 템플릿의 전역 비 템플릿 함수를 인라이닝 (inlining)하여 해결할 수 있습니다. – Fabian