我将一个小型的学术操作系统从TriCore移植到ARM Cortex(Thumb-2指令集)。为了使调度器正常工作,有时候需要直接跳转到另一个函数而不修改堆栈或链接寄存器。
在TriCore(或者更确切地说是tricore-g++)上,以下这个包装模板(适用于任意三个参数函数)可以起到作用:
这将生成汇编指令
在asm语句的闭合括号处...我不知道该怎么处理。好吧,我不是C++方面的专家,而且asm语法也不是很直观...所以有人能给我一个提示吗?一种方法是给出适用于arm-g++的正确__attribute__提示,另一种方法是修复asm代码。也许还有一种方法是告诉编译器当进入asm语句时,a1..a3应该已经在寄存器r0..r2中了(我研究过一些资料,但没有发现任何提示)。
在TriCore(或者更确切地说是tricore-g++)上,以下这个包装模板(适用于任意三个参数函数)可以起到作用:
template< class A1, class A2, class A3 >
inline void __attribute__((always_inline))
JUMP3( void (*func)( A1, A2, A3), A1 a1, A2 a2, A3 a3 ) {
typedef void (* __attribute__((interrupt_handler)) Jump3)( A1, A2, A3);
( (Jump3)func )( a1, a2, a3 );
}
//example for using the template:
JUMP3( superDispatch, this, me, next );
这将生成汇编指令
J
(又名JUMP),而不是CALL
,在跳转到(通常的)C++函数superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to)
时,堆栈和CSAs保持不变。
现在我需要在ARM Cortex(或者更确切地说,在arm-none-linux-gnueabi-g++上)实现相同的行为,即生成B
(又名BRANCH)指令,而不是BLX
(又名BRANCH with link and exchange)。但是在arm-g++中没有interrupt_handler
属性,我也找不到任何等效的属性。
因此,我尝试采用asm volatile
并直接编写汇编代码:
template< class A1, class A2, class A3 >
inline void __attribute__((always_inline))
JUMP3( void (*func)( A1, A2, A3), A1 a1, A2 a2, A3 a3 ) {
asm volatile (
"mov.w r0, %1;"
"mov.w r1, %2;"
"mov.w r2, %3;"
"b %0;"
:
: "r"(func), "r"(a1), "r"(a2), "r"(a3)
: "r0", "r1", "r2"
);
}
到目前为止,我的理论还算不错。Thumb-2需要将函数参数传递到寄存器中,即r0..r2在这种情况下,所以它应该可以工作。
但是,链接器出现了问题:
undefined reference to `r6'
在asm语句的闭合括号处...我不知道该怎么处理。好吧,我不是C++方面的专家,而且asm语法也不是很直观...所以有人能给我一个提示吗?一种方法是给出适用于arm-g++的正确__attribute__提示,另一种方法是修复asm代码。也许还有一种方法是告诉编译器当进入asm语句时,a1..a3应该已经在寄存器r0..r2中了(我研究过一些资料,但没有发现任何提示)。
(void*)
。 - osgxinterrupt
。请参阅http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html。 - Mike Seymourregister int reg0 asm("r0") = a1;
。http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html - Mike Seymour