Ich portiere ein kleines akademisches Betriebssystem von TriCore zu ARM Cortex (Thumb-2 Befehlssatz). Damit der Scheduler funktioniert, muss ich manchmal direkt zu einer anderen Funktion springen, ohne den Stack oder das Link-Register zu ändern.Direkt zu einer anderen C++ Funktion wechseln
Auf TriCore (oder vielmehr auf tricore-g ++), diese Vorlage Wrapper (für all drei Argument-Funktion) arbeitet:
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);
Dies würde den Assemblerbefehl J
(aka JUMP) erzeugt statt von CALL
, wobei der Stapel und CSAs unverändert bleiben, wenn zu der (ansonsten normalen) C++ Funktion superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to)
gesprungen wird.
Jetzt brauche ich ein gleichwertiges Verhalten auf ARM Cortex (oder, besser gesagt, für Arm-ohne-linux-gnueabi-g ++), dh erzeugen eine B
(aka Zweig) Anweisung statt BLX
(aka Zweig mit Link und Austausch) . Aber es gibt kein interrupt_handler
Attribut für arm-g ++ und ich konnte kein äquivalentes Attribut finden.
Also versuchte ich direkt an asm volatile
und Schreiben des asm-Code zurückgreifen:
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"
);
}
So weit, so gut, zumindest in meiner Theorie. Thumb-2 erfordert, dass Funktionsargumente in den Registern übergeben werden, d. H. In diesem Fall r0..r2, so dass es funktionieren sollte.
Aber dann stirbt der Linker mit
undefined reference to `r6'
auf der schließenden Klammer der asm-Anweisung ... und ich weiß nicht, was daraus zu machen. OK, ich bin nicht der Experte in C++, und die ASM-Syntax ist nicht sehr einfach ... Hat also jemand einen Tipp für mich? Ein Hinweis auf die korrekte __attribute__
für Arm-G ++ wäre eine Möglichkeit, ein Hinweis zur Behebung des Asm-Codes wäre ein anderer. Eine andere Möglichkeit wäre vielleicht, dem Compiler zu sagen, dass a1..a3
bereits in den Registern r0..r2
sein sollte, wenn die asm-Anweisung eingegeben wird (ich habe das ein wenig untersucht, aber keinen Hinweis gefunden).
Sind a1, a2, a3 ein Zeiger? versuche, sie in '(void *)' zu konvertieren – osgx
Das Attribut für einen ARM-Interrupt-Handler ist 'interrupt'. Siehe http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html –
@Mike: Nein, dieses Attribut erzeugt immer noch einen 'BLX' Befehl ... – orithena