我從TriCore移植到ARM Cortex(Thumb-2指令集)的小型學術操作系統。爲了讓調度程序工作,我有時需要直接跳轉到另一個函數,而無需修改堆棧或鏈接寄存器。直接跳轉到另一個C++函數
在三核(或者說,上的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)
時,堆棧和CSA保持不變。
現在我需要上的ARM Cortex等效行爲(或者說,對於臂-NONE-Linux的gnueabi-G ++),即產生一個B
(又名BRANCH)指令的,而不是BLX
(又名BRANCH與鏈接和交換) 。但是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
中(我查看了一下,但沒有找到任何提示)。
是a1,a2,a3指針嗎?嘗試將它們轉換爲'(void *)' – osgx 2010-03-29 16:33:27
ARM中斷處理程序的屬性是'interrupt'。請參閱http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html – 2010-03-29 16:45:47
@Mike:nope,該屬性仍會生成一個「BLX」指令... – orithena 2010-03-29 16:48:12