gpt4 book ai didi

c++ - 直接跳转到另一个C++函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:46:55 25 4
gpt4 key购买 nike

我正在将一个小型学术操作系统从 TriCore 移植到 ARM Cortex(Thumb-2 指令集)。为了使调度程序工作,有时我需要直接跳转到另一个函数而不修改堆栈或链接寄存器。

在 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++ 函数时保持堆栈和 CSA 不变 superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to).

现在我需要在 ARM Cortex(或者更确切地说,对于 arm-none-linux-gnueabi-g++)上有一个等效的行为,即生成一个 B(又名 BRANCH)指令而不是 BLX(又名 BRANCH,带有链接和交换)。但是 arm-g++ 没有 interrupt_handler 属性,我找不到任何等效的属性。

所以我尝试求助于 asm volatile 并直接编写 asm 代码:​​

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 中(我查看了一个位,但没有发现任何提示)。

最佳答案

链接错误是由于试图使用分支指令跳转到一个指针引起的。这会生成类似 b r6 的代码,但无法链接,因为 r6 不是符号。将分支指令更改为mov pc,%0,您应该会得到正确的跳转。

正如我在评论中提到的,ARM 中断处理程序是使用 interrupt 属性声明的,但正如您所发现的那样,这并不影响它们的调用方式。我猜这是一个特定于平台的技巧,恰好在 TriCore 上做了正确的事情。

您可以尝试使用 GCC 的扩展语法 register int reg0 asm("r0") = a1; 而不是 volatile mov 指令在特定寄存器中声明变量。这可能允许编译器生成更好的代码。

关于c++ - 直接跳转到另一个C++函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2539555/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com