Estoy portando un pequeño sistema operativo académico de TriCore a ARM Cortex (conjunto de instrucciones Thumb-2). Para que el programador funcione, a veces necesito SALTAR directamente a otra función sin modificar la pila ni el registro de enlace.Directamente Saltar a otra función de C++
En TriCore (o, más bien, en tricore-g ++), esta plantilla envoltorio (por cualquiera de las tres-argumento-función) funciona:
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);
Esto generaría la instrucción ensamblador J
(también conocido como SALTO) en lugar de CALL
, dejando sin cambios la pila y CSA al pasar a la función C++ (de lo contrario, normal) superDispatch(SchedulerImplementation* obj, Task::Id from, Task::Id to)
.
Ahora necesito un comportamiento equivalente en ARM Cortex (o, más bien, para el brazo-ninguno-linux-gnueabi-g ++), es decir, generar una instrucción de B
(aka RAMA) en lugar de BLX
(aka rama con enlace y cambio) . Pero no existe el atributo interrupt_handler
para arm-g ++ y no pude encontrar ningún atributo equivalente.
Así que trataron de recurrir a asm volatile
y escribir el código asm directamente:
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"
);
}
Hasta ahora, todo va bien, en mi teoría, al menos. Thumb-2 requiere que los argumentos de función se pasen en los registros, es decir, r0..r2 en este caso, por lo que debería funcionar.
Pero entonces el enlazador muere con
undefined reference to `r6'
en el soporte de cierre del estado asm ... y no sé qué hacer con él. OK, no soy el experto en C++, y la sintaxis asm no es muy sencilla ... ¿alguien me ha dado alguna pista? Una sugerencia al __attribute__
correcto para arm-g ++ sería de una manera, una sugerencia para arreglar el código de asm sería otra. Otra forma podría ser decirle al compilador que a1..a3
ya debería estar en los registros r0..r2
cuando se ingresa la declaración asm (investigué un poco, pero no encontré ninguna pista).
¿Están a1, a2, a3 un punteros? intente convertirlos a '(void *)' – osgx
El atributo para un manejador de interrupción ARM es 'interrupt'. Ver http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html –
@Mike: no, ese atributo aún genera una instrucción 'BLX' ... – orithena